網(wǎng)站首頁 編程語言 正文
正文
實現(xiàn)的效果是這樣的:
剛開始的時候,是在dev上找了兩個輪子,簡單測了下,都不太滿意,滑動事件處理的比較粗糙,總有bug。就在想著,要不要拿源碼改一版的時候,讓我無意間看到了這個帖子
里面的想法,大開眼界,是通過 DraggableScrollableSheet 和 IgnorePointer 來完美實現(xiàn)上面的效果。
實現(xiàn)
這是 DraggableScrollableSheet 的代碼,
DraggableScrollableSheet( maxChildSize: 0.8, minChildSize: 0.25, // 注意都是占父組件的比例 initialChildSize: 0.25, expand: true, builder: (BuildContext context, ScrollController controller) { return Stack(); // body列表和header欄都在stack內(nèi) }, )
這是 body 列表和 header,這里的 body 是個 list,
Stack( children: [ Container( color: Colors.blue, child: Body( // ListView.separated controller: controller, paddingTop: headerHeight, // 防止壓蓋 ), ), const IgnorePointer( // 這里不接收事件,所以拖動 header 也能夠滑動頁面 child: Header( // Container[Center[Text]] height: headerHeight, ), ), ], )
但如果我們想在 header 內(nèi)加點擊事件呢?那在 Stack header 上層再加 widget 就好了。
代碼就這點,我放在了 gitHub 上,感興趣的可以看下。
2022.8.23 補充:
這是在上面功能基礎(chǔ)上的一個小擴展,即當(dāng)滑動距離超過一半則自動滾至頂部,反之回到底部,來看下效果:
思路也很簡單,首先我要知道當(dāng)前滾動的距離或其占比,DraggableScrollableController 提供了這個能力:
void _draggableScrollListener() { // [_currStale] 記錄下當(dāng)前的占比 // [_controller.size] 即占比, 范圍[minChildSize,maxChildSize] // [_controller.pixels] 即距離 if (_currStale != _controller.size) { _currStale = _controller.size; } debugPrint('[listener] size: ${_controller.size}' ', pixels : ${_controller.pixels}'); }
其次要知道用戶何時停止了滾動,我們可以使用 NotificationListener 來監(jiān)聽 DraggableScrollableSheet 的滾動狀態(tài):
NotificationListener<ScrollNotification>( onNotification: (ScrollNotification notification) { ... return false; }, child: DraggableScrollableSheet(...),
之后在用戶停止?jié)L動的時候,我們判斷當(dāng)前距離,并根據(jù)結(jié)果讓 DraggableScrollableSheet 自動滾動到頂部或底部。
onNotification: (ScrollNotification notification) { if (_animation) { // 動畫中,不處理狀態(tài) return false; } if (notification is ScrollStartNotification) { debugPrint('start scroll'); } else if (notification is ScrollEndNotification) { debugPrint('stop scroll'); // 通過 [_controller.animateTo] 方法滾動 _scrollAnimation(); } return false;
在 _scrollAnimation 內(nèi)就是滾動的方法了,這里要注意的是,不能直接使用 await Feature,我測試在頻繁不同方向滑動時,可能會導(dǎo)致方法被掛起。在這直接 dedelayed(duration: xx) 即可:
Future<void> _scrollAnimation() async { if (_animation) { return; } _animation = true; //debugPrint('async start'); final int duration; // `await`ing the returned Feature(of [animateTo]) may cause the method to hang // So, Start a timer to set [_animation]. if (_currStale >= (_maxScale + _minScale) * 0.5) { duration = (_duration * ((_maxScale - _currStale) / (_maxScale - _minScale))) .toInt(); if (duration == 0) { _animation = false; return; } else { // [duration] control speed, Avoid situations where it's equal to 0 _animationTo(_maxScale, duration); } } else { duration = (_duration * ((_currStale - _minScale) / (_maxScale - _minScale))) .toInt(); if (duration == 0) { _animation = false; return; } else { _animationTo(_minScale, duration); } } Future.delayed( Duration(milliseconds: duration), ).then((value) => { //debugPrint('async stop'), _animation = false, }); }
其中 _animationTo
是實際控制控件滾動的方法:
void _animationTo(double scale, int duration) { _controller.animateTo( scale, duration: Duration(milliseconds: duration), curve: Curves.ease, ); }
2022.9.24 補充:
那如果再提供一種通過點擊按鈕來控制 DraggableScrollableSheet
收起和彈出的方法呢?
我們可以直接這樣,是不是很簡單:
Future<void> _scrollAnimation2() async { if (_animation) { return; } if (_currStale > (_maxScale + _minScale) * 0.5) { _animationTo(_minScale, _duration); } else { _animationTo(_maxScale, _duration); } }
原文鏈接:https://juejin.cn/post/7127686678587637796
相關(guān)推薦
- 2022-06-28 詳解Python中遞歸函數(shù)的原理與使用_python
- 2022-04-26 C#新特性之可空引用類型_C#教程
- 2022-03-21 oracle中commit之后進行數(shù)據(jù)回滾的方法_oracle
- 2022-02-24 TypeError: ‘Serializer‘ object is not callable
- 2022-03-14 跨域:Response to preflight request doesn t pass acce
- 2023-02-07 詳解C#如何實現(xiàn)窗體換膚_C#教程
- 2023-03-04 C語言模擬實現(xiàn)字符串庫函數(shù)的示例講解_C 語言
- 2022-11-05 解決使用pip安裝報錯:Microsoft?Visual?C++?14.0?is?required.
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支