前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )

【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )

作者头像
韩曙亮
发布2023-03-29 15:45:22
9510
发布2023-03-29 15:45:22
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

前言

在上一篇博客 【Flutter】Banner 轮播组件 ( flutter_swiper 插件 | Swiper 组件 ) 基础上进行开发 ;

一、移除顶部状态栏空白


在 Flutter 界面上方 , 默认有个状态栏 , 显示时间 , 电量 , 网络 , 信号强度等信息 , 这个状态栏是半透明的 ;

可以使用 MediaQuery 组件移除顶部状态栏空白部分 ;

调用 MediaQuery.removePadding 方法 , 第一个参数 context 设置成 BuildContext context , 第二个参数 child 设置成原来的组件 ;

修改前的代码 :

代码语言:javascript
复制
  @override
  Widget build(BuildContext context) {
    /// 界面框架
    return Scaffold(
      /// 居中组件
      body: Center(),
    );
  }

修改后的代码 : 下面代码中的 removeTop: true 很关键 , 代表移除顶部的空白 ;

代码语言:javascript
复制
  @override
  Widget build(BuildContext context) {
    /// 界面框架
    return Scaffold(
      /// 居中组件
      body: MediaQuery.removePadding(
      	  removeTop: true,
          context: context,
          child: Center(),),
    );
  }

移除后顶部空白后的效果 : 上述只是给出了简要的代码示例 , 完整代码看最后的示例 ;

二、帧布局组件


实现帧布局样式需要使用 Stack 组件 , 前面的组件在下层 , 后面的组件在上层 ;

代码语言:javascript
复制
  @override
  Widget build(BuildContext context) {
    /// 界面框架
    return Scaffold(

      /// 帧布局组件 , 前面的元素在下层 , 后面的元素在上层
      body: Stack(
        children: <Widget>[

          /// 消除顶部空白的组件
          MediaQuery.removePadding(),

          /// 透明度可变组件
          Opacity(),
        ],
      ),
    );
  }

上述设置 , 实现了在 Swiper 组件上方显示了 Text 组件 , 并且 Text 组件覆盖了 Swiper 组件 ;

三、透明度组件


Opacity 组件可以控制该组件的透明度改变 , 修改 opacity 属性 , 可以改变组件的透明度效果 , 0 是完全透明 , 1 是完全不透明 ;

代码语言:javascript
复制
          /// 透明度可变组件
          Opacity(
            opacity: appBarAlpha,
            child: Container(
              height: 80,
              decoration: BoxDecoration(color: Colors.white),
              child: Center(
                child: Padding(
                  padding: EdgeInsets.only(top: 20),
                  child: Text("标题透明渐变"),
                ),
              ),
            ),
          ),

四、监听滚动事件


NotificationListener 组件可以监听滚动事件 ;

在 onNotification 属性中设置监听事件 , 传入一个 NotificationListenerCallback 类型的方法 , 方法参数是 ScrollNotification 类型的 ;

指定监听的组件 : scrollNotification.depth == 0 指的是深度为 0 的元素 , 即 ListView 元素滚动时 , 才触发滚动 ;

调用 scrollNotification.metrics.pixels 获取滚动的距离 ; 滚动距离在 0 ~ 100 之间时 , 透明度组件透明度从 0 ~ 1 变化 , 如果滚动距离 >= 100 , 则透明度组件为 1 , 如果滚动距离小于 0 , 则透明度为 0 ;

注意 : 在最后设置完毕后 , 调用 setState 方法 , 更新 UI ;

代码示例 :

代码语言:javascript
复制
            NotificationListener(
              // 监听滚动的方法
              onNotification: (scrollNotification){

                // scrollNotification.depth == 0 指的是深度为 0 的元素
                //    即 ListView 元素滚动时 , 才触发滚动
                if(scrollNotification is ScrollUpdateNotification &&
                    scrollNotification.depth == 0) {

                  // 从 scrollNotification 中获取滚动参数
                  print("滚动距离 ${scrollNotification.metrics.pixels}");

                  // 滚动距离在 0 ~ 100 之间时
                  //    透明度组件透明度从 0 ~ 1 变化
                  //    如果滚动距离 >= 100 , 则透明度组件为 1

                  double alpha = scrollNotification.metrics.pixels / 100.0;

                  // 处理小于 0 和 大于 1 极端情况
                  // 如果只处于 0 ~ 1 之间 , 不做处理
                  if (alpha < 0) {
                    alpha = 0;
                  } else if (alpha > 1) {
                    alpha = 1;
                  }

                  // 更新 UI 数据
                  setState(() {
                    appBarAlpha = alpha;
                  });

                }
              },
              child: ListView(
                children: 
              ),
            ),

五、完整代码示例


代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';

/// 应用主界面
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List _imageUrls = [
    "https://img-blog.csdnimg.cn/20210401205234582.png",
    "https://img-blog.csdnimg.cn/20210401205307863.png",
    "https://img-blog.csdnimg.cn/20210401205249606.png"
  ];

  /// 顶层透明度组件的透明度
  double appBarAlpha = 0;

  @override
  Widget build(BuildContext context) {
    /// 界面框架
    return Scaffold(

      /// 帧布局组件 , 前面的元素在下层 , 后面的元素在上层
      body: Stack(
        children: <Widget>[

          /// 消除顶部空白的组件
          MediaQuery.removePadding(
            removeTop: true,
            context: context,
            // 使用 NotificationListener 组件 , 监听列表的滚动
            child: NotificationListener(
              // 监听滚动的方法
              onNotification: (scrollNotification){

                // scrollNotification.depth == 0 指的是深度为 0 的元素
                //    即 ListView 元素滚动时 , 才触发滚动
                if(scrollNotification is ScrollUpdateNotification &&
                    scrollNotification.depth == 0) {

                  // 从 scrollNotification 中获取滚动参数
                  print("滚动距离 ${scrollNotification.metrics.pixels}");

                  // 滚动距离在 0 ~ 100 之间时
                  //    透明度组件透明度从 0 ~ 1 变化
                  //    如果滚动距离 >= 100 , 则透明度组件为 1

                  double alpha = scrollNotification.metrics.pixels / 100.0;

                  // 处理小于 0 和 大于 1 极端情况
                  // 如果只处于 0 ~ 1 之间 , 不做处理
                  if (alpha < 0) {
                    alpha = 0;
                  } else if (alpha > 1) {
                    alpha = 1;
                  }

                  // 更新 UI 数据
                  setState(() {
                    appBarAlpha = alpha;
                  });

                }
              },
              child: ListView(
                children: <Widget>[
                  Container(
                    /// 设置 Banner 轮播图 160 像素
                    height: 160,
                    /// 这是 flutter_swiper 插件的轮播图
                    child: Swiper(
                      /// 轮播图数量
                      itemCount: _imageUrls.length,

                      /// 设置轮播图自动播放
                      autoplay: true,

                      /// 轮播条目组件
                      itemBuilder: (BuildContext context, int index) {
                        return Image.network(
                          /// 图片 URL 链接
                          _imageUrls[index],
                          /// 缩放方式
                          fit: BoxFit.fill,
                        );
                      },

                      /// 轮播图指示器
                      pagination: SwiperPagination(),

                    ),
                  ),

                  Container(
                    height: 800,
                    child: ListTile(
                      title: Text("标题透明渐变"),
                    ),
                  ),
                ],
              ),
            ),
          ),

          /// 透明度可变组件
          Opacity(
            opacity: appBarAlpha,
            child: Container(
              height: 80,
              decoration: BoxDecoration(color: Colors.white),
              child: Center(
                child: Padding(
                  padding: EdgeInsets.only(top: 20),
                  child: Text("标题透明渐变"),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

执行结果 :

六、相关资源

参考资料 :

重要的专题 :

博客源码下载 :

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 前言
  • 一、移除顶部状态栏空白
  • 二、帧布局组件
  • 三、透明度组件
  • 四、监听滚动事件
  • 五、完整代码示例
  • 六、相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档