Tôi không thể tìm thấy bất kỳ ví dụ nào cho thấy cách tạo một vòng kết nối IconButton
tương tự như FloatingActionButton
. Bất cứ ai có thể đề xuất cách / những gì cần thiết để tạo một nút tùy chỉnh như thế FloatingActionButton
?
Tôi không thể tìm thấy bất kỳ ví dụ nào cho thấy cách tạo một vòng kết nối IconButton
tương tự như FloatingActionButton
. Bất cứ ai có thể đề xuất cách / những gì cần thiết để tạo một nút tùy chỉnh như thế FloatingActionButton
?
Câu trả lời:
Tôi nghĩ rằng RawMaterialButton phù hợp hơn.
RawMaterialButton(
onPressed: () {},
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap
constraints: BoxConstraints.expand(width: 42, height: 42),
Bạn có thể sử dụng InkWell để làm điều đó:
Diện tích hình chữ nhật của Vật liệu phản ứng với cảm ứng.
Ví dụ dưới đây trình bày cách sử dụng InkWell
. Lưu ý: bạn không cần StatefulWidget
phải làm điều đó. Tôi đã sử dụng nó để thay đổi trạng thái của số đếm.
Thí dụ:
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)),
),//............
),
),
);
}
}
Nếu bạn muốn hưởng lợi splashColor
, highlightColor
hãy bọc InkWell
tiện ích con bằng cách sử dụng Material
tiện ích con có vòng tròn loại material. Và sau đó xóa decoration
trong Container
widget.
Kết quả:
RawMaterialButton(
onPressed: () {},
constraints: BoxConstraints(),
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.pause,
size: 35.0,
),
padding: EdgeInsets.all(15.0),
shape: CircleBorder(),
)
lưu ý constraints: BoxConstraints()
, nó không cho phép đệm ở bên trái.
Hạnh phúc xốn xang !!
Nếu bạn cần hình nền, bạn có thể sử dụng CircleAvatar với IconButton. Đặt thuộc tính backgroundImage.
CircleAvatar(
backgroundImage: NetworkImage(userAvatarUrl),
)
Ví dụ với nút:
CircleAvatar(
backgroundColor: Colors.blue,
radius: 20,
child: IconButton(
padding: EdgeInsets.zero,
icon: Icon(Icons.add),
color: Colors.white,
onPressed: () {},
),
),
Trên thực tế, có một ví dụ về cách tạo một IconButton vòng tròn tương tự như FloatingActionButton.
Ink(
decoration: const ShapeDecoration(
color: Colors.lightBlue,
shape: CircleBorder(),
),
child: IconButton(
icon: Icon(Icons.home),
onPressed: () {},
),
)
Để tạo một dự án cục bộ với mẫu mã này, hãy chạy:
flutter create --sample=material.IconButton.2 mysample
Đóng góp của tôi:
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,
),
),
);
}
}
Tôi đã tạo một phiên bản với phần cắt, độ cao và đường viền chính xác. Hãy tùy chỉnh nó.
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,
),
),
),
)),
Bạn cũng có thể sử dụng RaisedButton với một hình ảnh bên trong (ví dụ: đăng nhập mạng xã hội) như thế này (cần có kích thước hộp với fittebox để đối chiếu hình ảnh với kích thước được chỉ định):
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: () {},
),
),
),
Tôi đã sử dụng cái này vì tôi thích tùy chỉnh bán kính và kích thước đường viền.
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: () {}
),
),
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),
),
),
),
Không phải giải pháp Vật liệu:
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,
),
),
)
Bạn có thể sử dụng GestureDetector thay vì thư viện TouchableOpacity.
Dùng thử thẻ này
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,
),
)