[Android] Context actions menu is now updated when changing cells. (#6460) fixes...
authorGuido Neele <guido.neele@xs4all.nl>
Thu, 22 Aug 2019 11:23:55 +0000 (13:23 +0200)
committerRui Marinho <me@ruimarinho.net>
Thu, 22 Aug 2019 11:23:55 +0000 (12:23 +0100)
* Bugfix of issue 1455. Force SupportActionMode Menu to recreate when it's active and another cell is clicked.

* Added UITest

* Added an assert which checks if the new menu items have been updated.

* Correct project file

* Added a platform specific BindableProperty for the ViewCell to use ContextActions in LegacyMode.

* Update Xamarin.Forms.Core/PlatformConfiguration/AndroidSpecific/ViewCell.cs

Co-Authored-By: Gerald Versluis <github@geraldversluis.nl>
* Update Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml.cs

Co-Authored-By: Gerald Versluis <github@geraldversluis.nl>
* Update Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems

Co-Authored-By: Gerald Versluis <github@geraldversluis.nl>
.gitignore
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Core/Cells/Cell.cs
Xamarin.Forms.Core/PlatformConfiguration/AndroidSpecific/ViewCell.cs [new file with mode: 0644]
Xamarin.Forms.Platform.Android/CellAdapter.cs
Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs

index 1637be7..468b5de 100644 (file)
@@ -67,4 +67,5 @@ tools/
 !tools/mdoc/**/*
 caketools/
 *.binlog
-.ionide/**
\ No newline at end of file
+.ionide/**
+/.nuspec
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml
new file mode 100644 (file)
index 0000000..9046725
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<controls:TestContentPage x:Class="Xamarin.Forms.Controls.Issues.Issue1455"
+                          xmlns="http://xamarin.com/schemas/2014/forms"
+                          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+                          xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
+                          xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
+                          xmlns:d="http://xamarin.com/schemas/2014/forms/design"
+                          xmlns:local="clr-namespace:Xamarin.Forms.Controls.Issues"
+                          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+                          x:Name="Issue1455Page"
+                          mc:Ignorable="d">
+    <controls:TestContentPage.Resources>
+        <ResourceDictionary>
+            <DataTemplate x:Key="Temp1">
+                <ViewCell android:ViewCell.IsContextActionsLegacyModeEnabled="{Binding BindingContext.IsContextActionsLegacyModeEnabled, Source={x:Reference Issue1455Page}}}">
+                    <ViewCell.ContextActions>
+                        <MenuItem Text="{Binding Item1Text}" />
+                        <MenuItem Text="{Binding Item2Text}" />
+                        <MenuItem Text="{Binding Item3Text}" />
+                        <MenuItem Text="{Binding Item4Text}" />
+                    </ViewCell.ContextActions>
+                    <Grid>
+                        <Label Text="{Binding Text}" />
+                    </Grid>
+                </ViewCell>
+            </DataTemplate>
+            <DataTemplate x:Key="Temp2">
+                <ViewCell android:ViewCell.IsContextActionsLegacyModeEnabled="{Binding BindingContext.IsContextActionsLegacyModeEnabled, Source={x:Reference Issue1455Page}}}">
+                    <ViewCell.ContextActions>
+                        <MenuItem Text="{Binding Item1Text}" />
+                        <MenuItem Text="{Binding Item2Text}" />
+                    </ViewCell.ContextActions>
+                    <Grid>
+                        <Label Text="{Binding Text}" />
+                    </Grid>
+                </ViewCell>
+            </DataTemplate>
+
+            <local:Issue1455DataTemplateSelector x:Key="Issue1455DataTemplateSelector"
+                                                 Temp1Template="{StaticResource Temp1}"
+                                                 Temp2Template="{StaticResource Temp2}" />
+        </ResourceDictionary>
+    </controls:TestContentPage.Resources>
+    <controls:TestContentPage.ToolbarItems>
+        <ToolbarItem Command="{Binding ToggleLegacyMode}" Text="Toggle LegacyMode" />
+    </controls:TestContentPage.ToolbarItems>
+    <controls:TestContentPage.Content>
+        <ListView HorizontalOptions="FillAndExpand"
+                  ItemTemplate="{StaticResource Issue1455DataTemplateSelector}"
+                  ItemsSource="{Binding Items}"
+                  VerticalOptions="FillAndExpand" />
+    </controls:TestContentPage.Content>
+</controls:TestContentPage>
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1455.xaml.cs
new file mode 100644 (file)
index 0000000..12c5f58
--- /dev/null
@@ -0,0 +1,158 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml;
+using System.Windows.Input;
+
+#if UITEST
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Github, 1455, "Context action are not changed when selected item changed on Android", PlatformAffected.Android)]
+       public partial class Issue1455 : TestContentPage
+       {
+               public Issue1455()
+               {
+#if APP
+                       InitializeComponent();
+#endif
+               }
+
+               MyViewModel ViewModel
+               {
+                       get {
+                               return (MyViewModel)BindingContext;
+                       }
+               }
+
+               protected override void Init()
+               {
+                       BindingContext = new MyViewModel();
+               }
+
+
+               [Preserve(AllMembers = true)]
+               public class MyViewModel : PropertyChangedBase
+               {
+                       bool _isContextActionsLegacyModeEnabled;
+
+                       public bool IsContextActionsLegacyModeEnabled
+                       {
+                               get
+                               {
+                                       return _isContextActionsLegacyModeEnabled;
+                               }
+                               set
+                               {
+                                       _isContextActionsLegacyModeEnabled = value;
+                                       OnPropertyChanged();
+                               }
+                       }
+
+                       public ICommand ToggleLegacyMode { get; }
+
+                       public ObservableCollection<ContextMenuItem> Items { get; private set; }
+
+                       public MyViewModel()
+                       {
+                               IsContextActionsLegacyModeEnabled = false;
+
+                               ToggleLegacyMode = new Command(() => IsContextActionsLegacyModeEnabled = !IsContextActionsLegacyModeEnabled);
+
+                               Items = new ObservableCollection<ContextMenuItem>();
+
+                               Items.Add(new ContextMenuItem { Item1Text = "Lorem", Text = "Cell 1", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Ipsum", Text = "Cell 2", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Dictum", Text = "Cell 3", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Vestibulum", Text = "Cell 4", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Hendrerit", Text = "Cell 5", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Posuere", Text = "Cell 6", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Bibendum", Text = "Cell 7", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Vivamus", Text = "Cell 8", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Enim", Text = "Cell 9", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Quis", Text = "Cell 10", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Phasellus", Text = "Cell 11", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Pretium", Text = "Cell 12", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Aliquam", Text = "Cell 13", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Tristique", Text = "Cell 14", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Malesuada", Text = "Cell 15", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Dolor", Text = "Cell 16", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Id", Text = "Cell 17", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Orci", Text = "Cell 18", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Diam", Text = "Cell 19", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Nibh", Text = "Cell 20", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Non", Text = "Cell 21", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Aliquam", Text = "Cell 22", Type = ContextMenuItemType.Temp2 });
+                               Items.Add(new ContextMenuItem { Item1Text = "Ultrices", Text = "Cell 23", Type = ContextMenuItemType.Temp1 });
+                               Items.Add(new ContextMenuItem { Item2Text = "Vulputate", Text = "Cell 24", Type = ContextMenuItemType.Temp2 });
+                       }
+               }
+
+#if UITEST && __ANDROID__
+               [Test]
+               [Category(Core.UITests.UITestCategories.ListView)]
+               public void RefreshContextActions()
+               {
+                       RunningApp.WaitForElement("Cell 1");
+                       RunningApp.Screenshot("I am at Issue 1455");
+                       RunningApp.TouchAndHold(q => q.Marked("Cell 4"));
+                       RunningApp.Screenshot("Long Press Cell 4 to show context actions");
+                       RunningApp.Tap(q => q.Marked("Cell 5"));
+                       RunningApp.Screenshot("Clicked another cell and changed menu items");
+
+                       Assert.AreEqual(1, RunningApp.Query(c => c.Marked("Hendrerit")).Length);
+
+                       RunningApp.Back();
+
+                       RunningApp.WaitForElement("Toggle LegacyMode");
+                       RunningApp.Tap(q => q.Marked("Toggle LegacyMode"));
+
+                       RunningApp.TouchAndHold(q => q.Marked("Cell 4"));
+                       RunningApp.Screenshot("Long Press Cell 4 to show context actions");
+                       RunningApp.Tap(q => q.Marked("Cell 5"));
+                       RunningApp.Screenshot("Clicked another cell and changed menu items");
+
+                       Assert.AreEqual(1, RunningApp.Query(c => c.Marked("Vestibulum")).Length);
+               }
+#endif
+       }
+
+       public enum ContextMenuItemType
+       {
+               Temp1,
+               Temp2
+       }
+
+       [Preserve(AllMembers = true)]
+       public class ContextMenuItem
+       {
+               public ContextMenuItemType Type { get; set; } = ContextMenuItemType.Temp1;
+               public string Item1Text { get; set; } = "Text 1";
+               public string Item2Text { get; set; } = "Text 2";
+               public string Item3Text { get; set; } = "Text 3";
+               public string Item4Text { get; set; } = "Text 4";
+               public string Text { get; set; }
+       }
+
+       [Preserve(AllMembers = true)]
+       public class Issue1455DataTemplateSelector : DataTemplateSelector
+       {
+               public DataTemplate Temp1Template { get; set; }
+               public DataTemplate Temp2Template { get; set; }
+
+               protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
+               {
+                       return ((ContextMenuItem)item).Type == ContextMenuItemType.Temp1 ? Temp1Template : Temp2Template;
+               }
+       }
+}
index f6022d6..b54e5ff 100644 (file)
@@ -9,6 +9,10 @@
     <Import_RootNamespace>Xamarin.Forms.Controls.Issues</Import_RootNamespace>
   </PropertyGroup>
   <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Issue1455.xaml.cs">
+      <DependentUpon>Issue1455.xaml</DependentUpon>
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)CollectionViewHeaderFooterString.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)CollectionViewHeaderFooterTemplate.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)CollectionViewHeaderFooterView.cs" />
@@ -16,7 +20,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Issue3475.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue6945.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue5046.xaml.cs">
-      <DependentUpon>Issue5046.xaml</DependentUpon>
+      <DependentUpon>Issue5046.xaml</DependentUpon>    
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)Issue6609.cs" />
     </Compile>
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1455.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </EmbeddedResource>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue5268.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
index c8898d6..ac88494 100644 (file)
@@ -82,6 +82,8 @@ namespace Xamarin.Forms
                        get { return _contextActions != null && _contextActions.Count > 0 && IsEnabled; }
                }
 
+               public bool IsContextActionsLegacyModeEnabled { get; set; } = false;
+
                public double Height
                {
                        get { return _height; }
diff --git a/Xamarin.Forms.Core/PlatformConfiguration/AndroidSpecific/ViewCell.cs b/Xamarin.Forms.Core/PlatformConfiguration/AndroidSpecific/ViewCell.cs
new file mode 100644 (file)
index 0000000..8462e8e
--- /dev/null
@@ -0,0 +1,37 @@
+namespace Xamarin.Forms.PlatformConfiguration.AndroidSpecific
+{
+       using System;
+       using FormsCell = Forms.Cell;
+
+       public static class ViewCell
+       {
+               public static readonly BindableProperty IsContextActionsLegacyModeEnabledProperty = BindableProperty.Create("IsContextActionsLegacyModeEnabled", typeof(bool), typeof(Forms.ViewCell), false, propertyChanged: OnIsContextActionsLegacyModeEnabledPropertyChanged);
+
+               private static void OnIsContextActionsLegacyModeEnabledPropertyChanged(BindableObject element, object oldValue, object newValue)
+               {
+                       var cell = element as FormsCell;
+                       cell.IsContextActionsLegacyModeEnabled = (bool)newValue;
+               }
+
+               public static bool GetIsContextActionsLegacyModeEnabled(BindableObject element)
+               {
+                       return (bool)element.GetValue(IsContextActionsLegacyModeEnabledProperty);
+               }
+
+               public static void SetIsContextActionsLegacyModeEnabled(BindableObject element, bool value)
+               {
+                       element.SetValue(IsContextActionsLegacyModeEnabledProperty, value);
+               }
+
+               public static bool GetIsContextActionsLegacyModeEnabled(this IPlatformElementConfiguration<Android, FormsCell> config)
+               {
+                       return GetIsContextActionsLegacyModeEnabled(config.Element);
+               }
+
+               public static IPlatformElementConfiguration<Android, FormsCell> SetIsContextActionsLegacyModeEnabled(this IPlatformElementConfiguration<Android, FormsCell> config, bool value)
+               {
+                       SetIsContextActionsLegacyModeEnabled(config.Element, value);
+                       return config;
+               }
+       }
+}
index 520c9f5..0ac0fde 100644 (file)
@@ -193,7 +193,7 @@ namespace Xamarin.Forms.Platform.Android
                        {
                                MenuItem action = ActionModeContext.ContextActions[i];
 
-                               IMenuItem item = menu.Add(global::Android.Views.Menu.None, i,global::Android.Views.Menu.None, action.Text);
+                               IMenuItem item = menu.Add(global::Android.Views.Menu.None, i, global::Android.Views.Menu.None, action.Text);
 
                                _ = _context.ApplyDrawableAsync(action, MenuItem.IconImageSourceProperty, iconDrawable =>
                                {
@@ -235,7 +235,10 @@ namespace Xamarin.Forms.Platform.Android
 
                                ActionModeContext = cell;
 
-                               _actionMode?.Invalidate();
+                               if(ActionModeContext.IsContextActionsLegacyModeEnabled == false)
+                                       _actionModeNeedsUpdates = true;
+
+                _actionMode?.Invalidate();
                                _supportActionMode?.Invalidate();
                        }
                        else
index daac77f..c335f8f 100644 (file)
@@ -5,6 +5,7 @@ using Xamarin.Forms.Internals;
 using System;
 using System.Linq;
 using Android.Runtime;
+using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
 
 namespace Xamarin.Forms.Platform.Android
 {
@@ -31,6 +32,8 @@ namespace Xamarin.Forms.Platform.Android
                        }
                        else if (ParentView is ListView)
                        {
+                               cell.IsContextActionsLegacyModeEnabled = item.On<PlatformConfiguration.Android>().GetIsContextActionsLegacyModeEnabled();
+
                                unevenRows = ListView.HasUnevenRowsProperty;
                                rowHeight = ListView.RowHeightProperty;
                        }