最近在學習 Flutter,俗話說的好,紙上得來終覺淺,所以動手擼了一個 gank.io 的 APP,有興趣的可以 到 GitHub 看看原始碼。
本文將與大家分享專案中自定義的縮放控制元件 GestureZoomBox 。
功能
- 雙擊縮放。
- 雙指縮放。
- 以雙擊位置/雙指位置作為縮放中心。
- 限制縮放/拖動範圍,超過範圍自動回彈。
- 作為父級 Widget 直接巢狀,無侵入。
核心原理
手勢識別
Flutter 已經提供了 GestureDetector
處理手勢(點選、雙擊、縮放、拖動),我們只要將可縮放內容作為 GestureDetector
的 child 並設定相應手勢回撥即可。
Pan and scale callbacks cannot be used simultaneous because scale is a superset of pan. Simply use the scale callbacks instead.
這是原始碼中的註釋,大意是“縮放是平移的超集,兩者不能同時使用,只需使用縮放回撥即可”。因此我們只需要用到以下回撥:
/// 雙擊事件回撥,用來處理雙擊縮放。
final GestureTapCallback onDoubleTap;
/// 縮放值或者拖動位置發生改變。在這裡根據每次的變化量進行縮放/拖動處理。
final GestureScaleUpdateCallback onScaleUpdate;
/// 縮放/拖動結束。用來檢測並處理超過邊界的情況。
final GestureScaleEndCallback onScaleEnd;
複製程式碼
縮放和平移
使用 Transform
進行縮放和平移處理。
// 當前縮放值
double _scale = 1.0;
// 當前偏移值
Offset _offset = Offset.zero;
...
// 使用 Transform 包裹 child ,以便進行平移和縮放處理
Transform(
transform: Matrix4.identity()
..translate(_offset.dx, _offset.dy)
..scale(_scale, _scale),
child: widget.child,
alignment: Alignment.center,
)
複製程式碼
使用方法
新增依賴
dependencies:
gesture_zoom_box: ^0.0.2
複製程式碼
導包
import 'package:gesture_zoom_box/gesture_zoom_box.dart';
複製程式碼
使用控制元件
GestureZoomBox(
maxScale: 5.0,
doubleTapScale: 2.0,
duration: Duration(milliseconds: 200),
onPressed: () => Navigator.pop(context),
child: Image.network(widget.imageUrl),
)
複製程式碼