我正在尝试模仿Flutter中MaterialButton上的波纹敲击行为。本质上,我希望能够调用任意函数(例如tapTargetWithEffect(GlobalKey target)
),并在给定的GlobalKey
和要执行的onPressed
回调下看到按钮上的涟漪效应。>
我在指针测试中看到,可以通过WidgetsBinding
分配指针事件以触发涟漪效应。如何执行onPressed
回调?
答案 0 :(得分:1)
这是幼稚的实现方式。
HitTestEntry
对象)的列表onTap
个回调的目标(这些回调将实现RenderSemanticsGestureHandler
),首先获取并分配给tappable
onPointerDown
个回调的目标(这些回调将实现RenderPointerListener
),首先获取并分配给clickable
onTap
回调以执行按钮的onPressed
onPointerDown
呼叫PointerDownEvent
以显示涟漪
PointerDownEvent
接受position
参数,使其成为原始RenderBox
的中心PointerDownEvent
在应用程序边界内的某个地方调度PointerMoveEvent
,以取消WidgetsBinding.instance.dispatchEvent
在所需的持续时间之后
请注意,hitTest()
函数接受BoxHitTestResult
,其中将包含命中测试的结果:)
示例实现:
void tapTargetWithEffect(GlobalKey target) {
final RenderBox renderBox = target.currentContext.findRenderObject();
final child = renderBox as RenderSemanticsAnnotations;
if (child.button) {
final size = renderBox.size;
final center = renderBox.localToGlobal(size.center(Offset.zero));
final hitResult = BoxHitTestResult();
child.hitTest(hitResult, position: size.center(Offset.zero));
final pointerDown = PointerDownEvent(
position: center,
);
final tappableL = hitResult.path
.where((element) => element.target is RenderSemanticsGestureHandler)
.map((element) => element.target as RenderSemanticsGestureHandler)
.toList();
final clickableL = hitResult.path
.where((element) => element.target is RenderPointerListener)
.map((e) => e.target as RenderPointerListener)
.toList();
if (tappableL.isEmpty) {
print('No RenderSemanticsGestureHandler available');
return;
}
if (clickableL.isEmpty) {
print('No RenderPointerListener available');
return;
}
final tappable = tappableL.first;
final clickable = clickableL.first;
clickable.onPointerDown?.call(pointerDown);
tappable.onTap?.call();
// cancel the pointer down event
Future.delayed(Duration(milliseconds: 500)).then((value) {
print('Cancelling the pointer down event');
final result = BoxHitTestResult();
WidgetsBinding.instance.hitTest(result, Offset.zero);
WidgetsBinding.instance.dispatchEvent(PointerMoveEvent(), result);
});
}
}