[英]ListView - Only allow double-finger scrolling and disable single-finger one (Flutter)
我正在使用 Flutter ListView,並且只在用戶使用兩個手指時才需要讓用戶滾動。 如果用戶只使用一根手指,我應該禁用滾動。
我不知道如何實現這一點:/我嘗試過的:我嘗試對 ScrollPhysics 進行子類化並重寫 shouldAcceptUserOffset 或 applyPhysicsToUserOffset,但沒有任何效果。 我也嘗試通讀文檔,但沒有找到任何相關內容。
非常感謝您的任何建議!
挖了Flutter源碼(雖然代碼很多,但是看起來很漂亮),終於找到了一個hack。 這適用於我的 iOS 模擬器和 Android 手機。
評論:
onlyScrollableWhenMultiFinger: true
),則在下面的示例中為MultiFingerListViewController
設置onlyScrollableWhenMultiFinger: true
。使用步驟:
MultiFingerListViewParent
作為列表視圖的父級。physics
特性。樣本:
class TestDoubleFingerScrollV2 extends StatefulWidget {
@override
_TestDoubleFingerScrollV2State createState() => _TestDoubleFingerScrollV2State();
}
class _TestDoubleFingerScrollV2State extends State<TestDoubleFingerScrollV2> {
final controller = MultiFingerListViewController(onlyScrollableWhenMultiFinger: true);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('TestDoubleFingerScrollV2')),
body: MultiFingerListViewParent(
controller: controller,
child: ListView.builder(
physics: MultiFingerScrollPhysics(controller: controller),
itemCount: 100,
itemBuilder: (context, index) =>
Container(height: 60, color: Colors.green.withAlpha((index * 50) % 255), child: Text('$index'))),
));
}
}
來源:
import 'package:flutter/material.dart';
import 'package:flutter_proj/components/finger_aware_listener.dart';
import 'package:flutter_proj/components/mux_listener.dart';
class MultiFingerListViewController {
final bool onlyScrollableWhenMultiFinger;
final _fingerAwareListener = FingerAwareListener();
bool _lastShouldScrollable = false;
MultiFingerListViewController({@required this.onlyScrollableWhenMultiFinger});
bool _updateShouldScrollable() {
_lastShouldScrollable =
(!onlyScrollableWhenMultiFinger) || _fingerAwareListener.info.isCurrentRunMultiFingerUpToNow;
return _lastShouldScrollable;
}
}
class MultiFingerListViewParent extends StatelessWidget {
final MultiFingerListViewController controller;
final Widget child;
const MultiFingerListViewParent({Key key, this.child, this.controller}) : super(key: key);
@override
Widget build(BuildContext context) {
return MuxListener(
onPointer: controller._fingerAwareListener.handlePointer,
child: child,
);
}
}
// This sub-class should have some boilerplate code, e.g. look at [NeverScrollableScrollPhysics] to see it
/// NOTE (WARN): This is a HACK, VIOLATING what the comments said for `applyPhysicsToUserOffset`. But works well for me.
class MultiFingerScrollPhysics extends ScrollPhysics {
final MultiFingerListViewController controller;
const MultiFingerScrollPhysics({ScrollPhysics parent, @required this.controller}) : super(parent: parent);
@override
MultiFingerScrollPhysics applyTo(ScrollPhysics ancestor) {
return MultiFingerScrollPhysics(controller: controller, parent: buildParent(ancestor));
}
/// NOTE This **HACK** is actually **VIOLATING** what the comment says!
/// The comment in [ScrollPhysics.applyPhysicsToUserOffset] says:
/// "This method must not adjust parts of the offset that are entirely within
/// the bounds described by the given `position`."
/// In addition, when looking at [BouncingScrollPhysics.applyPhysicsToUserOffset],
/// we see they directly return the original `offset` when `!position.outOfRange`
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
if (controller._updateShouldScrollable()) {
// When k fingers are dragging, the speed is actually *k* times the normal speed. So we divide it by k.
// (see https://github.com/flutter/flutter/issues/11884)
final currNumFinger = controller._fingerAwareListener.info.currentRunSeenPointers.length;
return offset / currNumFinger;
} else {
return 0.0;
}
}
@override
Simulation createBallisticSimulation(ScrollMetrics position, double velocity) {
// When this method is called, the fingers seem to all *have left* the screen. Thus we cannot calculate the
// current information, but should use the previous cache.
if (controller._lastShouldScrollable) {
return super.createBallisticSimulation(position, velocity);
} else {
return null;
}
}
}
它依賴於其他幾個小組件(非常短的代碼),我把它們放在這里。
希望能幫助到你! 如果您有更好的解決方案,請告訴我:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.