需求
下拉到可刷新位置时震动
flutter version: 3.22.2
仅在该版本测试,其他版本未测试。
方法
各有优缺点,本文使用方案3,建议使用方案2。
1.修改SDK中的RefreshIndicator(pass)
2.Copy RefreshIndicator,在原控件上加逻辑(更稳定,推荐)
3.监听ScrollNotification(更灵活,本文使用)
How Use
ListenReadyRefresh(
//到达位置时回调
ready: () async => Vibration.vibrate(
amplitude: await Vibration.hasAmplitudeControl() == true ? 1 : -1,
duration: 50),
child: RefreshIndicator(
triggerMode: RefreshIndicatorTriggerMode.anywhere,
child:....))
ListenReadyRefresh Widget 实现
通过ScrollNotification计算下,复制RefreshIndicator计算逻辑,到达位置时触发回调;
import 'dart:ui';
import 'package:flutter/cupertino.dart';
class ListenReadyRefresh extends StatefulWidget {
final Widget child;
final Function ready;
const ListenReadyRefresh({super.key, required this.child, required this.ready});
State<ListenReadyRefresh> createState() =>
_ListenReadyRefreshState();
}
class _ListenReadyRefreshState
extends State<ListenReadyRefresh> {
var _dragOffset = 0.0;
var vibration = true;
var canStart = false;
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: handleScrollNotification, child: widget.child);
}
bool handleScrollNotification(ScrollNotification notification) {
if((((notification is ScrollStartNotification && notification.dragDetails != null)
|| (notification is ScrollUpdateNotification && notification.dragDetails != null))
&& (( notification.metrics.axisDirection == AxisDirection.up && notification.metrics.extentAfter == 0.0)
|| (notification.metrics.axisDirection == AxisDirection.down && notification.metrics.extentBefore == 0.0)) && _dragOffset==0)){
canStart = true;
return false;
}
if(!canStart){
return false;
}
if (notification is ScrollEndNotification) {
_dragOffset = 0.0;
vibration = true;
canStart = false;
}
double? scrollDelta;
if (notification is OverscrollNotification) {
scrollDelta = notification.overscroll!;
} else if (notification is ScrollUpdateNotification) {
scrollDelta = notification.scrollDelta!;
}
if (scrollDelta != null && vibration == true) {
if (notification.metrics.axisDirection == AxisDirection.down) {
_dragOffset = _dragOffset - scrollDelta;
} else if (notification.metrics.axisDirection == AxisDirection.up) {
_dragOffset = _dragOffset + scrollDelta;
}
double newValue =
_dragOffset / (notification.metrics.viewportDimension * 0.25);
newValue = clampDouble(newValue, 0.0, 1.0);
if(newValue == 1 && vibration){
vibration =false;
widget.ready();
}
}
return false;
}
}