Card
Flutter Card 组件,卡片组件具有圆角和阴影,看起来有立体感。
构造函数
Card({
Key key,
this.color,
this.shadowColor,
this.elevation,
this.shape,
this.borderOnForeground = true,
this.margin,
this.clipBehavior,
this.child,
this.semanticContainer = true,
})
常用属性
color:颜色
color:Colors.blue[500],
elevation:阴影大小
elevation: elevation: 5.0,
shape:Card 的阴影效果
shape:const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(14.0))),
margin:外边距
margin: EdgeInsets.only(top: 10.0,bottom: 10.0,left: 10.0,right: 10.0)
child
child: Text("内容"),
listTile
const ListTile({
Key key,
Widget leading, //头部图片(显示在标题前)
Widget title, //标题
Widget subtitle, //副标题
Widget trailing, //尾部图标
bool isThreeLine = false, //是否 3 行显示
bool dense, //是否显示为紧凑模式(开启时整体条目会显示的更小)
VisualDensity visualDensity, //组件的视觉密度,通过调整它可以使得标准 Material 组件之间更加紧凑或疏远。例如:VisualDensity(horizontal: -4, vertical: -4)
EdgeInsetsGeometry contentPadding, //内边距
bool enabled = true, //是否可用(禁用点击事件)
GestureTapCallback onTap, //点击事件
GestureLongPressCallback onLongPress, //长按事件
bool selected = false, //选中状态(被选中后字体颜色与主题色一致,即 title、subtitle、secondary 是否采用 activeColor 的颜色)
Color focusColor,
Color hoverColor,
FocusNode focusNode, //焦点管理
bool autofocus = false, //自动获取焦点
})
-
leading 通常是个 Icon 或 CircleAvatar;title/subtitle 通常是 Text;trailing 通常是 Icon;
-
上面都是通常的用法,实际使用中 leading/title/subtitle/trailing 都可以是任何 widget,但建议采用通常的用法
-
title 只可单行显示,subtitle 根据 isThreeLine 决定;当不设置 subtitle 时(且 isThreeLine = false),整体条目会单行显示。
-
leading/trailing 小部件的高度会受到整体条目固定高度的限制,宽度不受限制。(整体条目的高度会根据 [是否有subtitle、isThreeLine、dense] 固定为 [48.0、56.0;64.0、72.0;76.0、88.0] 中的某固定值)
CheckBox和Switch
CheckBox
Switch
和复选框Checkbox
,它们都是继承自StatefulWidget
,但它们的选择状态属于用户数据,所以最好由父Widget来管理其选择状态。当用户点击Switch
或Checkbox
时,它们会触发onChanged
回调,我们可以在此回调中处理选择状态改变逻辑
CheckBox({
Key key,
@required bool value, //复选框的值
bool tristate: false, //为true时复选框会多一个值为null的状态,复选框内显示为横线
@required ValueChanged<bool> onChanged, //点击复选框的回调
Color activeColor, //选中时复选框的颜色
Color checkColor, //选中时对号的颜色
MaterialTapTargetSize materialTapTargetSize //有效点击区域的大小
})
Switch
value 当前开关状态 布尔值 onChanged 监听(开关状态改变时调用) activeColor 打开 状态 轨道 和 按钮颜色 activeTrackColor 打开 状态轨道颜色 inactiveThumbColor 关闭 状态按钮颜色 inactiveTrackColor 关闭 状态轨道颜色 activeThumbImage 打开 状态下按钮图片 inactiveThumbImage 关闭 状态下按钮图片 materialTapTargetSize 配置tap目标的最小大小 dragStartBehavior 确定处理拖动启动行为的方式。(没看出有什么变化) Flutter 还提供了仿苹果的Switch组件CupertinoSwitch。下面来介绍一下:
属性 说明 value 当前开关状态 布尔值 onChanged 监听(开关状态改变时调用) activeColor 打开 状态 轨道 和 按钮颜色
Switch(
activeColor:Colors.red,
activeTrackColor:Colors.yellow,
inactiveThumbColor:Colors.pink[200],
inactiveTrackColor:Colors.black,
activeThumbImage:AssetImage('images/aa.jpg'),
inactiveThumbImage:AssetImage('images/ba.jpg'),
dragStartBehavior:DragStartBehavior.start,
value: this.valuea,
onChanged: (bool v) {
setState(() {
this.valuea = v;
});
},
),
CupertinoSwitch(
value: this.valueb,
onChanged: (bool value) {
setState(() {
this.valueb = value;
});
},
),
Radio
value | 可以是任意类型的数据,只要和groupValue相同就是选中了 |
---|---|
groupValue | 组内当前的选择的值,相同的groupValue被认定为一组单选框 |
onChanged | 选值更改监听 |
activeColor | 被选中时候按钮的颜色 |
fillColor | 按钮的填充颜色,可以根据状态(如MaterialState.selected)返回颜色值 |
overlayColor | 点击时的波纹的颜色 |
splashRadius | 波纹的半径 |
代码如下:在onChanged中修改当前的groupValue的值,当groupValue与这个组件的value属性的值相等时就表示这个单选框选中,否则就是不选中
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: RadioDemo()
)
);
}
}
enum SingingCharacter { lafayette, jefferson }
class RadioDemo extends StatefulWidget {
@override
_RadioDemoState createState() => new _RadioDemoState();
}
class _RadioDemoState extends State<RadioDemo> {
SingingCharacter _character = SingingCharacter.lafayette;
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 20.0),
child: Column(
children: <Widget>[
Radio(
value: SingingCharacter.lafayette,
groupValue: _character,
activeColor: Colors.red,
onChanged: (SingingCharacter value) {
print(value);
setState(() {
_character = value;
});
},
),
Radio(
value: SingingCharacter.jefferson,
groupValue: _character,
onChanged: (SingingCharacter value) {
print(value);
setState(() {
_character = value;
});
},
)
]
)
);
}
}
SwitchListTile
SwitchListTile “带标题的开关”
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/generated/i18n.dart';
class SwitchDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return TextFieldStateDemo();
}
}
class TextFieldStateDemo extends State {
bool _isCheck;
@override
void initState() {
super.initState();
_isCheck = false;
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Switch 和 SwitchListTile"),
centerTitle: true,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(),
SizedBox(
height: 20,
),
Text(
"一:普通的Switch",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
Switch(
value: _isCheck,
onChanged: _changed,
),
Text(
"二:特质的Switch",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
Switch(
//来初始化此 Switch 是否被选中。true 表示选中 ,false 表示不选中
value: _isCheck,
//当 拖动改变状态时的回调。
onChanged: _changed,
//当 value 是 true 时 滑块的颜色。也就是开的状态时的颜色
activeColor: Colors.red,
// 当 value 是 true 时 滑道的颜色
activeTrackColor: Colors.blueAccent,
// 当 value 是 true 时 滑块上的图片。 如果 activeColor 也设置了 , 以 activeThumbImage 为准
// 如果设置的是网络图片的话。当 滑块 滑到这里 才开始加载。所以 没加载出图片的之前 ,以 activeColor 为准
activeThumbImage: NetworkImage(
"https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=3868620627,2694438302&fm=58"),
// 当 value 是 false 时 滑块的颜色。也就是开的状态时的颜色
inactiveThumbColor: Colors.amberAccent,
// 当 value 是 false 时 滑道的颜色
inactiveTrackColor: Colors.green,
// 当 value 是 false 时 滑块上的图片。 如果 inactiveThumbColor 也设置了 , 以 inactiveThumbImage 为准
inactiveThumbImage: AssetImage("images/hashiqi.jpg"),
),
Text(
"三:SwitchListTile",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
SizedBox(
width: 200,
child: SwitchListTile(
// 是否选中 是否打开
value: _isCheck,
// 当打开关闭的时候的回调
onChanged: _changed,
// 选中时 滑块的颜色
activeColor: Colors.red,
// 选中时 滑道的颜色
activeTrackColor: Colors.black,
// 选中时 滑块的图片
// activeThumbImage: AssetImage("images/hashiqi.jpg"),
// 未选中时 滑块的颜色
inactiveThumbColor: Colors.green,
// 未选中时 滑道的颜色
inactiveTrackColor: Colors.amberAccent,
// 未选中时 滑块的颜色
inactiveThumbImage: AssetImage("images/hashiqi.jpg"),
// 标题
title: Text("标题"),
// 副标题 在标题下面的
// subtitle: Text("副标题"),
// 是不是三行, true 时: subtitle 不能为null, false时可以为 null
// isThreeLine: true,
// 如果为 true ,则 text 和 icon 都用 activeColor 时的color
// selected: true,
// 是否垂直密集居中
dense: true,
// 左边的一个东西
secondary: Icon(Icons.access_time),
),
),
]),
);
}
void _changed(isCheck) {
setState(() {
_isCheck = isCheck;
});
}
}
CheckBoxListTile
const CheckboxListTitle({
Key key,
@required bool value,
@required ValueChanged<bool> onChanged,
Color activeColor,
Widget title, //复选框的主标题
Widget subtitle, //复选框的副标题
bool isThreeLine: false, //文字是否为三行
bool dense, //是否为垂直密集列表的一部分
Widget secondary, //图标
bool selected: false, //文字和图标颜色是否为选中的颜色(activeColor)
ListTileControlAffinity controlAffinity: ListTileControlAffinity.platform //文字、图标、复选框的排列顺序
});
dense
如果为true
,表示这个复选框是一个列表的一部分,会缩小字体。
为false
时则是默认大小
isThreeLine
是否为三行,这是个坑。
首先要搭配subtitle
使用,没有subtitle
的话报错。
然后就是这个坑了,不是文字以三行显示,而是告诉程序,我现在的文字(title
)是不是有三行。。。
title
只有一行
isThreeLine
为false
isThreeLine
为true
可以看到为false
的时候,文字会垂直局中,为true
的时候,文字偏上,这是因为告诉程序这段文字有三行,会把三行文字整体垂直居中显示,这就造成了上边的情况。
title
为三行
isThreeLine
为false
isThreeLine
为true
可以看到显示上并没有什么区别,这是因为设置为true
的时候,告诉了程序这是三行文字,会居中显示,为false
的时候实际上是把整个CheckboxListTile
的区域撑满,居中不居中并没有什么区别。
title
为两行和一行的情况显示是相同的,最多就是三行,超过三行的文字不会显示,会被剪切。
实际上isThreeLine
是设置title
和subtitle
同时存在时文字在垂直方向的显示方式
RadioListTile
-
value: 此 Radio 的 value 值
-
onChanged: 当选择此 radio 的时候 的回调。 参数就是 此 value 的值
-
groupValue: 如果 Radio 的 value 和 groupValue 一样 就 是此 Radio 选中 其他 设置为 不选中
-
activeColor: 选中的颜色
-
title: 标题, 具有代表性的就是 Text
-
subtitle: 副标题(在 title 下面), 具有代表性的就是 Text
-
isThreeLine = false: // 是否是三行文本
- true : 副标题 不能为 null
- false:如果没有副标题 ,就只有一行, 如果有副标题 ,就只有两行
-
dense: 是否密集垂直
-
secondary: 左边的一个控件
-
selected = false: text 和 icon 的 color 是否 是 activeColor 的颜色
-
controlAffinity = ListTileControlAffinity.platform:
- ListTileControlAffinity.platform 根据不同的平台,来显示 对话框 的位置
- ListTileControlAffinity.trailing:勾选在右,title 在中,secondary 在左
- ListTileControlAffinity.leading :勾选在左,title 在中,secondary 在右
import 'package:flutter/material.dart';
class RadioDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Radio 和 Radio RadioListTile "),
centerTitle: true,
),
body: RadioStateDemo(),
);
}
}
class RadioStateDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return RadioSDemo();
}
}
class RadioSDemo extends State<RadioStateDemo> {
String groupValue;
String valueLiu;
String valueZhang;
String valueGuo;
String valueLi;
@override
void initState() {
super.initState();
groupValue = "刘德华";
valueLiu = "刘德华";
valueZhang = "张学友";
valueGuo = "郭富城";
valueLi = "黎明";
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 20,
),
Text(
"一:Radio",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Radio<String>(
// 此 Radio 的 value 值
value: valueLiu,
// 当选择此 radio 的时候 的回调。 参数就是 此 value 的值
onChanged: (value) {
setState(() {
groupValue = value;
});
},
// 如果 Radio 的 value 和 groupValue 一样 就 是此 Radio 选中 其他 设置为 不选中
groupValue: groupValue,
// 选中的颜色
activeColor: Colors.red,
// 响应手势的大小 , 默认是 48 * 48
// MaterialTapTargetSize.shrinkWrap 水波纹 在中间
// MaterialTapTargetSize.padded 水波纹 靠左上
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
Radio(
value: valueZhang,
onChanged: (value) {
setState(() {
groupValue = value;
});
},
groupValue: groupValue,
activeColor: Colors.red,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
Radio(
value: valueGuo,
onChanged: (value) {
setState(() {
groupValue = value;
});
},
groupValue: groupValue,
activeColor: Colors.red,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
Radio(
value: valueLi,
onChanged: (value) {
setState(() {
groupValue = value;
});
},
groupValue: groupValue,
activeColor: Colors.red,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
],
),
SizedBox(
height: 40,
),
Text(
"二:RadioListTile",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
// 不知道 为什么 Row 父布局 不行(暂时不知道why)
Column(
// mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RadioListTile<String>(
title: Text(valueLiu),
// 必须要的属性
value: valueLiu,
//是否选中发生变化时的回调, 回调的 bool 值 就是是否选中 , true 是 选中
groupValue: groupValue,
onChanged: _changed,
// 选中时 填充的颜色
activeColor: Colors.red,
// 标题, 具有代表性的就是 Text ,
// selected 如果是 true :
// 如果 不设置 text 的 color 的话, text的颜色 跟随 activeColor
// 副标题(在 title 下面), 具有代表性的就是 Text , 如果 不设置 text 的 color 的话, text的颜色 跟随 activeColor
subtitle: Text("副标题"),
// 是否是三行文本
// 如果是 true : 副标题 不能为 null
// 如果是 false:
// 如果没有副标题 ,就只有一行, 如果有副标题 ,就只有两行
isThreeLine: false,
// 是否密集垂直
dense: false,
// 左边的一个控件
// secondary: Text("secondary"),
// text 和 icon 的 color 是否 是 activeColor 的颜色
selected: true,
controlAffinity: ListTileControlAffinity.leading,
),
RadioListTile<String>(
title: Text(valueZhang),
value: valueZhang,
groupValue: groupValue,
onChanged: _changed),
RadioListTile<String>(
title: Text(valueGuo),
value: valueGuo,
groupValue: groupValue,
onChanged: _changed),
RadioListTile<String>(
title: Text(valueLi),
value: valueLi,
groupValue: groupValue,
onChanged: _changed),
],
)
],
);
}
void _changed(value) {
groupValue = value;
setState(() {});
}
}