看过好多说flutter手势冲突的文章,但大多都是说的都是官方组件之间的联动。但是作为一个Android 开发者,我理解的手势冲突更应该是去处理父父子子的关系。可以动态的决定这个事件是父处理还是子处理。
flutter 滑动组件一般都可以设置ScrollPhysics
,我们通过重写ScrollPhysics的applyPhysicsToUserOffset
方法来进行事件的分发。当组件有手势滑动的时候,会先回调这个方法,这个方法的返回值决定这次手势真正处理的数值,比如返回0,这个组件就不会滑动。
scala
class _ChildScrollPhysics extends ScrollPhysics {
final ScrollController controller;
const _ChildScrollPhysics(this.controller, {super.parent});
@override
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
var isReach = (
(position.pixels <= position.minScrollExtent && offset > 0 ) || // 到达顶部
(position.pixels >= position.maxScrollExtent && offset < 0) // 到达底部
);
if(isReach){
controller.jumpTo(controller.position.pixels - offset);
return 0;
}else {
return a;
}
}
@override
_ChildScrollPhysics applyTo(ScrollPhysics? ancestor) {
return _ChildScrollPhysics(controller,parent: buildParent(ancestor));
}
}
less
var contoller = ScrollController();
class ScrollPhysicsTestPage extends StatelessWidget {
const ScrollPhysicsTestPage({super.key});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.white,
child: ListView.builder(
controller: contoller,
physics: ClampingScrollPhysics(),
itemBuilder: (context,index){
if(index == 3){
return SizedBox(
height: 300,
child: ListView.builder(
padding: EdgeInsets.zero,
physics: _ChildScrollPhysics(contoller),
itemBuilder: (context,index){
return Container(height: 100,color: Colors.blue,
margin: const EdgeInsets.only(bottom: 20));
},
itemCount: 10,
),
);
}
return Container(height: 100,color: Colors.red,
margin: const EdgeInsets.only(bottom: 20)
);
}),
);
}
}
_ChildScrollPhysics 中的controll 是父节点的controller。
arduino
var isReach = (
(position.pixels <= position.minScrollExtent && offset > 0 ) || // 到达顶部
(position.pixels >= position.maxScrollExtent && offset < 0) // 到达底部
);
这部分代码是判断子节点是否滑动到边界。
kotlin
if(isReach){
controller.jumpTo(controller.position.pixels - offset);
return 0;
}else {
return a;
}
如果到了边界交给父节点的controller 去处理。没有到边界自己全权处理。