Flutter监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )相关的知识,希望对你有一定的参考价值。
前言
在上一篇博客 【Flutter】Banner 轮播组件 ( flutter_swiper 插件 | Swiper 组件 ) 基础上进行开发 ;
一、移除顶部状态栏空白
在 Flutter 界面上方 , 默认有个状态栏 , 显示时间 , 电量 , 网络 , 信号强度等信息 , 这个状态栏是半透明的 ;
可以使用 MediaQuery 组件移除顶部状态栏空白部分 ;
调用 MediaQuery.removePadding 方法 , 第一个参数 context 设置成 BuildContext context , 第二个参数 child 设置成原来的组件 ;
修改前的代码 :
@override
Widget build(BuildContext context) {
/// 界面框架
return Scaffold(
/// 居中组件
body: Center(),
);
}
修改后的代码 : 下面代码中的 removeTop: true
很关键 , 代表移除顶部的空白 ;
@override
Widget build(BuildContext context) {
/// 界面框架
return Scaffold(
/// 居中组件
body: MediaQuery.removePadding(
removeTop: true,
context: context,
child: Center(),),
);
}
移除后顶部空白后的效果 : 上述只是给出了简要的代码示例 , 完整代码看最后的示例 ;
二、帧布局组件
实现帧布局样式需要使用 Stack 组件 , 前面的组件在下层 , 后面的组件在上层 ;
@override
Widget build(BuildContext context) {
/// 界面框架
return Scaffold(
/// 帧布局组件 , 前面的元素在下层 , 后面的元素在上层
body: Stack(
children: <Widget>[
/// 消除顶部空白的组件
MediaQuery.removePadding(),
/// 透明度可变组件
Opacity(),
],
),
);
}
上述设置 , 实现了在 Swiper 组件上方显示了 Text 组件 , 并且 Text 组件覆盖了 Swiper 组件 ;
三、透明度组件
Opacity 组件可以控制该组件的透明度改变 , 修改 opacity 属性 , 可以改变组件的透明度效果 , 0 是完全透明 , 1 是完全不透明 ;
/// 透明度可变组件
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 ;
代码示例 :
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:
),
),
五、完整代码示例
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("标题透明渐变"),
),
),
),
),
],
),
);
}
}
执行结果 :
六、相关资源
参考资料 :
- Flutter 官网 : https://flutter.dev/
- Flutter 插件下载地址 : https://pub.dev/packages
- Flutter 开发文档 : https://flutter.cn/docs ( 强烈推荐 )
- 官方 GitHub 地址 : https://github.com/flutter
- Flutter 中文社区 : https://flutter.cn/
- Flutter 实用教程 : https://flutter.cn/docs/cookbook
- Flutter CodeLab : https://codelabs.flutter-io.cn/
- Dart 中文文档 : https://dart.cn/
- Dart 开发者官网 : https://api.dart.dev/
- Flutter 中文网 : https://flutterchina.club/ , http://flutter.axuer.com/docs/
- Flutter 相关问题 : https://flutterchina.club/faq/ ( 入门阶段推荐看一遍 )
- GitHub 上的 Flutter 开源示例 : https://download.csdn.net/download/han1202012/15989510
- Flutter 实战电子书 : https://book.flutterchina.club/chapter1/
重要的专题 :
- Flutter 动画参考文档 : https://flutterchina.club/animations/
博客源码下载 :
-
GitHub 地址 : https://github.com/han1202012/flutter_app ( 随博客进度一直更新 , 有可能没有本博客的源码 )
-
博客源码快照 : https://download.csdn.net/download/han1202012/21515304 ( 本篇博客的源码快照 , 可以找到本博客的源码 )
以上是关于Flutter监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )的主要内容,如果未能解决你的问题,请参考以下文章
Flutter - ScrollController 滚动监听及控制