写文章很累的,还得录制屏幕做gif图,打赏关注的来一波呗
技术交流QQ群: 490113234
1.普通Button按钮:
在Flutter中使用RaisedButton 使用起来很简单,给源码的参数添加下注释,自己看吧。
///注:Flutter SDK源码
const RaisedButton({
Key key,
//点击回调
@required this.onPressed,
//水波纹高亮变化回调
this.onHighlightChanged,
//定义按钮的基本颜色,以及按钮的最小大小、内部填充和形状的默认值
this.textTheme,
//按钮文字颜色
this.textColor,
//按钮禁用的时候文字的颜色
this.disabledTextColor,
//按钮颜色
this.color,
//按钮被禁用的时候显示的颜色
this.disabledColor,
//下面这两个看我的 “Flutter之水波纹” 这篇文章
this.highlightColor,
this.splashColor,
//按钮主题高亮
this.colorBrightness,
//按钮下面阴影
this.elevation: 2.0,
this.highlightElevation: 8.0,
this.disabledElevation: 0.0,
this.padding,
//shapeborder看我的“Flutter之Material” 这篇文章
this.shape,
this.animationDuration: kThemeChangeDuration,
this.child,
}) ;普通Button按钮
还有两个按钮需要说明下:① FlatButton:
没有阴影,就是一个平滑的按钮,常用的比如一些界面上面的文字区域点击可以使用它,还有水波纹效果。
dialog有确定和取消两个选项,5.0以上的手机,触摸或者点击这两个选项是有水波纹一样的效果,我们可以用FlatButton。
toolbar上面显示的文本触摸或者点击也有这样的效果,我们也都可以通过FlatButton实现。
② RawMaterialButton:
RaisedButton 和 FlatButton 基于当前Theme和ButtonThem配置一个RawMaterialButton。
Flatbutton最普通,RaisedButton还能配置ButtonTheme,是Flatbutton的一个升级版本,RawMaterialButton是他们两个的升级版本。
2.下拉菜单按钮:
在Flutter中用DropdownButton展示下拉菜单按钮。
///注:Flutter SDK中源码
DropdownButton({
Key key,
//下拉菜单显示的条目集合信息
@required this.items,
//下拉菜单选择完之后,呈现给用的值
this.value,
//提示文字,第一次不指定默认的值即value值为null,我们的hint就起到了作用
//一般hint展示:请选择一个条目,或者我们第一次把hint展示位下拉菜单条目的第一个值
this.hint,
//下拉菜单item点击之后的回调
@required this.onChanged,
this.elevation: 8,
//TextStyle
this.style,
//下拉菜单icon按钮大小
this.iconSize: 24.0,
this.isDense: false,
})DropdownButton 下拉菜单按钮
下面我们看看如何实现上面的效果:
通过上面的源码的注释this.items这个是一个集合List>
那么我们定义一个方法用于生成下拉菜单item数据集合:
List generateItemList() {
List items = new List();
DropdownMenuItem item1 = new DropdownMenuItem(
value: '张三', child: new Text('张三'));
DropdownMenuItem item2 = new DropdownMenuItem(
value: '李四', child: new Text('李四'));
DropdownMenuItem item3 = new DropdownMenuItem(
value: '王二', child: new Text('王二'));
DropdownMenuItem item4 = new DropdownMenuItem(
value: '麻子', child: new Text('麻子'));
items.add(item1);
items.add(item2);
items.add(item3);
items.add(item4);
return items;
}
this.hint 展示提示文字信息,当然我们也可以在hint中展示我们下拉菜单选中的item数据,那样就没有item定位了。
this.value展示下拉菜单选中的item数据,如果this.value为空,那么我们先展示的是this.hint的值,都没有的话,就是空白。
this.onChanged 下拉菜单item点击的回调
那么问题来了,我们点击了item,之后怎么把点击的item值显示出来?
我们需要使用setState方法,通知框架该对象的内部状态已经更改
void setState(VoidCallback fn)
那么既然是有状态的!我们就需要在有状态的小部件(StatefulWidget)中才能使用。
核心代码:
class DropDownStateWidget extends StatefulWidget{
@override
State createState()=>DropDownState();
}
class DropDownState extends State{
//下拉菜单item点击之后获取到的值
var selectItemValue;
/*DropDownState(){
selectItemValue=getDropdownMenuItem()[0].value;
}*/
@override
Widget build(BuildContext context) {
//DropdownButtonHideUnderline:下拉菜单展示的内容处没有下划线
return new DropdownButtonHideUnderline(
child: new DropdownButton(
hint: new Text('下拉菜单选择一个人名'),
//设置这个value之后,选中对应位置的item,
//再次呼出下拉菜单,会自动定位item位置在当前按钮显示的位置处
value: selectItemValue,
items: generateItemList(),
onChanged: (T){
setState(() {
selectItemValue=T;
});
},
),
);
}
}
使用的话,自己创建个main入口的无状态小部件,给脚手架的body设置
new DropDownStateWidget() 即可。
3. 悬浮按钮 FloatingActionButtonFloatingActionButton
///Flutter SDK源码:
const FloatingActionButton({
Key key,
//子widget:可以是Text文本或者图片(icon或者image)
this.child,
this.tooltip,
//Text文本或者图片(icon或者image)默认的颜色,前提是Text或者icon不设置颜色的情况下才使用
this.foregroundColor,
//按钮背景颜色
this.backgroundColor,
this.heroTag: const _DefaultHeroTag(),
//阴影
this.elevation: 6.0,
this.highlightElevation: 12.0,
@required this.onPressed,
this.mini: false,
//边距
this.notchMargin: 4.0,
//圆形的悬浮按钮
this.shape: const CircleBorder(),
this.isExtended: false,
})
上面的截图用下面这段代码即可实现:
new FloatingActionButton(onPressed: (){
print('button click');
},
foregroundColor: Colors.white,
backgroundColor: Colors.amber,
child: new Icon(Icons.add),),
)
另外:Flutter还提供另一个扩展的FloatActionButton.extended
///SDK源码:
FloatingActionButton.extended({
Key key,
this.tooltip,
//Text文本或者图片(icon或者image)默认的颜色,前提是Text或者icon不设置颜色的情况下才使用
this.foregroundColor,
//按钮背景颜色
this.backgroundColor,
this.heroTag: const _DefaultHeroTag(),
this.elevation: 6.0,
this.highlightElevation: 12.0,
@required this.onPressed,
this.notchMargin: 4.0,
//体育场形状
this.shape: const StadiumBorder(),
this.isExtended: true,
//Icon或者Image
@required Widget icon,
//Text文本
@required Widget label,
})
我们可以实现下面这个icon图标:icon: new Icon(Icons.flag , color: Colors.red,),FloatingActionButton.extended 之 Icon效果
关键代码如下:
new FloatingActionButton.extended(
onPressed: () {
print('button click');
},
foregroundColor: Colors.white,
backgroundColor: Colors.amber,
//如果不手动设置icon和text颜色,则默认使用foregroundColor颜色
icon: new Icon(Icons.flag,color: Colors.red,),
label: new Text('FloatingActionButton.extended', maxLines: 1),
)
我们还可以实现image的FloatActionButton效果:icon: newCircleAvatar(
backgroundImage: newAssetImage('images/zhubo01.jpg'),
)FloatingActionButton.extended 之 Image效果
关键代码如下:
new FloatingActionButton.extended(
onPressed: () {
print('button click');
},
foregroundColor: Colors.white,
backgroundColor: Colors.amber,
//如果不手动设置icon和text颜色,则默认使用foregroundColor颜色
icon: new CircleAvatar(
backgroundImage: new AssetImage('images/zhubo01.jpg'),
),
label: new Text('FloatingActionButton', maxLines: 1),
)
4.复选框 Checkbox
Flutter提供Checkbox,他的状态需要我们自己进行控制,看过我之前文章的都知道
void setState(VoidCallback fn)
我们来使用下Checkbox:
① 首先创建一个有状态的小部件
class _CheckBoxStateWidget extends StatefulWidget{
@override
State createState() =>new _CheckBoxState();
}
② 接下来创建一个checkbox内部状态类
class _CheckBoxState extends State{
bool isChecked=false;
@override
Widget build(BuildContext context) {
return new Checkbox(value: isChecked, onChanged: (bool){
setState(() {
isChecked=bool;
});
},activeColor: Colors.green,);
}
}
最后直接使用_CheckBoxStateWidget()即可Checkbox
下面我们看看列表式的checkbox含文本,如何处理?
///SDK源码相关字段解释:
const CheckboxListTile({
Key key,
//bool值用于控制当前checkbox是否选中
@required this.value,
//点击回调
@required this.onChanged,
this.activeColor,
this.title,
this.subtitle,
this.isThreeLine: false,
this.dense,
this.secondary,
this.selected: false,
//控制亲和度,这个比较重要
this.controlAffinity: ListTileControlAffinity.platform,
})
enum ListTileControlAffinity {
//按钮显示在文字前面
leading,
///按钮显示在文字后面
trailing,
//显示样式根据手机当前平台默认样式展示
platform,
}
关键代码如下:
class _CheckBoxListStateWidget extends StatefulWidget{
@override
State createState() =>new _CheckBoxListState();
}
class _CheckBoxListState extends State{
//初始化全部复选框按钮默认都是false
List checkedList=[false,false,false,false];
@override
Widget build(BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//我用IOS模拟器测试的时候,不设置亲和力,默认值是platform,按钮展示在文字后面,很丑啊
new CheckboxListTile(controlAffinity:ListTileControlAffinity.leading,title:new Text('张三'),value: checkedList[0], onChanged: (bool)=>updateCheckboxStatus(0,bool)),
new CheckboxListTile(controlAffinity:ListTileControlAffinity.leading,title:new Text('李四'),value: checkedList[1], onChanged: (bool)=>updateCheckboxStatus(1,bool)),
new CheckboxListTile(controlAffinity:ListTileControlAffinity.leading,title:new Text('王二'),value: checkedList[2], onChanged: (bool)=>updateCheckboxStatus(2,bool)),
new CheckboxListTile(controlAffinity:ListTileControlAffinity.leading,title:new Text('麻子'),value: checkedList[3], onChanged: (bool)=>updateCheckboxStatus(3,bool)),
],
);
}
void updateCheckboxStatus(int position,bool isCheck){
setState(() {
checkedList[position]=isCheck;
});
}
}CheckboxListTile
5.RadioButton
///SDK源码:
const Radio({
Key key,
//value和groupValue值一样的话,则按钮选中
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.activeColor
})水平排列多个Radio
关键代码如下:
class _RadioButtonStateWidget extends StatefulWidget{
@override
State createState() =>new _RadioButtonState();
}
class _RadioButtonState extends State{
bool isChecked=false;
int groupValue;
@override
Widget build(BuildContext context) {
return new ButtonBar(//ButtonBar:水平排列按钮
alignment: MainAxisAlignment.center,
children: [
//value和groupValue值一样的话,则按钮选中
new Radio(value: 1,
groupValue: groupValue,
onChanged: (int e) => updateGroupValue(e)),
new Radio(value: 2,
groupValue: groupValue,
onChanged: (int e) => updateGroupValue(e)),
new Radio(value: 3,
groupValue: groupValue,
onChanged: (int e) => updateGroupValue(e)),
new Radio(value: 4,
groupValue: groupValue,
onChanged: (int e) => updateGroupValue(e)),
//value值为null则表示按钮不可用
new Radio(value: null, groupValue: null, onChanged: null)
],
);
}
///更新group的值,Radio的value==groupValue时候,则按钮选中
void updateGroupValue(int e){
setState(() {
groupValue=e;
});
}
}
下面我创建一个列表单选按钮组合,关键代码如下,自己可以用column包裹就行了:
new RadioListTile(
title: const Text('张三'),
value: 1,
groupValue: groupValue,
onChanged: (int e)=>updateGroupValue(e),
)RadioListTile
6.Slider 滑块普通Slider
效果和Seekbar效果基本一致,如果要更加细腻的控制样式,请使用:SliderThemeData
//SDK源码:const Slider({
Key key,
//用于更新进度 @required this.value,
//进度变化回调 @required this.onChanged,
this.onChangeStart,
this.onChangeEnd,
this.min: 0.0,
this.max: 1.0,
//刻度 this.divisions,
//拖动滑块时候,在刻度上方气泡里面显示的进度值 this.label,
//滑块轨道中活动的部分的颜色。 this.activeColor,
//滑块轨道的不活动部分的颜色 this.inactiveColor,
})
关键代码如下:
class _SlideState extends State {
double mCurrentValue = 1.0;
@override
Widget build(BuildContext context) {
return new Slider(
value: mCurrentValue,
min: 1.0,
max: 10.0,
label: '$mCurrentValue',
onChanged: (e) {
setState(() {
//四舍五入的双精度值 mCurrentValue = e.roundToDouble();
});
});
}
}
下面我们看看带有刻度和气泡提示的滑块效果:Slider 带刻度和气泡
我们接下来看看如何使用SliderThemeData ?SliderThemeData
添加颜色之后效果更加明显,直接贴代码了:
class _SlideState extends State {
double mCurrentValue = 0.0;
@override
Widget build(BuildContext context) {
return new SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: Colors.deepOrangeAccent,
activeTickMarkColor:Colors.white,
inactiveTickMarkColor: Colors.white,
inactiveTrackColor:Colors.black,
valueIndicatorColor:Colors.blue,
thumbColor:Colors.green,
overlayColor:Colors.amber,
),
child: new Container(
margin: const EdgeInsets.all(10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
new Text('0.0'),
new Expanded(
child: new Slider(
onChanged: (double value) {
setState(() {
mCurrentValue = value;
});
},
divisions: 10,//不想出现刻度和气泡,删除这个属性就可以了,自己实验 label: '$mCurrentValue',
value: mCurrentValue,
)),
new Text('1.0'),
],
),
),
);
}
}
7.TextField 文本输入框
TextFiled的装饰器InputDecoration中InputBorder有两个实现类:
1.UnderlineInputBorder:只有一个下划线的输入框
2.OutlineInputBorder:圆角矩形边框的输入框
我们如果不使用上面两个border的话,默认没有下划线和边框的,大家可以参考我的Material那篇文章,看看怎么使用shape。
下面我将使用StadiumBorder(体育场形状)的shapeBorder包裹我们的文本输入框:
final TextEditingController _textController = new TextEditingController();
new Container(
margin: const EdgeInsets.all(10.0),
child: new Material(
type: MaterialType.canvas,
shape: new StadiumBorder(
side: new BorderSide(
color: Colors.green,
style: BorderStyle.solid
)
),
child: new TextField(
autofocus: true,//自动获取焦点 controller:_textController,
decoration: new InputDecoration(
contentPadding: new EdgeInsets.all(15.0),
border: InputBorder.none
),
onChanged:(String content){
print(content);//文本内容变化,会回调给我们 },
),
),
)TextField