您好,登錄后才能下訂單哦!
這篇文章主要講解了“Flutter Flow如何實現滑動顯隱層”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Flutter Flow如何實現滑動顯隱層”吧!
思路其實非常簡單,監聽橫向滑動的手勢事件,根據偏移量讓上層組件進行偏移。當放手時,根據偏移量是否達到寬度的一半,使用動畫進行移出或者關閉。
偏移的實現方式有很多,但需要自由地進行布局和矩陣變換、透明度,并且需要支持動畫的變化,Flow 組件是一個非常不錯的選擇。 Flow 組件可以通過代理類對子組件進行自定義布局,靈活性極強;如果是 CustomPaint
是 繪制之王 可以繪制萬物,那么 Flow
就是 布局之王,可以擺放萬物。
另外,在滑動過程中需要注意限制偏移量,使偏移量在 0~size.width
之內;當放手時,通過動畫控制器來驅動動畫,使用補間讓偏移量運動到 0
(打開) 或 size.width
(關閉) 。當關閉時,在右下角展示一個按鈕用于點擊展開:
Flow 組件布局最重要的是實現 FlowDelegate
,在其中的 paintChildren
方法中實現布局的邏輯。和 CustomPainter
類似,FlowDelegate
的實現類也可以通過 super
構造為 repaint
入參設置可監聽對象。可監聽對象的變化會觸發 paintChildren
重新繪制:
SwipeFlowDelegate
實現類再構造時傳入可監聽對象 offsetX
,在繪制索引為 1
的孩子時,通過 Matrix4
進行偏移。這樣只要在手勢水平滑動中,更新 offsetX 值即可。另外,可以根據 offsetX.value
是否達到 size.width
知道是否是關閉狀態,如果已經關閉,繪制按鈕。
class SwipeFlowDelegate extends FlowDelegate { final ValueListenable<double> offsetX; SwipeFlowDelegate(this.offsetX) : super(repaint: offsetX); @override void paintChildren(FlowPaintingContext context) { Size size = context.size; context.paintChild(0); Matrix4 offsetM4 = Matrix4.translationValues(offsetX.value, 0, 0); context.paintChild(1, transform: offsetM4); // 偏移量對于父級尺寸 if (offsetX.value == size.width) { Matrix4 m1 = Matrix4.translationValues(size.width / 2 - 30, size.height / 2 - 30, 0); context.paintChild(2, transform: m1); Matrix4 m2 = Matrix4.translationValues(size.width / 2 - 30, -(size.height / 2 - 50), 0); context.paintChild(3, transform: m2); } } @override bool shouldRepaint(covariant SwipeFlowDelegate oldDelegate) { return oldDelegate.offsetX.value != offsetX.value; } }
從這里可以看出,FlowDelegate
的最大優勢是可以自定義孩子的繪制與否,還可以在繪制時通過 Matrix4
對孩子進行矩陣變換,還有可選參數可以控制透明度。接下來使用 Flow
組件時,提供 SwipeFlowDelegate
,并在 children 列表中依次放入子組件。其中前兩個組件由外界傳入,分別是底組件和上層組件,這樣組件的布局就完成了,接下來監聽事件,更新 factor
即可:
final ValueNotifier<double> factor = ValueNotifier(0); Flow( delegate: SwipeFlowDelegate(factor), children: [ widget.content, widget.overflow, GestureDetector( onTap: open, child: const Icon(Icons.menu_open_outlined, color: Colors.white)), GestureDetector( onTap: () { Navigator.of(context).pop(); }, child: const Icon(Icons.close, color: Colors.white)) ], )
這里手勢的處理是非常簡單的,通過 GestureDetector
監聽水平拖拽事件。在 onHorizontalDragUpdate
中根據拖拽的偏移量更新 factor
的值,其中通過 .clamp(0, widget.width)
可以限制偏移量的取值區間。
@override Widget build(BuildContext context) { return GestureDetector( behavior: HitTestBehavior.opaque, onHorizontalDragUpdate: _onHorizontalDragUpdate, onHorizontalDragEnd: _onHorizontalDragEnd, child: SizedBox( height: MediaQuery.of(context).size.height, width: widget.width, child: Flow( delegate:// 同上,略... ); } void _onHorizontalDragUpdate(DragUpdateDetails details) { double cur = factor.value + details.delta.dx; factor.value = cur.clamp(0, widget.width); } void _onHorizontalDragEnd(DragEndDetails details) { if (factor.value > widget.width / 2) { close(); } else { open(); } }
最后在 _onHorizontalDragEnd
回調中,根據當前偏移量是否大于一般寬度,決定關閉還是打開。期間過程使用動畫進行偏移量的過渡變化。
動畫的使用,主要是通過 AnimationController
動畫控制器來驅動數值的變化;在放手時 Tween
創建補間動畫器,監聽動畫器數值的變化更新偏移量。這樣偏移量就可以在指定時間內,在兩個值之間漸變,從而產生動畫效果。比如抬手時,open
方法是讓偏移量從當前位置變化到 0
:
class _ScrollHideWrapperState extends State<ScrollHideWrapper> with SingleTickerProviderStateMixin { late AnimationController _ctrl; final ValueNotifier<double> factor = ValueNotifier(0); @override void initState() { super.initState(); _ctrl = AnimationController( duration: const Duration(milliseconds: 200), vsync: this, ); } @override Widget build(BuildContext context) { // 略同... } // 動畫關閉 Future<void> close() async { Animation<double> anim = Tween<double>(begin: factor.value, end: widget.width).animate(_ctrl); anim.addListener(() => factor.value = anim.value); await _ctrl.forward(from: 0); } // 動畫打開 Future<void> open() async { Animation<double> anim = Tween<double>(begin: factor.value, end: 0).animate(_ctrl); anim.addListener(() => factor.value = anim.value); await _ctrl.forward(from: 0); } }
如果想讓動畫的變化非勻速,可以使用 Curve 來控制動畫曲線。這樣,基于 Flow 實現的自定義布局,就可以根據手勢和動畫,完成特定的交互功能。從這里可以看出 Flow 自定義布局的靈活性非常強,很多疑難雜癥,都可以使用它來完成。
感謝各位的閱讀,以上就是“Flutter Flow如何實現滑動顯隱層”的內容了,經過本文的學習后,相信大家對Flutter Flow如何實現滑動顯隱層這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。