Xamarin.Forms iOS端DragGestureRecognizer拖动元素背景变主题色问题求解
解决方案
你遇到的是iOS平台系统级拖拽的默认行为,Xamarin.Forms默认调用系统逻辑生成拖拽预览,会自动添加主题色背景和操作标识(绿色加号),跨平台属性无法直接修改该效果,需在iOS平台层自定义拖拽预览解决,具体实现步骤如下:
实现步骤
1. 共享项目创建自定义效果
public class ClearDragPreviewEffect : RoutingEffect { public ClearDragPreviewEffect() : base($"你的项目命名空间.{nameof(ClearDragPreviewEffect)}") { } }
2. iOS项目实现平台效果
[assembly: ResolutionGroupName("你的项目命名空间")] [assembly: ExportEffect(typeof(IosClearDragPreviewEffect), nameof(ClearDragPreviewEffect))] public class IosClearDragPreviewEffect : PlatformEffect { protected override void OnAttached() { if (Control != null || Element is not View formsView) return; var dragInteraction = formsView.Interactions.OfType<UIDragInteraction>().FirstOrDefault(); if (dragInteraction == null) return; dragInteraction.Delegate = new CustomDragDelegate(formsView); } protected override void OnDetached() { } private class CustomDragDelegate : UIDragInteractionDelegate { private readonly View _targetView; public CustomDragDelegate(View targetView) => _targetView = targetView; public override UIDragItem[] GetItemsForBeginningSession(UIDragInteraction interaction, IUIDragSession session) { var nativeView = Platform.GetRenderer(_targetView).NativeView; // 生成不带背景的元素截图 UIGraphics.BeginImageContextWithOptions(nativeView.Bounds.Size, false, UIScreen.MainScreen.Scale); nativeView.DrawViewHierarchy(nativeView.Bounds, afterScreenUpdates: true); var previewImage = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); var dragItem = new UIDragItem(new NSItemProvider()) { PreviewProvider = () => new UIDragPreview(new UIImageView(previewImage) { BackgroundColor = UIColor.Clear, Bounds = nativeView.Bounds }) }; return new[] { dragItem }; } public override UIDragPreviewParameters GetPreviewForLiftingItem(UIDragInteraction interaction, UIDragItem item, IUIDragSession session) { return new UIDragPreviewParameters { BackgroundColor = UIColor.Clear, ShadowPath = null }; } } }
3. XAML中应用效果
给绑定了DragGestureRecognizer的Grid添加效果即可:
<CollectionView.ItemTemplate> <DataTemplate> <Grid> <!-- 添加这部分效果引用 --> <Grid.Effects> <local:ClearDragPreviewEffect /> </Grid.Effects> <Grid.GestureRecognizers> <DragGestureRecognizer DragStartingCommand="{Binding BindingContext.DragCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}" DragStartingCommandParameter="{Binding}"/> </Grid.GestureRecognizers> <Frame> <Image Source="{Binding ImagePath,Mode=OneWay}" Aspect="AspectFill"/> </Frame> <Label Grid.Row="1" Text="{Binding Name,Mode=OneWay}"/> </Grid> </DataTemplate> </CollectionView.ItemTemplate>
注意事项
- 请将代码中的「你的项目命名空间」替换为自己项目的实际命名空间
- 该修改仅调整拖拽预览的样式,不会影响原有DragCommand的业务逻辑
- 若同时适配Android平台,无需额外修改,该效果仅作用于iOS
内容的提问来源于stack exchange,提问作者takecx
相关产品推荐
相关产品推荐

