UIScrollView在WillEndDragging时向子控件传递事件问题
解决方案:在iOS自定义渲染器中手动触发触摸取消事件
步骤1:创建自定义ScrollView(适配CollectionView同理)
在共享项目中定义自定义滚动视图,方便渲染器定位:
public class CustomScrollView : ScrollView { }
步骤2:实现iOS自定义渲染器
创建iOS平台渲染器,监听滚动结束事件并追踪初始触摸控件,手动发送取消事件:
[assembly: ExportRenderer(typeof(CustomScrollView), typeof(CustomScrollViewRenderer))] namespace YourAppNamespace.iOS.Renderers { public class CustomScrollViewRenderer : ScrollViewRenderer { private UIView _activeTouchView; protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e) { base.OnElementChanged(e); if (Control != null) { Control.WillEndDragging += OnWillEndDragging; Control.TouchesBegan += OnTouchesBegan; } } private void OnTouchesBegan(NSSet touches, UIEvent evt) { base.TouchesBegan(touches, evt); var touch = touches.AnyObject as UITouch; if (touch == null) return; var touchLocation = touch.LocationInView(Control); _activeTouchView = Control.HitTest(touchLocation, evt); } private void OnWillEndDragging(object sender, UIScrollViewWillEndDraggingEventArgs e) { if (_activeTouchView == null) return; var touches = new NSSet(); var evt = UIEvent.FromEventHandle(IntPtr.Zero); _activeTouchView.TouchesCancelled(touches, evt); _activeTouchView = null; } protected override void Dispose(bool disposing) { if (Control != null) { Control.WillEndDragging -= OnWillEndDragging; Control.TouchesBegan -= OnTouchesBegan; } base.Dispose(disposing); } } }
步骤3:自定义控件适配触摸取消事件
如果你的自定义控件需要重置点击状态,在其iOS渲染器中重写TouchesCancelled方法:
public class CustomButtonRenderer : ButtonRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Button> e) { base.OnElementChanged(e); if (Control != null) { Control.TouchesCancelled += OnTouchesCancelled; } } private void OnTouchesCancelled(NSSet touches, UIEvent evt) { base.TouchesCancelled(touches, evt); Control.Highlighted = false; // 同步Xamarin Forms控件状态,比如调用自定义重置方法 ((CustomButton)Element)?.ResetPressedState(); } protected override void Dispose(bool disposing) { if (Control != null) { Control.TouchesCancelled -= OnTouchesCancelled; } base.Dispose(disposing); } }
关键说明
- 通过
HitTest定位触摸起始点对应的子控件,确保取消事件发送给正确目标。 - 在
WillEndDragging中手动触发TouchesCancelled,对齐Android/UWP平台的触摸行为,让控件能重置点击状态。 - 若使用CollectionView,只需将渲染器基类替换为
CollectionViewRenderer,核心逻辑完全一致。
内容的提问来源于stack exchange,提问作者TheDeC
相关产品推荐
相关产品推荐

