【问题标题】:Xamarin Forms - Listview view cell swipe left and right events using xamalXamarin Forms - Listview viewcell 使用 xaml 向左和向右滑动事件
【发布时间】:2016-08-04 02:21:10
【问题描述】:

我需要为 listview viewcell 左右滑动手势编写代码(或 XAML)。

向左滑动时,从列表视图(或可观察集合)列表中删除记录并更新列表视图中剩余的列表项。向右滑动时,保存记录。

【问题讨论】:

    标签: xaml xamarin xamarin.forms gestures


    【解决方案1】:

    我是用cs代码做的,你可以在xaml上试试。

    首先,您应该使用手势构建滑动组件

    SwipeGestureGrid.cs

    public class SwipeGestureGrid : Grid
        {
            #region Private Member
            private double _gestureX { get; set; }
            private double _gestureY { get; set; }
            private bool IsSwipe { get; set; }
            #endregion
            #region Public Member
            #region Events
            #region Tapped
            public event EventHandler Tapped;
            protected void OnTapped(EventArgs e)
            {
                if (Tapped != null)
                    Tapped(this, e);
            }
            #endregion
            #region SwipeUP
            public event EventHandler SwipeUP;
            protected void OnSwipeUP(EventArgs e)
            {
                if (SwipeUP != null)
                    SwipeUP(this, e);
            }
            #endregion
            #region SwipeDown
            public event EventHandler SwipeDown;
            protected void OnSwipeDown(EventArgs e)
            {
                if (SwipeDown != null)
                    SwipeDown(this, e);
            }
            #endregion
            #region SwipeRight
            public event EventHandler SwipeRight;
            protected void OnSwipeRight(EventArgs e)
            {
                if (SwipeRight != null)
                    SwipeRight(this, e);
            }
            #endregion
            #region SwipeLeft
            public event EventHandler SwipeLeft;
            protected void OnSwipeLeft(EventArgs e)
            {
                if (SwipeLeft != null)
                    SwipeLeft(this, e);
            }
            #endregion
            #endregion
            public double Height
            {
                get
                {
                    return HeightRequest;
                }
                set
                {
                    HeightRequest = value;
                }
            }
            public double Width
            {
                get
                {
                    return WidthRequest;
                }
                set
                {
                    WidthRequest = value;
                }
            }
            #endregion
            public SwipeGestureGrid()
            {
                PanGestureRecognizer panGesture = new PanGestureRecognizer();
                panGesture.PanUpdated += PanGesture_PanUpdated;
    
                TapGestureRecognizer tapGesture = new TapGestureRecognizer();
                tapGesture.Tapped += TapGesture_Tapped;
    
                GestureRecognizers.Add(panGesture);
                GestureRecognizers.Add(tapGesture);
            }
    
            private void TapGesture_Tapped(object sender, EventArgs e)
            {
                try
                {
                    if (!IsSwipe)
                        OnTapped(null);
    
                    IsSwipe = false;
                }
                catch (Exception ex)
                {
    
                }
            }
    
            private void PanGesture_PanUpdated(object sender, PanUpdatedEventArgs e)
            {
                try
                {
                    switch (e.StatusType)
                    {
                        case GestureStatus.Running:
                            {
                                _gestureX = e.TotalX;
                                _gestureY = e.TotalY;
                            }
                            break;
                        case GestureStatus.Completed:
                            {
                                IsSwipe = true;
                                //Debug.WriteLine("{0}  {1}", _gestureX, _gestureY);
                                if (Math.Abs(_gestureX) > Math.Abs(_gestureY))
                                {
                                    if (_gestureX > 0)
                                    {
                                        OnSwipeRight(null);
                                    }
                                    else
                                    {
                                        OnSwipeLeft(null);
                                    }
                                }
                                else
                                {
                                    if (_gestureY > 0)
                                    {
                                        OnSwipeDown(null);
                                    }
                                    else
                                    {
                                        OnSwipeUP(null);
                                    }
                                }
                            }
                            break;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }
    

    接下来在列表视图中使用数据模板并为 Gesturecompoment 附加事件

    页面.cs

    ListView lsvData = new ListView()
            {
                VerticalOptions = LayoutOptions.Fill,
                HorizontalOptions = LayoutOptions.Fill,
                BackgroundColor = Color.White,
                HasUnevenRows = true,
            };
            List<string> lstData = new List<string>();
            public Pages()
            {
                #region DataTemplate
                DataTemplate ListDataTemplate = new DataTemplate(() =>
                {
                    #region DataArea of Template
                    SwipeGestureGrid gridData = new SwipeGestureGrid()
                    {
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        VerticalOptions = LayoutOptions.FillAndExpand,
                        HeightRequest = 60,
                        RowDefinitions =
                            {
                                new RowDefinition { },
                            },
                        ColumnDefinitions =
                            {
                                new ColumnDefinition { },
                            }
                    };
                    #endregion
                    #region Base of Template
                    Grid gridBase = new Grid()
                    {
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        VerticalOptions = LayoutOptions.FillAndExpand,
                        HeightRequest = 60,
                        RowDefinitions =
                        {
                            new RowDefinition { },
                        },
                        ColumnDefinitions =
                        {
                            new ColumnDefinition { },                                                   //Put Cells Data here
                            new ColumnDefinition { Width = new GridLength(0, GridUnitType.Absolute)},   //Button for Cells here
                        },
                    };
                    #endregion
                    Label lblText = new Label
                    {
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        VerticalOptions = LayoutOptions.FillAndExpand,
                        FontAttributes = FontAttributes.Bold,
                        VerticalTextAlignment = TextAlignment.End,
                        TextColor = Color.Black,
                        BackgroundColor = Color.Silver,
                        LineBreakMode = LineBreakMode.TailTruncation,
                        FontSize = 18,
                    };
                    lblText.SetBinding(Label.TextProperty, ".");
    
                    ImageButton btnCellDelete = new ImageButton() { Source = "Delete" };
    
                    gridData.Children.Add(lblText, 0, 0);
    
                    gridBase.Children.Add(gridData, 0, 0);
                    gridBase.Children.Add(btnCellDelete, 1, 0);
    
                    gridData.SwipeLeft += GridTemplate_SwipeLeft;
                    gridData.SwipeRight += GridTemplate_SwipeRight; ;
                    gridData.Tapped += GridTemplate_Tapped; ;
                    btnCellDelete.Clicked += BtnCellDelete_Clicked; ;
    
                    return new ViewCell
                    {
                        View = gridBase,
                        Height = 60,
                    };
                });
    
                #endregion
                for (int i = 1; i <= 100; i++)
                {
                    lstData.Add(i.ToString());
                }
                lsvData.ItemTemplate = ListDataTemplate;
                lsvData.ItemsSource = lstData;
                Content = lsvData;
            }
    

    事件

    向左滑动显示删除按钮

    private void GridTemplate_SwipeLeft(object sender, EventArgs e)
        {
            try
            {
                if (sender is SwipeGestureGrid)
                {
                    var templateGrid = ((SwipeGestureGrid)sender).Parent;
                    if (templateGrid != null && templateGrid is Grid)
                    {
                        var CellTemplateGrid = (Grid)templateGrid;
                        CellTemplateGrid.ColumnDefinitions[1].Width = new GridLength(60, GridUnitType.Absolute);
                    }
                }
    
            }
            catch (Exception ex)
            {
    
            }
        }
    

    向右滑动隐藏删除按钮

    private void GridTemplate_SwipeRight(object sender, EventArgs e)
        {
            try
            {
                if (sender is SwipeGestureGrid)
                {
                    var templateGrid = ((SwipeGestureGrid)sender).Parent;
                    if (templateGrid != null && templateGrid is Grid)
                    {
                        var CellTemplateGrid = (Grid)templateGrid;
                        CellTemplateGrid.ColumnDefinitions[1].Width = new GridLength(0, GridUnitType.Absolute);
                    }
                }
            }
            catch (Exception ex)
            {
    
            }
        }
    

    删除按钮点击事件

    private void BtnCellDelete_Clicked(object sender, EventArgs e)
        {
            try
            {
                if (sender is ImageButton)
                {
                    var templateGrid = ((ImageButton)sender);
                    //templateGrid.Parent = gridBase
                    //templateGrid.Parent.Parent = cell
                    if (templateGrid.Parent != null && templateGrid.Parent.Parent != null && templateGrid.Parent.Parent.BindingContext != null && templateGrid.Parent.Parent.BindingContext is string)
                    {
                        var deletedate = templateGrid.Parent.Parent.BindingContext as string;
                        lstData.RemoveAll(f => f == deletedate);
                        lsvData.ItemsSource = null;
                        lsvData.ItemsSource = lstData;
                    }
                }
            }
            catch (Exception ex)
            {
    
            }
        }
    

    源码可以在我的github找到 https://github.com/act70255/ListViewSwipeGesture

    【讨论】:

    【解决方案2】:

    我对 James Lin 的课程进行了重新设计,使其基于命令,使其对 MVVM 友好。

    public class SwipeGestureGrid : Grid
    {
        public static readonly BindableProperty SwipeLeftCommandProperty = 
            BindableProperty.Create("SwipeLeftCommand", typeof(ICommand), typeof(ICommand), null);
        public static readonly BindableProperty SwipeRightCommandProperty =
            BindableProperty.Create("SwipeRightCommand", typeof(ICommand), typeof(ICommand), null);
        public static readonly BindableProperty SwipeUpCommandProperty =
            BindableProperty.Create("SwipeUpCommand", typeof(ICommand), typeof(ICommand), null);
        public static readonly BindableProperty SwipeDownCommandProperty =
            BindableProperty.Create("SwipeDownCommand", typeof(ICommand), typeof(ICommand), null);
        public static readonly BindableProperty TappedCommandProperty =
            BindableProperty.Create("TappedCommand", typeof(ICommand), typeof(ICommand), null);
    
        private double _gestureStartX;
        private double _gestureStartY;
        private double _gestureDistanceX;
        private double _gestureDistanceY;
    
        public double GestureStartX
        {
            get => _gestureStartX;
            private set
            {
                _gestureStartX = value;
                OnPropertyChanged();
            }
        }
    
        public double GestureStartY
        {
            get => _gestureStartY;
            private set
            {
                _gestureStartY = value;
                OnPropertyChanged();
            }
        }
    
        private bool IsSwipe { get; set; }
    
        public ICommand TappedCommand
        {
            get => (ICommand) GetValue(TappedCommandProperty);
            set => SetValue(TappedCommandProperty, value);
        }
        public ICommand SwipeLeftCommand
        {
            get => (ICommand)GetValue(SwipeLeftCommandProperty);
            set => SetValue(SwipeLeftCommandProperty, value);
        }
        public ICommand SwipeRightCommand
        {
            get => (ICommand)GetValue(SwipeRightCommandProperty);
            set => SetValue(SwipeRightCommandProperty, value);
        }
        public ICommand SwipeUpCommand
        {
            get => (ICommand)GetValue(SwipeUpCommandProperty);
            set => SetValue(SwipeUpCommandProperty, value);
        }
        public ICommand SwipeDownCommand
        {
            get => (ICommand)GetValue(SwipeDownCommandProperty);
            set => SetValue(SwipeDownCommandProperty, value);
        }
    
        public SwipeGestureGrid()
        {
            var panGesture = new PanGestureRecognizer();
            panGesture.PanUpdated += PanGesture_PanUpdated;
    
            var tapGesture = new TapGestureRecognizer();
            tapGesture.Tapped += TapGesture_Tapped;
    
            GestureRecognizers.Add(panGesture);
            GestureRecognizers.Add(tapGesture);
        }
    
        private void TapGesture_Tapped(object sender, EventArgs e)
        {
            try
            {
                if (!IsSwipe)
                    TappedCommand?.Execute(this);
    
                IsSwipe = false;
            }
            catch (Exception ex)
            {
    
            }
        }
    
        private void PanGesture_PanUpdated(object sender, PanUpdatedEventArgs e)
        {
                switch (e.StatusType)
                {
                    case GestureStatus.Started:
                        {
                            GestureStartX = e.TotalX;
                            GestureStartY = e.TotalY;
                        }
                        break;
                    case GestureStatus.Running:
                        {
                            _gestureDistanceX = e.TotalX;
                            _gestureDistanceY = e.TotalY;
                        }
                        break;
                    case GestureStatus.Completed:
                        {
                            IsSwipe = true;
    
                            if (Math.Abs(_gestureDistanceX) > Math.Abs(_gestureDistanceY))
                            {
                                if (_gestureDistanceX > 0)
                                {
                                    SwipeRightCommand?.Execute(this);
                                }
                                else
                                {
                                    SwipeLeftCommand?.Execute(null);
                                }
                            }
                            else
                            {
                                if (_gestureDistanceY > 0)
                                {
                                    SwipeDownCommand?.Execute(null);
                                }
                                else
                                {
                                    SwipeUpCommand?.Execute(null);
                                }
                            }
                        }
                        break;
                }
        }
    }
    

    我们在 DataTemplate 中为 ScrollableListView 使用它:

    <DataTemplate x:Key="ThreeRowTemplateTemplate" x:DataType="{x:Type tracking:TrackingItem}">
                <ViewCell>
                    <controls:SwipeGestureGrid ColumnSpacing="0" RowSpacing="0" SwipeLeftCommand="{Binding SwipeLeftCommand}">
    

    在这种情况下,绑定命令必须在 TrackingItem 上。它似乎工作得很好,但检测有时有点不稳定 - 可能与 ScrollableListView 的手势处理存在冲突。

    【讨论】:

      猜你喜欢
      • 2015-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      相关资源
      最近更新 更多