美文网首页
Flutter-实现中间留白,空间不足支持滚动效果

Flutter-实现中间留白,空间不足支持滚动效果

作者: Codepgq | 来源:发表于2022-12-23 10:20 被阅读0次

    前言

    在日常开发中我们可能会遇到这种设计,上半部分的内容是固定的,然后中间是空白,下面是按钮,当屏幕空间显示不下的时候,就压缩空白区域,如果空白区域被压缩完了,就整体滚动(或者上半部分滚动)。

    如图所示

    布局

    根据上面的示意图,随意创建几个Widget出来,效果如下

    class AutoResizeSpacer extends StatelessWidget {
      const AutoResizeSpacer({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('自动压缩空白区域 '),
          ),
          body: Column(
            children: [
              _textField('请输入账号(手机/邮箱)'),
              _textField('请输入验证码'),
              _textField('请输入密码'),
              _button(),
            ],
          ),
        );
      }
    
      Widget _textField(String labelText) {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: InputDecoration(labelText: labelText),
          ),
        );
      }
    
      Widget _button() {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: ElevatedButton(onPressed: () {}, child: const Text('我是按钮')),
        );
      }
    }
    
    默认布局

    上面的代码就把布局给做出来了,但是是不符合设计要求的效果的,接下来就是完成设计的效果。

    在Flutter里面,空白可以用Spacer来表示,这个小部件会撑满剩余的空间,所以我们就可以在Column中新增一个Spacer。效果如下

    Column(
        children: [
            ...
            const Spacer(),
            ...
        ]
    )
    
    小屏幕 大屏 看起来一切安好,直到遇到特小屏设备 image-20221224092643703.png

    上面这个报错,对于Flutter开发来说那不是家常便饭,解决起来也和喝水一样简单,你可能马上就会想到SingleChildScrollView包裹起来,然后。。。你就会发现啥都没有了

    SingleChildScrollView

    这个也很好理解,就是Spacer惹的祸。

    方案一:底部固定,上半部分滚动

    对于上面那种情况,我们可以在外层在套用一个Column,同时把Button提到外面这个Column中,就可以完成这个设计

    ...
    body:Column(
            children: [
              Expanded(
                child: SingleChildScrollView(
                  child: Column(
                    children: [
                      _textField('请输入账号(手机/邮箱)'),
                      _textField('请输入验证码'),
                      _textField('请输入密码'),
                    ],
                  ),
                ),
              ),
              _button(),
            ],
         ),
    ...      
    
    
    image-20221224093354270.png

    这个很好理解,把Column分为两个部分,一个是扩展区域,另外一个是按钮的空间,扩展区域(上半部分)在用一个SIngleChildScrollView进行包裹,当空间不够展示完整的child的时候,就可以滚动。

    方案二:整体滚动

    可以使用CustomScrollView,在配合SliverFillRemaining来完成。


    sliver.gif

    使用之前先来了解一下SliverFillRemaining这个widget,点进去看到他的官方说明:A sliver that contains a single box child that fills the remaining space in the viewport.,会填充一整屏(一整个viewport)的空间,可以用下面的gif来理解

    fillRemaining.gif

    SliverFillRemaining里面有一个属性是:hasScrollBody,意思就是要不要动态计算最大可用范围,默认是开启的。我们把它关闭,然后再观察一下下面这个gif


    fillRemaining-2.gif

    到这里应该就知道如何处理了,把button放在SliverFillRemaining中,然后调整一下他的布局方式就可以完成上面的效果

    ...
    body: CustomScrollView(
          slivers: [
            SliverToBoxAdapter(
              child: Column(
                children: [
                  _textField('请输入账号(手机/邮箱)'),
                  _textField('请输入验证码'),
                  _textField('请输入密码'),
                ],
              ),
            ),
    
            SliverFillRemaining(
              hasScrollBody: false,
              child: Align(
                alignment: Alignment.bottomCenter,
                child: _button(),
              ),
            ),
          ],
        )
    ...
    

    结尾

    到这里就可以根据要求完成上面的效果了,由于代码量很少,就不上传git了,贴一下全部代码吧

    class AutoResizeSpacer extends StatelessWidget {
      const AutoResizeSpacer({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('自动压缩空白区域 '),
          ),
          body: _body2(),
        );
      }
    
      Widget _body2() {
        return CustomScrollView(
          slivers: [
            SliverToBoxAdapter(
              child: Column(
                children: [
                  _textField('请输入账号(手机/邮箱)'),
                  _textField('请输入验证码'),
                  _textField('请输入密码'),
                ],
              ),
            ),
    
            SliverFillRemaining(
              hasScrollBody: false,
              child: Align(
                alignment: Alignment.bottomCenter,
                child: _button(),
              ),
            ),
          ],
        );
      }
    
      Widget _body1() {
        return Column(
          children: [
            Expanded(
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    _textField('请输入账号(手机/邮箱)'),
                    _textField('请输入验证码'),
                    _textField('请输入密码'),
                  ],
                ),
              ),
            ),
            _button(),
          ],
        );
      }
    
      Widget _textField(String labelText) {
        return Padding(
          padding: const EdgeInsets.all(16.0),
          child: TextField(
            decoration: InputDecoration(labelText: labelText),
          ),
        );
      }
    
      Widget _button() {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: ElevatedButton(onPressed: () {}, child: const Text('我是按钮')),
        );
      }
    }
    

    相关文章

      网友评论

          本文标题:Flutter-实现中间留白,空间不足支持滚动效果

          本文链接:https://www.haomeiwen.com/subject/nvmbqdtx.html