android - Xamarin.Forms。SwipeGesture 和 ScrollView 在 Android 上不能一起使用
问题描述
我将 Grid 与 SwipeGesture 和 ScrollView 一起使用。ScrollView 运行良好,但 SwipeGesture 不仅适用于 Android。在iOS中我没有问题。
为什么?请帮帮我
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ScrollView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
...
</ScrollView>
</Grid>
C#:
var leftSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Right };
leftSwipeGesture.Threshold = 50;
leftSwipeGesture.Swiped += (sender, e) => Navigation.PopAsync();
grid.GestureRecognizers.Add(leftSwipeGesture);
解决方案
我根据链接解决了这个问题。我创建了一个新组件:
public class GestureScrollView : ScrollView
{
public event EventHandler SwipeLeft;
public event EventHandler SwipeRight;
public void OnSwipeLeft() =>
SwipeLeft?.Invoke(this, null);
public void OnSwipeRight() =>
SwipeRight?.Invoke(this, null);
}
安卓渲染器:
[assembly: ExportRenderer(typeof(GestureScrollView), typeof(GestureScrollViewRenderer))]
namespace SwipeScrollView.Droid.Platform.Renderers
{
public class GestureScrollViewRenderer : ScrollViewRenderer
{
readonly CustomGestureListener _listener;
readonly GestureDetector _detector;
public GestureScrollViewRenderer(Context context) : base(context)
{
_listener = new CustomGestureListener();
_detector = new GestureDetector(context, _listener);
}
public override bool DispatchTouchEvent(MotionEvent e)
{
if (_detector != null)
{
_detector.OnTouchEvent(e);
base.DispatchTouchEvent(e);
return true;
}
return base.DispatchTouchEvent(e);
}
public override bool OnTouchEvent(MotionEvent ev)
{
base.OnTouchEvent(ev);
if (_detector != null)
return _detector.OnTouchEvent(ev);
return false;
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
{
_listener.OnSwipeLeft -= HandleOnSwipeLeft;
_listener.OnSwipeRight -= HandleOnSwipeRight;
}
if (e.OldElement == null)
{
_listener.OnSwipeLeft += HandleOnSwipeLeft;
_listener.OnSwipeRight += HandleOnSwipeRight;
}
}
void HandleOnSwipeLeft(object sender, EventArgs e) =>
((GestureScrollView)Element).OnSwipeLeft();
void HandleOnSwipeRight(object sender, EventArgs e) =>
((GestureScrollView)Element).OnSwipeRight();
}
}
自定义手势监听器:
public class CustomGestureListener : GestureDetector.SimpleOnGestureListener
{
static readonly int SWIPE_THRESHOLD = 100;
static readonly int SWIPE_VELOCITY_THRESHOLD = 100;
MotionEvent mLastOnDownEvent;
public event EventHandler OnSwipeLeft;
public event EventHandler OnSwipeRight;
public override bool OnDown(MotionEvent e)
{
mLastOnDownEvent = e;
return true;
}
public override bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
if (e1 == null)
e1 = mLastOnDownEvent;
float diffY = e2.GetY() - e1.GetY();
float diffX = e2.GetX() - e1.GetX();
if (Math.Abs(diffX) > Math.Abs(diffY))
{
if (Math.Abs(diffX) > SWIPE_THRESHOLD && Math.Abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffX > 0)
OnSwipeRight?.Invoke(this, null);
else
OnSwipeLeft?.Invoke(this, null);
}
}
return base.OnFling(e1, e2, velocityX, velocityY);
}
}
核:
<ctrl:GestureScrollView x:Name="gi"> ... </ctrl:GestureScrollView>
gi.SwipeLeft += (s, e) =>
DisplayAlert("Gesture Info", "Swipe Left Detected", "OK");
gi.SwipeRight += (s, e) =>
DisplayAlert("Gesture Info", "Swipe Right Detected", "OK");
推荐阅读
- flutter - Flutter 中的通用 CRUD Http 函数
- javascript - angualr 10 中的 iframe-resizer 实现(使用 loader.js 动态添加 iframe)
- javascript - 在没有 fs 的情况下保存到 JSON?
- angular - Angular mat-form-field 在标签之间添加空格
- python - 从 OrderedDict 中移除 {}
- libcurl - 如何将 CURLU_ALLOW_SPACE 与 curl_easy_perform 一起使用
- c# - 使用全球化更改为剑道网格创建按钮文本
- angular - 无法读取未定义的属性(读取“已检查”)
- git - 错误:错误的 DVC 文件名 'my_server\models\*.tar.gz.dvc' 被 git 忽略
- visual-studio-code - 类文档自动生成工具