记录一下,解决不同应用场景的需求中各种组件的应用,这里不涉及原理,及详细解析。
场景1:组件需要点击事件
InkWell组件
------------------------------
InkWell(
onTap: (){
print("点击事件");
},
child: Text("需要添加点击事件的组件"),
)
------------------------------
InkResponse组件
------------------------------
InkResponse(
onTap: (){
print("点击事件");
},
child: Text("需要添加点击事件的组件"),
)
------------------------------
GestureDetector组件
------------------------------
GestureDetector(
onTap: (){
print("点击事件");
},
child: Text("需要添加点击事件的组件"),
)
------------------------------
区别:
1.三种点击效果有所区别,InkWell水波纹,InkResponse圆形,GestureDetector无明显效果
2. 平时一般使用InkWell就行了, GestureDetector手势事件比较多。
3.三种点击区域有所差别,对margin,及pading区域的事件响应不同。
4.后续补充
场景2:布局需要背景色,背景图,圆角,阴影及边框,这里用Container实现
Container的背景色,背景图,圆角,阴影及边框的设置
------------------------------
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
///背景色
color: ToolColorRandomColor(),
///圆角
borderRadius: BorderRadius.circular(10),
///边框
border: Border.all(color: Colors.black, width: 1),
///阴影
shape: BoxShape.rectangle,
boxShadow: [
BoxShadow(
color: Colors.red,
offset: Offset(-1, -1),
blurRadius: 1,
)
],
///背景图
image: DecorationImage(
image: AssetImage(
'assets/images/profile_third_24x26.png'),
fit: BoxFit.fill,
),
),
child: Center(child: Text("Container的背景图,圆角及边框的设置"),),
)
------------------------------
注意点:
1.在圆角及边框同时存在时,且并不是全部边框,或全部边框颜色不一致,设置圆角会报错
2.后续补充
场景3:需要显示圆形的图
CircleAvatar组件【效果图1】
------------------------------
CircleAvatar(
backgroundImage: NetworkImage("https://imagecloud.thepaper.cn/thepaper/image/210/561/140.jpg"),
radius: ToolScreenUtilSetWidth(100),
)
------------------------------
ClipOval 组件【效果图2】
------------------------------
class _MyClipper extends CustomClipper{
@override
Rect getClip(Size size) {
return new Rect.fromLTRB(0, 0, 200, 200);
}
@override
bool shouldReclip(CustomClipper oldClipper) {
return false;
}
}
------------------------------
ClipOval(
clipper: _MyClipper(),
child: Image.network("https://imagecloud.thepaper.cn/thepaper/image/210/561/140.jpg"),
)
------------------------------
区别:
1.需要使用圆形图片时,最好使用CircleAvatar,比较方便使用,ClipOval默认剪裁的是椭圆形。
2. ClipOval的优势是可以用于自定义区域大小剪裁椭圆,同理还有ClipRect,剪裁矩形。
3.后续补充
场景4:部分业务需要在某一状态显示和隐藏组件
Offstage组件
Offstage(
offstage: true,
child: Text("需要隐藏的组件"),
),
Visibility组件
Visibility(
visible: true,
child: Text("需要隐藏的组件"),
),
区别:
1.Offstage组件,可以实现widget大小为0,GONE的效果,也可以满足动态添加的需求。如果offstage为true表示隐藏,默认是true。
2.Visibility组件,不仅可以实现GONE的效果,还可以实现INVISIBLE的效果,即不显示但还占据空间。还有更多功能,比如隐藏后是否响应事件等等。如果visible是true代表显示,否则隐藏。
3.Visibility组件,默认隐藏是不占据空间的,如果想保留空间大小,需要添加几个属性Visibility(
visible: true,
maintainAnimation: true,
maintainSize: true,
maintainState: true,
child: Text("补测"),
),
其中maintainSize就是保持大小不变,但是单独设置这一个不行,会报错,maintainAnimation和maintainState也需要同时设置。
4.后续补充
场景5:appBar显示的隐藏比较特殊,直接使用Offstage会报错,需要外面包裹PreferredSize使用。
------------------------------------
appBar: PreferredSize(
child: Offstage(
offstage: false,
child: AppBar(
title: Text("标题"),
),
),
preferredSize: Size.fromHeight(MediaQuery.of(context).size.height * 0.07),
)
-----------------------------------
扩展:
PreferredSize此控件不对其子控件施加任何约束,并且不以任何方式影响孩子的布局。
常用来自定义AppBar和AppBar.bottom(PreferredSize子控件为AppBar或者AppBar.bottom)
Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(200),
child: Container(
color: Colors.blue,
),
),
body: Test1(),
)
AppBar.bottom通常是TabBar等,通过PreferredSize可设置为任意组件:
Scaffold(
appBar: AppBar(
bottom: PreferredSize(
preferredSize: Size.fromHeight(48),
child: Container(
height: 48,
color: Colors.red,
),
),
),
body: Test1(),
)
场景6:键盘删除事件
在当前页面最外层包裹
-----------------------------------
RawKeyboardListener(
autofocus: true,
onKey: (event) {
print("键盘----event=${event.toString()}");
if (event.runtimeType == RawKeyDownEvent) {
if (event.physicalKey == PhysicalKeyboardKey.enter) {
} else if (event.physicalKey == PhysicalKeyboardKey.backspace) {
}
}
},
child:Text("需要监听键盘删除的页面"),
)
在TextField的onChanged中判断value为空时识为删除
-----------------------------------
onChanged: (value) {
if (!gameGridFile.value.isComposingRangeValid) {
print("输入了---${value}");
}
},
吐槽:
没有找到特别适合的监听事件。
场景7:准确获得键盘输入的汉字,因为键盘输入,涉及到拼音事件,不经过过滤的话,获取到的输入不准确
在TextField的onChanged中
-----------------------------------
onChanged: (value) {
if (!gameGridFile.value.isComposingRangeValid) {
print("输入了---${value}");
}
},
-----------------------------------
场景8:不需要表情的输入,需要输入的表情屏蔽
在TextField中设置
RegExp regexp = RegExp(
"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]");
-----------------------------------
inputFormatters: [FilteringTextInputFormatter.deny(regexp)],
-----------------------------------
场景9:在多输入框时需要手动对输入框焦点进行变换
///存储焦点
List gameGridViewFocusNodeList = [];
FocusNode focusNode = FocusNode();
gameGridViewFocusNodeList.add(focusNode);
///获取index焦点,更改焦点
FocusNode focusNode = gameGridViewFocusNodeList[index];
focusNode.requestFocus();
场景10:键盘弹出时,布局需要相应的变化,防止被遮挡,需要对键盘高度进行监听
///初始化方法
void initState() {
super.initState();
///监听键盘高度变化
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeMetrics() {
super.didChangeMetrics();
WidgetsBinding.instance.addPostFrameCallback((_) {
print('键盘高度---${MediaQuery.of(context).viewInsets.bottom}');
});
}
///析构
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
场景11:在布局时外层因为需要自适应高度,内层也有需要自适应的child,同层级存在已知高度的child,如果不做处理,内层自适应的child会撑满外层布局,使用IntrinsicHeight组件可以统一内层child的高度【选取同层级最高的,已设置高度的child不受影响】
IntrinsicHeight组件
效果图1
-----------------------------------
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 50,
color: ToolColorRandomColor(),
),
Container(
height: 100,
width: 50,
color: ToolColorRandomColor(),
),
Container(
width: 50,
color: ToolColorRandomColor(),
),
Container(
width: 50,
height: 200,
color: ToolColorRandomColor(),
)
],
);
效果图2
-----------------------------------
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 50,
color: ToolColorRandomColor(),
),
Container(
height: 100,
width: 50,
color: ToolColorRandomColor(),
),
Container(
width: 50,
color: ToolColorRandomColor(),
),
Container(
width: 50,
height: 200,
color: ToolColorRandomColor(),
)
],
),
);