flutter-开发中,各种组件的应用场景【一】

记录一下,解决不同应用场景的需求中各种组件的应用,这里不涉及原理,及详细解析。

场景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的背景图,圆角及边框的设置"),),
      )

------------------------------

WechatIMG120.jpeg

注意点:

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.jpeg
效果图2.jpeg

区别:

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(),
          )
        ],
      ),
    );

效果图1.jpeg
效果图2.jpeg

你可能感兴趣的:(flutter-开发中,各种组件的应用场景【一】)