如何创建一个圆形图标按钮在扑动?

如何创建类似于 FloatingActionButton的东西?

252003 次浏览

你可以使用 墨水井来做到这一点:

一种对触摸作出反应的材料的矩形区域。

下面的例子演示了如何使用 InkWell。你不需要 StatefulWidget来做这件事。我用它来改变计数的状态。

例如:

import 'package:flutter/material.dart';


class SettingPage extends StatefulWidget {
@override
_SettingPageState createState() => new _SettingPageState();
}


class _SettingPageState extends State<SettingPage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new InkWell(// this is the one you are looking for..........
onTap: () => setState(() => _count++),
child: new Container(
//width: 50.0,
//height: 50.0,
padding: const EdgeInsets.all(20.0),//I used some padding without fixed width and height
decoration: new BoxDecoration(
shape: BoxShape.circle,// You can use like this way or like the below line
//borderRadius: new BorderRadius.circular(30.0),
color: Colors.green,
),
child: new Text(_count.toString(), style: new TextStyle(color: Colors.white, fontSize: 50.0)),// You can add a Icon instead of text also, like below.
//child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
),//............
),
),
);
}
}

如果你想获得 splashColorhighlightColor的好处,包装 InkWell小部件使用 Material小部件与材质类型的圆。然后删除 Container小部件中的 decoration

结果:

enter image description here

我认为原材料按钮更适合。

RawMaterialButton(
onPressed: () {},
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)

你也可以像这样使用 RaisedButton (例如用于社交登录) :

FittedBox(
fit: BoxFit.scaleDown,
child: SizedBox(
height: 60,
width: 60,
child: RaisedButton(
child: Image.asset(
'assets/images/google_logo.png'),
shape: StadiumBorder(),
color: Colors.white,
onPressed: () {},
),
),
),

你可以很容易地做到以下几点:

FlatButton(
onPressed: () {


},
child: new Icon(
Icons.arrow_forward,
color: Colors.white,
size: 20.0,
),
shape: new CircleBorder(),
color: Colors.black12,
)

结果就是enter image description here

更新(使用新的 ElevatedButton)

  • ElevatedButton(定制较少)

    ElevatedButton(
    onPressed: () {},
    child: Icon(Icons.menu, color: Colors.white),
    style: ElevatedButton.styleFrom(
    shape: CircleBorder(),
    padding: EdgeInsets.all(20),
    backgroundColor: Colors.blue, // <-- Button color
    foregroundColor: Colors.red, // <-- Splash color
    ),
    )
    
  • ElevatedButton(具有更多定制)

    ElevatedButton(
    onPressed: () {},
    child: Icon(Icons.menu),
    style: ButtonStyle(
    shape: MaterialStateProperty.all(CircleBorder()),
    padding: MaterialStateProperty.all(EdgeInsets.all(20)),
    backgroundColor: MaterialStateProperty.all(Colors.blue), // <-- Button color
    overlayColor: MaterialStateProperty.resolveWith<Color?>((states) {
    if (states.contains(MaterialState.pressed)) return Colors.red; // <-- Splash color
    }),
    ),
    )
    
  • 使用 InkWell

    ClipOval(
    child: Material(
    color: Colors.blue, // Button color
    child: InkWell(
    splashColor: Colors.red, // Splash color
    onTap: () {},
    child: SizedBox(width: 56, height: 56, child: Icon(Icons.menu)),
    ),
    ),
    )
    

输出(最后两个相同) :

enter image description here

你只需要使用形状: CircleBorder()

MaterialButton(
onPressed: () {},
color: Colors.blue,
textColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 24,
),
padding: EdgeInsets.all(16),
shape: CircleBorder(),
)

enter image description here

我的贡献是:

import 'package:flutter/material.dart';


///
/// Create a circle button with an icon.
///
/// The [icon] argument must not be null.
///
class CircleButton extends StatelessWidget {
const CircleButton({
Key key,
@required this.icon,
this.padding = const EdgeInsets.all(8.0),
this.color,
this.onPressed,
this.splashColor,
})  : assert(icon != null),
super(key: key);


/// The [Icon] contained ny the circle button.
final Icon icon;


/// Empty space to inscribe inside the circle button. The [icon] is
/// placed inside this padding.
final EdgeInsetsGeometry padding;


/// The color to fill in the background of the circle button.
///
/// The [color] is drawn under the [icon].
final Color color;


/// The callback that is called when the button is tapped or otherwise activated.
///
/// If this callback is null, then the button will be disabled.
final void Function() onPressed;


/// The splash color of the button's [InkWell].
///
/// The ink splash indicates that the button has been touched. It
/// appears on top of the button's child and spreads in an expanding
/// circle beginning where the touch occurred.
///
/// The default splash color is the current theme's splash color,
/// [ThemeData.splashColor].
final Color splashColor;


@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);


return ClipOval(
child: Material(
type: MaterialType.button,
color: color ?? theme.buttonColor,
child: InkWell(
splashColor: splashColor ?? theme.splashColor,
child: Padding(
padding: padding,
child: icon,
),
onTap: onPressed,
),
),
);
}
}

此代码将帮助您添加按钮,而不需要任何不必要的填充,

RawMaterialButton(
elevation: 0.0,
child: Icon(Icons.add),
onPressed: (){},
constraints: BoxConstraints.tightFor(
width: 56.0,
height: 56.0,
),
shape: CircleBorder(),
fillColor: Color(0xFF4C4F5E),
),

试试这张牌

Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0), // half of height and width of Image
),
child: Image.asset(
"assets/images/home.png",
width: 50,
height: 50,
),
)
RawMaterialButton(
onPressed: () {},
constraints: BoxConstraints(),
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)

记下 constraints: BoxConstraints(),这是为了不允许在左边填充。

飞翔快乐! !

如果需要背景图像,可以使用 CircleAvatar 和 IconButton。

CircleAvatar(
backgroundImage: NetworkImage(userAvatarUrl),
)

按钮示例:

        CircleAvatar(
backgroundColor: Colors.blue,
radius: 20,
child: IconButton(
padding: EdgeInsets.zero,
icon: Icon(Icons.add),
color: Colors.white,
onPressed: () {},
),
),

enter image description here

我使用这一个,因为我喜欢定制的边界-半径和大小。

  Material( // pause button (round)
borderRadius: BorderRadius.circular(50), // change radius size
color: Colors.blue, //button colour
child: InkWell(
splashColor: Colors.blue[900], // inkwell onPress colour
child: SizedBox(
width: 35,height: 35, //customisable size of 'button'
child: Icon(Icons.pause,color: Colors.white,size: 16,),
),
onTap: () {}, // or use onPressed: () {}
),
),


Material( // eye button (customised radius)
borderRadius: BorderRadius.only(
topRight: Radius.circular(10.0),
bottomLeft: Radius.circular(50.0),),
color: Colors.blue,
child: InkWell(
splashColor: Colors.blue[900], // inkwell onPress colour
child: SizedBox(
width: 40, height: 40, //customisable size of 'button'
child: Icon(Icons.remove_red_eye,color: Colors.white,size: 16,),),
onTap: () {}, // or use onPressed: () {}
),
),

enter image description here

我创建了一个版本与正确的裁剪,高度和边界。随时自定义它。

Material(
elevation: 2.0,
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(50),
color: Colors.white,
child: InkWell(
onTap: () => null,
child: Container(
padding: EdgeInsets.all(9.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.blue, width: 1.4)),
child: Icon(
Icons.menu,
size: 22,
color: Colors.red,
),
),
),
)),

实际上有一个示例如何创建一个类似于 FloatingActionButton 的圆形 IconButton。

Ink(
decoration: const ShapeDecoration(
color: Colors.lightBlue,
shape: CircleBorder(),
),
child: IconButton(
icon: Icon(Icons.home),
onPressed: () {},
),
)

若要使用此代码示例创建本地项目,请运行:

flutter create --sample=material.IconButton.2 mysample
ClipOval(
child: MaterialButton(
color: Colors.purple,
padding: EdgeInsets.all(25.0),
onPressed: () {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0)),
child: Text(
'1',
style: TextStyle(fontSize: 30.0),
),
),
),

非物质解决方案:

final double floatingButtonSize = 60;
final IconData floatingButtonIcon;


TouchableOpacity(
onTap: () {
/// Do something...
},
activeOpacity: 0.7,
child: Container(
height: floatingButtonSize,
width: floatingButtonSize,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(floatingButtonSize / 2),
color: Theme.of(context).primaryColor,
boxShadow: [
BoxShadow(
blurRadius: 25,
color: Colors.black.withOpacity(0.2),
offset: Offset(0, 10),
)
],
),
child: Icon(
floatingButtonIcon ?? Icons.add,
color: Colors.white,
),
),
)

可以使用 GestureDetector 代替 TouchableOpacity 库。

使用电梯按钮:

          ElevatedButton(
onPressed: () {},
child: Icon(
Icons.add,
color: Colors.white,
size: 60.0,
),
style: ElevatedButton.styleFrom(
shape: CircleBorder(), primary: Colors.green),
)

下面的代码将创建一个半径为25的圆,并将其中的白色添加图标。如果用户也想要使用 click 方法,只需将 Container 小部件封装到 GestureDetector ()或 InkWell ()中即可实现。

Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(50 / 2),
),
child: Center(
child: Icon(
Icons.add,
color: Colors.white,
),
),
),

二零二一年

如果你需要它的平面(没有高度) ,因为扁平按钮现在是不推荐的。

TextButton(
onPressed: (){},
child: Icon(Icons.arrow_back),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.black26),
shape: MaterialStateProperty.all(const CircleBorder())),
);

“提升按钮”被破坏了, 现在你可以通过高举按钮来创建它。

ElevatedButton(
onPressed: () {},
child: Icon(Icons.add, color: Colors.white),
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(20),
primary: Colors.blue,
onPrimary: Colors.black,
),
)

enter image description here

用圆形就行了


MaterialButton(
onPressed: () {
print("Circle button pressed");
},
color: Colors.blue,
textColor: Colors.white,
child: Icon(
Icons.favorite,
size: 20,
),
padding: EdgeInsets.all(16),
//use this class Circleborder() for circle shape.
shape: const CircleBorder(),
)
Container(
width: 70.w,
height: 70.h,
alignment: AlignmentDirectional.topCenter,
child: MaterialButton(
onPressed: () {},
color: Color(0xff022C43),
textColor: Colors.white,
child: Icon(
Icons.arrow_forward,
size: 24,
),
padding: EdgeInsets.all(16),
shape: CircleBorder(),
)
)
Card(
elevation: 4.0,
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(150),
),
child: InkWell(
onTap: (){},
child: Container(
width: 40,
height: 40,
padding: const EdgeInsets.all(3.0),
decoration: const BoxDecoration(
shape: BoxShape.circle, color: backGroundColor),
child: Image.asset(imageUrl)),
)),

在 Flutter 有很多方法可以创建圆形图标按钮。下面的每个示例将使用不同的方法。

  1. 使用 ElevatedButton + Icon (推荐)
  2. 使用材质按钮
  3. ClipOval + 材质 + 墨水井 + 填充 + 图标
  4. IconButton + CircleAvatar
  5. 墨水 + 图标按钮

使用 ElevatedButton + 图标

ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
padding: const EdgeInsets.all(30)
),
child: const Icon(
Icons.add,
size: 50,
),
onPressed: () {},

),

产出: enter image description here

使用材质按钮

MaterialButton(
shape: const CircleBorder(),
color: Colors.red,
padding: const EdgeInsets.all(20),
onPressed: () {},
child: const Icon(
Icons.star,
size: 50,
color: Colors.yellow,
),

)

产出: enter image description here

ClipOval + 材质 + 墨水井 + 填充 + 图标

ClipOval(
child: Material(
color: Colors.blue,
child: InkWell(
onTap: () {},
child: const Padding(
padding: EdgeInsets.all(20),
child: Icon(
Icons.plus_one,
size: 50,
color: Colors.white,
),
),
),
),

)

产出: enter image description here

IconButton + CircleAvatar

CircleAvatar(
radius: 50,
backgroundColor: Colors.amber,
child: IconButton(
color: Colors.black,
padding: const EdgeInsets.all(20),
iconSize: 50,
icon: const Icon(Icons.shop),
onPressed: () {
// do something
}),

),

产出: enter image description here

墨水 + 图标按钮

Ink(
decoration:
const ShapeDecoration(
shape: CircleBorder(),
color: Colors.purple
),
child: IconButton(
icon: const Icon(Icons.arrow_back),
iconSize: 30,
color: Colors.white,
onPressed: () {},
),

)

产出: enter image description here