Xamarin Forms:在ListView中使用滑动手势删除

7

我想在Xamarin Forms中实现滑动删除功能,我尝试了以下方法。

  1. Wrote a custom renderer for the list view and in the "OnElementChanged" of the renderer am able to access the binded command to the "CustomListView" and am able to add this command to the Swipe Gesture as added below.

       swipeGestureRecognizer = new UISwipeGestureRecognizer (() => {
            if (command == null) {
                Console.WriteLine ("No command set");
                return;}
    
            command.Execute (null);
        });
    

然而,我在访问特定行(滑动行)时遇到了问题,以便我可以使列表视图中滑动行上的按钮可见/隐藏。请问您能否建议实现此功能的方法?


我会将手势添加到ItemTemplate或UITableCell中。 - SKall
你也在安卓上实现了这个吗? - Saket Kumar
3个回答

7

3
Xamarin Forms 实现覆盖了最基本的使用情况。但需要注意的是,很遗憾的是在 Xamarin Forms 中不能向右滑动。而且,你仅能使用最基本的菜单项,无法真正自定义(例如选择不同的字体),这意味着你几乎要立即开始查看自定义渲染器。 - wislon
是的,我发现特别是这方面的文档非常缺乏。 - Sam W

4
您可以像这样做:
    protected override void OnElementChanged (ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged (e);
        var swipeDelegate = new SwipeRecogniserDelegate ();
        swipeGestureRecognizer = new UISwipeGestureRecognizer {
            Direction = UISwipeGestureRecognizerDirection.Left,
            Delegate = swipeDelegate
        };
        swipeGestureRecognizer.AddTarget (o => {
            var startPoint = swipeDelegate.GetStartPoint ();
            Console.WriteLine (startPoint);
            var indexPath = this.Control.IndexPathForRowAtPoint(startPoint);
            if(listView.SwipeCommand != null) {
                listView.SwipeCommand.Execute(indexPath.Row);
            }
        });
        this.Control.AddGestureRecognizer (swipeGestureRecognizer);
        this.listView = (SwipableListView)this.Element;
    }

关键是“SwipeRecogniserDelegate”。它的实现如下所示:

public class SwipeRecogniserDelegate : UIGestureRecognizerDelegate
{
    PointF startPoint;

    public override bool ShouldReceiveTouch (UIGestureRecognizer recognizer, UITouch touch)
    {
        return true;
    }

    public override bool ShouldBegin (UIGestureRecognizer recognizer)
    {
        var swipeGesture = ((UISwipeGestureRecognizer)recognizer);
        this.startPoint = swipeGesture.LocationOfTouch (0, swipeGesture.View);
        return true;
    }

    public PointF GetStartPoint ()
    {
        return startPoint;
    }
}

0

我使用新的Xamarin.Forms SwipeView 成功完成了这个任务。

将当前行传递到CommandParameter中,并在事件处理程序中使用它。

顺便说一下:由于某种原因,SwipeView具有默认的白色BackgroundColor,您可以使用其他颜色覆盖它以匹配您的主题。

Xaml:

            <ListView Margin="-20,0,0,0" x:Name="photosListView" ItemSelected="OnItemSelected" VerticalOptions="FillAndExpand" SeparatorColor="Gray" VerticalScrollBarVisibility="Default" HasUnevenRows="true"  SeparatorVisibility="Default" Background="{StaticResource PrimaryDark}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <SwipeView BackgroundColor="{StaticResource PrimaryDark}" >
                                <SwipeView.RightItems>
                                    <SwipeItems>
                                        <SwipeItem Text="Delete" BackgroundColor="LightPink" Clicked="OnDeleteRow" CommandParameter="{Binding .}" />
                                    </SwipeItems>
                                </SwipeView.RightItems>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>

                                    <StackLayout Orientation="Horizontal">
                                        <CheckBox IsVisible="{Binding SelectEnabled}" Color="{StaticResource White}" IsChecked="{Binding Selected}" Margin="20,0,-15,0"  CheckedChanged="OnItemCheckedChanged" />
                                        <Grid WidthRequest="70" HeightRequest="50">
                                            <Grid.Margin>
                                                <OnPlatform x:TypeArguments="Thickness" Android="15,0,0,0" iOS="10,0,0,0" />
                                            </Grid.Margin>
                                            <Image Aspect="AspectFill"  Source="{Binding ThumbImageSource}" HorizontalOptions="Fill" />
                                        </Grid>
                                    </StackLayout>

                                    <StackLayout Grid.Column="1" Spacing="0" Padding="0" Margin="0,5,0,0">
                                        <Label Text="{Binding Photo.Description}" TextColor="{StaticResource TextColour}" FontSize="16" FontAttributes="Bold"  />
                                        <Label Text="{Binding DateTakenString}" TextColor="{StaticResource TextColour}" FontSize="14" />
                                    </StackLayout>
                                </Grid>
                            </SwipeView>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>

cs:

    public async void OnDeleteRow(object sender, EventArgs e)
    {
        if (await GetDeleteRowConfirmationFromUser())
        {
            SwipeItem si = sender as SwipeItem;
            PhotoListItem itemToDelete = si.CommandParameter as PhotoListItem;
            LocalDatabaseService db = new LocalDatabaseService();
            db.DeletePhoto(itemToDelete.Photo);
            _listItems.Remove(itemToDelete);
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接