flutter 简单封装一个滑动监听回调

原创
2020/10/25 09:10
阅读数 799

很多 App 都有监听滑动事件来改变 AppBar 颜色,或者 AppBar 的字体颜色,亦或者是其它控件的渐变,缩放等值。我看 Flutter 并没有详细的监听事件。于是自己写了一个。效果如下:

定义回调

 //颜色值改变的回调  ValueChanged<Color> onColorChange;  //百分比变化回调  ValueChanged<double> onPercentChange;  //回调最大可滑动高度  ValueChanged<double> onMaxHeightCallBack;  //滑动方向监听回调  ValueChanged<ScrollDirection> onScrollDirectionCallBack;

监听事件

  void addListener() {    scrollController.addListener(() {      // print("$_scrollController.offset" + " / " + "$oldOffset");      //      // print("max" + _scrollController.position.maxScrollExtent.toString());      expandPix = scrollController.position.maxScrollExtent;
if (onMaxHeightCallBack != null) onMaxHeightCallBack(expandPix);
if (oldOffset > scrollController.offset) { // print("向下滑"); //1--->0 //黑变白 if (onScrollDirectionCallBack != null) { onScrollDirectionCallBack(ScrollDirection.down); } double progress = scrollController.position.pixels.toInt() / expandPix; // print("object===" + // (_scrollController.position.pixels.toInt() / expandPix).toString()); if (progress > 0.5) { valueColor = endColor.withOpacity((progress - 0.5) * 2); } else { valueColor = startColor.withOpacity(1 - (2 * progress)); } if (onPercentChange != null) { onPercentChange(progress); } if (onColorChange != null) { onColorChange(valueColor); } } else { if (onScrollDirectionCallBack != null) { onScrollDirectionCallBack(ScrollDirection.up); } //0--->1 // print("向上滑"); double progress = scrollController.position.pixels.toInt() / expandPix;
// print("object===" + // (_scrollController.position.pixels.toInt() / expandPix).toString());
if (progress < 0.5) { valueColor = startColor.withOpacity(1 - (2 * progress)); } else { valueColor = endColor.withOpacity((progress - 0.5) * 2); }
if (onPercentChange != null) { onPercentChange(progress); }
if (onColorChange != null) { onColorChange(valueColor); } } oldOffset = scrollController.offset; //print("======" + _scrollController.position.pixels.toString()); }); }

用法

//用法  ScrollControl _scrollControl;
_scrollControl = new ScrollControl( scrollController: _scrollController, onColorChange: (color) { this.mainColor = color; infoMap["color"] = color.toString();
setState(() {}); }, onMaxHeightCallBack: (maxHeight) { infoMap["maxHeight"] = maxHeight.toString(); }, onScrollDirectionCallBack: (direction) { infoMap["direction"] = direction.toString(); }, onPercentChange: (percent) { this.fadeValue = percent; infoMap["percent"] = percent.toString(); setState(() {}); });
_scrollControl.addListener();

全部代码

import 'package:flutter/material.dart';
class ScrollControllPage extends StatefulWidget { @override _ScrollControllPageState createState() => _ScrollControllPageState();}
class _ScrollControllPageState extends State<ScrollControllPage> { //滑动监听 ScrollController _scrollController = ScrollController();
Color mainColor = Colors.white;
double fadeValue = 0;
//用法 ScrollControl _scrollControl;
//打印滑动信息 Map<String, String> infoMap = { "color": "", "direction": "", "percent": "", "maxHeight": "" };
@override void initState() { // TODO: implement initState super.initState();
_scrollControl = new ScrollControl( scrollController: _scrollController, onColorChange: (color) { this.mainColor = color; infoMap["color"] = color.toString();
setState(() {}); }, onMaxHeightCallBack: (maxHeight) { infoMap["maxHeight"] = maxHeight.toString(); }, onScrollDirectionCallBack: (direction) { infoMap["direction"] = direction.toString(); }, onPercentChange: (percent) { this.fadeValue = percent; infoMap["percent"] = percent.toString(); setState(() {}); });
_scrollControl.addListener(); }
@override Widget build(BuildContext context) { return Scaffold( body: NestedScrollView( controller: _scrollController, headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverAppBar( backgroundColor: Colors.blue, leading: Container( child: Icon( Icons.arrow_back_ios, color: mainColor, ), ), title: Container( height: 80, width: MediaQuery.of(context).size.width, alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Expanded( child: Container( height: 40, child: Container( alignment: Alignment.centerLeft, child: Text( "滑动监听小封装", style: TextStyle(color: mainColor), ), ), ), ), ], ), ), pinned: true, flexibleSpace: Stack(overflow: Overflow.visible, children: [ FlexibleSpaceBar( centerTitle: true, background: Container( height: 120, width: MediaQuery.of(context).size.width, decoration: BoxDecoration( image: DecorationImage( image: NetworkImage( "https://static.runoob.com/images/demo/demo2.jpg"), fit: BoxFit.cover)), ), ), Positioned( bottom: -40, left: 0, right: 0, child: Opacity( opacity: 1 - this.fadeValue, child: _buildHeader(), ), ) ]), expandedHeight: 160, forceElevated: innerBoxIsScrolled, floating: true, ), ]; }, body: Container( margin: EdgeInsets.only( top: 10 + 40.0, ), padding: EdgeInsets.only(bottom: 10), child: MediaQuery.removePadding( context: context, removeTop: true, child: SingleChildScrollView( child: Container( margin: EdgeInsets.only(top: 160), child: Column(children: buildItems(infoMap).toList()), ), )), )), ); }
_buildHeader() { return Container( margin: EdgeInsets.only(left: 10, right: 10), height: 80, width: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Colors.red), ); }
List<Widget> buildItems( Map<String, String> infos, ) { List<Widget> _items = new List(); infos.forEach((key, value) { _items.add(Container( height: 80, width: 300, child: Text("${key}: ${value}"), )); });
return _items; }}
///////////////
//定义滑动方向enum ScrollDirection { // 方向 下 down,
//方向 上 up,}
class ScrollControl { final ScrollController scrollController;
//起始颜色 Color startColor;
//最终颜色 Color endColor;
Color valueColor = Color.fromARGB((1 * 255).toInt(), 255, 255, 255);
double expandPix = 0;
double oldOffset = -1;
//颜色值改变的回调 ValueChanged<Color> onColorChange; //百分比变化回调 ValueChanged<double> onPercentChange; //回调最大可滑动高度 ValueChanged<double> onMaxHeightCallBack; //滑动方向监听回调 ValueChanged<ScrollDirection> onScrollDirectionCallBack;
ScrollControl({ @required this.scrollController, this.startColor = Colors.white, this.endColor = Colors.black, this.onColorChange, this.onPercentChange, this.onMaxHeightCallBack, this.onScrollDirectionCallBack, });
void addListener() { scrollController.addListener(() { // print("$_scrollController.offset" + " / " + "$oldOffset"); // // print("max" + _scrollController.position.maxScrollExtent.toString()); expandPix = scrollController.position.maxScrollExtent;
if (onMaxHeightCallBack != null) onMaxHeightCallBack(expandPix);
if (oldOffset > scrollController.offset) { // print("向下滑"); //1--->0 //黑变白 if (onScrollDirectionCallBack != null) { onScrollDirectionCallBack(ScrollDirection.down); } double progress = scrollController.position.pixels.toInt() / expandPix; // print("object===" + // (_scrollController.position.pixels.toInt() / expandPix).toString()); if (progress > 0.5) { valueColor = endColor.withOpacity((progress - 0.5) * 2); } else { valueColor = startColor.withOpacity(1 - (2 * progress)); } if (onPercentChange != null) { onPercentChange(progress); } if (onColorChange != null) { onColorChange(valueColor); } } else { if (onScrollDirectionCallBack != null) { onScrollDirectionCallBack(ScrollDirection.up); } //0--->1 // print("向上滑"); double progress = scrollController.position.pixels.toInt() / expandPix;
// print("object===" + // (_scrollController.position.pixels.toInt() / expandPix).toString());
if (progress < 0.5) { valueColor = startColor.withOpacity(1 - (2 * progress)); } else { valueColor = endColor.withOpacity((progress - 0.5) * 2); }
if (onPercentChange != null) { onPercentChange(progress); }
if (onColorChange != null) { onColorChange(valueColor); } } oldOffset = scrollController.offset; //print("======" + _scrollController.position.pixels.toString()); }); }}



本文分享自微信公众号 - Flutter学习簿(gh_d739155d3b2c)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部