зеркало из https://github.com/DeGsoft/maui-linux.git
[Shell] Fix back button behavior so that it only applies the property you've set opposed to replacing the entire thing (#6762)
* Fix backbutton behavior to only apply what you've set opposed to replacing everything * - move GetPropertyIfSet to Core.Internals * - make GetPropertyIfSet public. fixes #5744
This commit is contained in:
Родитель
659fa4faac
Коммит
9311b5f489
|
@ -0,0 +1,203 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms.PlatformConfiguration;
|
||||
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
|
||||
using System.Threading;
|
||||
using System.ComponentModel;
|
||||
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.None, 0, "Shell Back Button Behavior Test",
|
||||
PlatformAffected.All)]
|
||||
#if UITEST
|
||||
[NUnit.Framework.Category(UITestCategories.Shell)]
|
||||
#endif
|
||||
public class ShellBackButtonBehavior : TestShell
|
||||
{
|
||||
const string EntryCommandParameter = "EntryCommandParameter";
|
||||
const string ToggleBehaviorId = "ToggleBehaviorId";
|
||||
const string ToggleCommandId = "ToggleCommandId";
|
||||
const string ToggleCommandCanExecuteId = "ToggleCommandCanExecuteId";
|
||||
const string ToggleIconId = "ToggleIconId";
|
||||
const string ToggleIsEnabledId = "ToggleIsEnabledId";
|
||||
const string ToggleTextId = "ToggleTextId";
|
||||
const string CommandResultId = "CommandResult";
|
||||
const string PushPageId = "PushPageId";
|
||||
|
||||
protected override void Init()
|
||||
{
|
||||
AddContentPage(new BackButtonPage());
|
||||
}
|
||||
|
||||
public class BackButtonPage : ContentPage
|
||||
{
|
||||
BackButtonBehavior behavior = new BackButtonBehavior();
|
||||
Entry _commandParameter;
|
||||
Label _commandResult = new Label() { AutomationId = CommandResultId };
|
||||
|
||||
public BackButtonPage()
|
||||
{
|
||||
_commandParameter = new Entry()
|
||||
{
|
||||
Placeholder = "Command Parameter",
|
||||
AutomationId = EntryCommandParameter
|
||||
};
|
||||
|
||||
_commandParameter.TextChanged += (_, __) =>
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(_commandParameter.Text))
|
||||
behavior.ClearValue(BackButtonBehavior.CommandParameterProperty);
|
||||
else
|
||||
behavior.CommandParameter = _commandParameter.Text;
|
||||
};
|
||||
|
||||
StackLayout layout = new StackLayout();
|
||||
|
||||
layout.Children.Add(new Label()
|
||||
{
|
||||
Text = "Test setting different Back Button Behavior properties"
|
||||
});
|
||||
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Toggle Behavior",
|
||||
Command = new Command(ToggleBehavior),
|
||||
AutomationId = ToggleBehaviorId
|
||||
|
||||
});
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Toggle Command",
|
||||
Command = new Command(ToggleCommand),
|
||||
AutomationId = ToggleCommandId
|
||||
});
|
||||
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Toggle Command Can Execute",
|
||||
Command = new Command(ToggleCommandIsEnabled),
|
||||
AutomationId = ToggleCommandCanExecuteId
|
||||
});
|
||||
|
||||
layout.Children.Add(_commandParameter);
|
||||
layout.Children.Add(_commandResult);
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Toggle Text",
|
||||
Command = new Command(ToggleBackButtonText),
|
||||
AutomationId = ToggleTextId
|
||||
});
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Toggle Icon",
|
||||
Command = new Command(ToggleIcon),
|
||||
AutomationId = ToggleIconId
|
||||
});
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Toggle Is Enabled",
|
||||
Command = new Command(ToggleIsEnabled),
|
||||
AutomationId = ToggleIsEnabledId
|
||||
});
|
||||
|
||||
layout.Children.Add(new Button()
|
||||
{
|
||||
Text = "Push Page",
|
||||
Command = new Command(PushPage),
|
||||
AutomationId = PushPageId
|
||||
});
|
||||
|
||||
|
||||
Content = layout;
|
||||
ToggleBehavior();
|
||||
}
|
||||
|
||||
async void PushPage(object obj)
|
||||
{
|
||||
await Navigation.PushAsync(new BackButtonPage());
|
||||
}
|
||||
|
||||
public void ToggleBehavior()
|
||||
{
|
||||
if (this.IsSet(Shell.BackButtonBehaviorProperty))
|
||||
this.ClearValue(Shell.BackButtonBehaviorProperty);
|
||||
else
|
||||
this.SetValue(Shell.BackButtonBehaviorProperty, behavior);
|
||||
}
|
||||
|
||||
public void ToggleCommand()
|
||||
{
|
||||
if (behavior.Command == null)
|
||||
behavior.Command = new Command<string>(result =>
|
||||
{
|
||||
_commandResult.Text = result;
|
||||
}, (_) => canExecute);
|
||||
else
|
||||
behavior.ClearValue(BackButtonBehavior.CommandProperty);
|
||||
}
|
||||
|
||||
bool canExecute = true;
|
||||
public void ToggleCommandIsEnabled()
|
||||
{
|
||||
canExecute = !canExecute;
|
||||
if (behavior.Command is Command command)
|
||||
command.ChangeCanExecute();
|
||||
}
|
||||
|
||||
public void ToggleBackButtonText()
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(behavior.TextOverride))
|
||||
behavior.ClearValue(BackButtonBehavior.TextOverrideProperty);
|
||||
else
|
||||
behavior.TextOverride = "Text";
|
||||
}
|
||||
|
||||
public void ToggleIcon()
|
||||
{
|
||||
if (behavior.IsSet(BackButtonBehavior.IconOverrideProperty))
|
||||
behavior.ClearValue(BackButtonBehavior.IconOverrideProperty);
|
||||
else
|
||||
behavior.IconOverride = "coffee.png";
|
||||
|
||||
}
|
||||
|
||||
public void ToggleIsEnabled()
|
||||
{
|
||||
behavior.IsEnabled = !behavior.IsEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UITEST && (__IOS__ || __ANDROID__)
|
||||
[Test]
|
||||
public void CommandTest()
|
||||
{
|
||||
RunningApp.Tap(ToggleCommandId);
|
||||
RunningApp.EnterText(EntryCommandParameter, "parameter");
|
||||
ShowFlyout();
|
||||
|
||||
var commandResult = RunningApp.WaitForElement(CommandResultId)[0].ReadText();
|
||||
|
||||
Assert.AreEqual(commandResult, "parameter");
|
||||
RunningApp.EnterText(EntryCommandParameter, "canexecutetest");
|
||||
RunningApp.Tap(ToggleCommandCanExecuteId);
|
||||
|
||||
commandResult = RunningApp.WaitForElement(CommandResultId)[0].ReadText();
|
||||
Assert.AreEqual(commandResult, "parameter");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -637,8 +637,33 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
Items.Add(item);
|
||||
return page;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ShellItem AddContentPage(ContentPage contentPage)
|
||||
{
|
||||
ContentPage page = new ContentPage();
|
||||
ShellItem item = new ShellItem()
|
||||
{
|
||||
Items =
|
||||
{
|
||||
new ShellSection()
|
||||
{
|
||||
Items =
|
||||
{
|
||||
new ShellContent()
|
||||
{
|
||||
Content = contentPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Items.Add(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
#if UITEST
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<Compile Include="$(MSBuildThisFileDirectory)Issue7061.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue7111.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellGestures.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellBackButtonBehavior.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ShellInsets.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewGrouping.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue5412.cs" />
|
||||
|
|
|
@ -56,5 +56,16 @@ namespace Xamarin.Forms
|
|||
Binding binding = Binding.Create(sourceProperty, mode, converter, stringFormat: stringFormat);
|
||||
self.SetBinding(targetProperty, binding);
|
||||
}
|
||||
|
||||
public static T GetPropertyIfSet<T>(this BindableObject bindableObject, BindableProperty bindableProperty, T returnIfNotSet)
|
||||
{
|
||||
if (bindableObject == null)
|
||||
return returnIfNotSet;
|
||||
|
||||
if (bindableObject.IsSet(bindableProperty))
|
||||
return (T)bindableObject.GetValue(bindableProperty);
|
||||
|
||||
return returnIfNotSet;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,11 +10,13 @@ using System;
|
|||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ActionBarDrawerToggle = Android.Support.V7.App.ActionBarDrawerToggle;
|
||||
using AView = Android.Views.View;
|
||||
using LP = Android.Views.ViewGroup.LayoutParams;
|
||||
using R = Android.Resource;
|
||||
using Toolbar = Android.Support.V7.Widget.Toolbar;
|
||||
using ADrawableCompat = Android.Support.V4.Graphics.Drawable.DrawableCompat;
|
||||
|
||||
namespace Xamarin.Forms.Platform.Android
|
||||
{
|
||||
|
@ -47,7 +49,6 @@ namespace Xamarin.Forms.Platform.Android
|
|||
//assume the default
|
||||
Color _tintColor = Color.Default;
|
||||
Toolbar _toolbar;
|
||||
string _defaultNavigationContentDescription;
|
||||
|
||||
public ShellToolbarTracker(IShellContext shellContext, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
|
@ -55,6 +56,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
_toolbar = toolbar ?? throw new ArgumentNullException(nameof(toolbar));
|
||||
_drawerLayout = drawerLayout ?? throw new ArgumentNullException(nameof(drawerLayout));
|
||||
|
||||
_toolbar.SetNavigationOnClickListener(this);
|
||||
((IShellController)_shellContext.Shell).AddFlyoutBehaviorObserver(this);
|
||||
}
|
||||
|
||||
|
@ -114,45 +116,55 @@ namespace Xamarin.Forms.Platform.Android
|
|||
void AView.IOnClickListener.OnClick(AView v)
|
||||
{
|
||||
var backButtonHandler = Shell.GetBackButtonBehavior(Page);
|
||||
if (backButtonHandler?.Command != null)
|
||||
backButtonHandler.Command.Execute(backButtonHandler.CommandParameter);
|
||||
else if (CanNavigateBack)
|
||||
OnNavigateBack();
|
||||
else
|
||||
_shellContext.Shell.FlyoutIsPresented = !_shellContext.Shell.FlyoutIsPresented;
|
||||
var isEnabled = backButtonHandler.GetPropertyIfSet(BackButtonBehavior.IsEnabledProperty, true);
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
if (backButtonHandler?.Command != null)
|
||||
backButtonHandler.Command.Execute(backButtonHandler.CommandParameter);
|
||||
else if (CanNavigateBack)
|
||||
OnNavigateBack();
|
||||
else
|
||||
_shellContext.Shell.FlyoutIsPresented = !_shellContext.Shell.FlyoutIsPresented;
|
||||
}
|
||||
|
||||
v.Dispose();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
UpdateTitleView(_shellContext.AndroidContext, _toolbar, null);
|
||||
|
||||
_drawerToggle?.Dispose();
|
||||
if (_searchView != null)
|
||||
{
|
||||
UpdateTitleView(_shellContext.AndroidContext, _toolbar, null);
|
||||
|
||||
_drawerToggle?.Dispose();
|
||||
if (_searchView != null)
|
||||
{
|
||||
_searchView.View.RemoveFromParent();
|
||||
_searchView.View.ViewAttachedToWindow -= OnSearchViewAttachedToWindow;
|
||||
_searchView.SearchConfirmed -= OnSearchConfirmed;
|
||||
_searchView.Dispose();
|
||||
}
|
||||
|
||||
((IShellController)_shellContext.Shell).RemoveFlyoutBehaviorObserver(this);
|
||||
_searchView.View.RemoveFromParent();
|
||||
_searchView.View.ViewAttachedToWindow -= OnSearchViewAttachedToWindow;
|
||||
_searchView.SearchConfirmed -= OnSearchConfirmed;
|
||||
_searchView.Dispose();
|
||||
}
|
||||
|
||||
SearchHandler = null;
|
||||
_shellContext = null;
|
||||
_drawerToggle = null;
|
||||
_searchView = null;
|
||||
Page = null;
|
||||
_toolbar = null;
|
||||
_drawerLayout = null;
|
||||
_disposed = true;
|
||||
((IShellController)_shellContext.Shell).RemoveFlyoutBehaviorObserver(this);
|
||||
|
||||
if (_backButtonBehavior != null)
|
||||
_backButtonBehavior.PropertyChanged -= OnBackButtonBehaviorChanged;
|
||||
}
|
||||
|
||||
_backButtonBehavior = null;
|
||||
SearchHandler = null;
|
||||
_shellContext = null;
|
||||
_drawerToggle = null;
|
||||
_searchView = null;
|
||||
Page = null;
|
||||
_toolbar = null;
|
||||
_drawerLayout = null;
|
||||
_disposed = true;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
protected virtual IShellSearchView GetSearchView(Context context)
|
||||
|
@ -169,6 +181,9 @@ namespace Xamarin.Forms.Platform.Android
|
|||
{
|
||||
if (oldPage != null)
|
||||
{
|
||||
if (_backButtonBehavior != null)
|
||||
_backButtonBehavior.PropertyChanged -= OnBackButtonBehaviorChanged;
|
||||
|
||||
oldPage.PropertyChanged -= OnPagePropertyChanged;
|
||||
((INotifyCollectionChanged)oldPage.ToolbarItems).CollectionChanged -= OnPageToolbarItemsChanged;
|
||||
}
|
||||
|
@ -176,6 +191,11 @@ namespace Xamarin.Forms.Platform.Android
|
|||
if (newPage != null)
|
||||
{
|
||||
newPage.PropertyChanged += OnPagePropertyChanged;
|
||||
_backButtonBehavior = Shell.GetBackButtonBehavior(newPage);
|
||||
|
||||
if (_backButtonBehavior != null)
|
||||
_backButtonBehavior.PropertyChanged += OnBackButtonBehaviorChanged;
|
||||
|
||||
((INotifyCollectionChanged)newPage.ToolbarItems).CollectionChanged += OnPageToolbarItemsChanged;
|
||||
|
||||
UpdatePageTitle(_toolbar, newPage);
|
||||
|
@ -186,6 +206,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
}
|
||||
}
|
||||
|
||||
BackButtonBehavior _backButtonBehavior = null;
|
||||
protected virtual void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == Page.TitleProperty.PropertyName)
|
||||
|
@ -195,11 +216,52 @@ namespace Xamarin.Forms.Platform.Android
|
|||
else if (e.PropertyName == Shell.NavBarIsVisibleProperty.PropertyName)
|
||||
UpdateNavBarVisible(_toolbar, Page);
|
||||
else if (e.PropertyName == Shell.BackButtonBehaviorProperty.PropertyName)
|
||||
{
|
||||
var backButtonHandler = Shell.GetBackButtonBehavior(Page);
|
||||
|
||||
if (_backButtonBehavior != null)
|
||||
_backButtonBehavior.PropertyChanged -= OnBackButtonBehaviorChanged;
|
||||
|
||||
UpdateLeftBarButtonItem();
|
||||
|
||||
_backButtonBehavior = backButtonHandler;
|
||||
if (_backButtonBehavior != null)
|
||||
_backButtonBehavior.PropertyChanged += OnBackButtonBehaviorChanged;
|
||||
}
|
||||
else if (e.PropertyName == Shell.TitleViewProperty.PropertyName)
|
||||
UpdateTitleView();
|
||||
}
|
||||
|
||||
void OnBackButtonBehaviorChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if(e.PropertyName == BackButtonBehavior.IsEnabledProperty.PropertyName)
|
||||
{
|
||||
UpdateBackButtonBehaviorIsEnabled();
|
||||
_drawerToggle.SyncState();
|
||||
}
|
||||
|
||||
UpdateLeftBarButtonItem();
|
||||
}
|
||||
|
||||
void UpdateBackButtonBehaviorIsEnabled()
|
||||
{
|
||||
if (_drawerLayout == null || _drawerToggle == null)
|
||||
return;
|
||||
|
||||
bool isEnabled = _backButtonBehavior?.IsEnabled ?? true;
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
_drawerLayout.SetDrawerLockMode(DrawerLayout.LockModeUnlocked);
|
||||
_drawerToggle.OnDrawerStateChanged(DrawerLayout.LockModeUnlocked);
|
||||
}
|
||||
else
|
||||
{
|
||||
_drawerLayout.SetDrawerLockMode(DrawerLayout.LockModeLockedClosed);
|
||||
_drawerToggle.OnDrawerStateChanged(DrawerLayout.LockModeLockedClosed);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnPageToolbarItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateToolbarItems();
|
||||
|
@ -233,26 +295,10 @@ namespace Xamarin.Forms.Platform.Android
|
|||
}
|
||||
|
||||
protected virtual async void UpdateLeftBarButtonItem(Context context, Toolbar toolbar, DrawerLayout drawerLayout, Page page)
|
||||
{
|
||||
var backButtonHandler = Shell.GetBackButtonBehavior(page);
|
||||
toolbar.SetNavigationOnClickListener(this);
|
||||
|
||||
if (backButtonHandler != null)
|
||||
{
|
||||
await UpdateDrawerArrowFromBackButtonBehavior(context, toolbar, drawerLayout, backButtonHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
await UpdateDrawerArrow(context, toolbar, drawerLayout);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task UpdateDrawerArrow(Context context, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
if (_drawerToggle == null && !context.IsDesignerContext())
|
||||
{
|
||||
_drawerToggle = new ActionBarDrawerToggle(context.GetActivity(), drawerLayout, toolbar, R.String.Ok, R.String.Ok)
|
||||
|
||||
{
|
||||
ToolbarNavigationClickListener = this,
|
||||
};
|
||||
|
@ -263,104 +309,99 @@ namespace Xamarin.Forms.Platform.Android
|
|||
drawerLayout.AddDrawerListener(_drawerToggle);
|
||||
}
|
||||
|
||||
if (CanNavigateBack)
|
||||
var backButtonHandler = Shell.GetBackButtonBehavior(page);
|
||||
|
||||
var image = backButtonHandler.GetPropertyIfSet<ImageSource>(BackButtonBehavior.IconOverrideProperty, null);
|
||||
var text = backButtonHandler.GetPropertyIfSet(BackButtonBehavior.TextOverrideProperty, String.Empty);
|
||||
var command = backButtonHandler.GetPropertyIfSet<ICommand>(BackButtonBehavior.CommandProperty, null);
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
_drawerToggle.DrawerIndicatorEnabled = false;
|
||||
using (var icon = new DrawerArrowDrawable(context.GetThemedContext()))
|
||||
Element item = page;
|
||||
while (!Application.IsApplicationOrNull(item))
|
||||
{
|
||||
icon.SetColorFilter(TintColor.ToAndroid(Color.White), PorterDuff.Mode.SrcAtop);
|
||||
icon.Progress = 1;
|
||||
toolbar.NavigationIcon = icon;
|
||||
if (item is IShellController shell)
|
||||
{
|
||||
image = shell.FlyoutIcon;
|
||||
break;
|
||||
}
|
||||
item = item?.Parent;
|
||||
}
|
||||
}
|
||||
else if (_flyoutBehavior == FlyoutBehavior.Flyout)
|
||||
|
||||
DrawerArrowDrawable icon = null;
|
||||
|
||||
var tintColor = Color.White;
|
||||
if (TintColor != Color.Default)
|
||||
tintColor = TintColor;
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
toolbar.NavigationIcon = null;
|
||||
var drawable = _drawerToggle.DrawerArrowDrawable;
|
||||
drawable.SetColorFilter(TintColor.ToAndroid(Color.White), PorterDuff.Mode.SrcAtop);
|
||||
_drawerToggle.DrawerIndicatorEnabled = true;
|
||||
var customIcon = await context.GetFormsDrawableAsync(image);
|
||||
|
||||
if(customIcon != null)
|
||||
icon = new FlyoutIconDrawerDrawable(context, tintColor, customIcon, text);
|
||||
}
|
||||
else
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(text) && icon == null)
|
||||
icon = new FlyoutIconDrawerDrawable(context, tintColor, icon, text);
|
||||
|
||||
if(icon == null)
|
||||
{
|
||||
icon = new DrawerArrowDrawable(context.GetThemedContext());
|
||||
|
||||
ADrawableCompat.SetTint(icon, tintColor.ToAndroid());
|
||||
ADrawableCompat.SetTintMode(icon, PorterDuff.Mode.SrcAtop);
|
||||
}
|
||||
|
||||
icon.Progress = (CanNavigateBack) ? 1 : 0;
|
||||
|
||||
if (command != null || CanNavigateBack)
|
||||
{
|
||||
_drawerToggle.DrawerIndicatorEnabled = false;
|
||||
toolbar.NavigationIcon = icon;
|
||||
}
|
||||
else
|
||||
{
|
||||
toolbar.NavigationIcon = null;
|
||||
_drawerToggle.DrawerIndicatorEnabled = true;
|
||||
_drawerToggle.DrawerArrowDrawable = icon;
|
||||
}
|
||||
|
||||
UpdateBackButtonBehaviorIsEnabled();
|
||||
_drawerToggle.SyncState();
|
||||
|
||||
//this needs to be set after SyncState
|
||||
UpdateToolbarIconAccessibilityText(toolbar, _shellContext.Shell);
|
||||
}
|
||||
|
||||
|
||||
protected virtual Task UpdateDrawerArrow(Context context, Toolbar toolbar, DrawerLayout drawerLayout)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual void UpdateToolbarIconAccessibilityText(Toolbar toolbar, Shell shell)
|
||||
{
|
||||
//if AutomationId was specified the user wants to use UITests and interact with FlyoutIcon
|
||||
if (!string.IsNullOrEmpty(shell.FlyoutIcon?.AutomationId))
|
||||
{
|
||||
if (_defaultNavigationContentDescription == null)
|
||||
_defaultNavigationContentDescription = toolbar.NavigationContentDescription;
|
||||
toolbar.NavigationContentDescription = shell.FlyoutIcon.AutomationId;
|
||||
}
|
||||
else
|
||||
else if(toolbar.SetNavigationContentDescription(_shellContext.Shell.FlyoutIcon) == null)
|
||||
{
|
||||
toolbar.SetNavigationContentDescription(_shellContext.Shell.FlyoutIcon, _defaultNavigationContentDescription);
|
||||
toolbar.SetNavigationContentDescription(R.String.Ok);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task UpdateDrawerArrowFromBackButtonBehavior(Context context, Toolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
|
||||
protected virtual Task UpdateDrawerArrowFromBackButtonBehavior(Context context, Toolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
|
||||
{
|
||||
var behavior = backButtonHandler;
|
||||
var command = behavior.Command;
|
||||
var commandParameter = behavior.CommandParameter;
|
||||
var image = behavior.IconOverride;
|
||||
var text = behavior.TextOverride;
|
||||
var enabled = behavior.IsEnabled;
|
||||
|
||||
Drawable icon = null;
|
||||
|
||||
if (image != null)
|
||||
icon = await context.GetFormsDrawableAsync(image);
|
||||
|
||||
if (text != null)
|
||||
icon = new FlyoutIconDrawerDrawable(context, TintColor, icon, text);
|
||||
|
||||
if (CanNavigateBack && icon == null)
|
||||
{
|
||||
icon = new DrawerArrowDrawable(context.GetThemedContext());
|
||||
(icon as DrawerArrowDrawable).Progress = 1;
|
||||
}
|
||||
|
||||
var iconState = icon.GetConstantState();
|
||||
if (iconState != null)
|
||||
{
|
||||
using (var mutatedIcon = iconState.NewDrawable().Mutate())
|
||||
{
|
||||
mutatedIcon.SetColorFilter(TintColor.ToAndroid(Color.White), PorterDuff.Mode.SrcAtop);
|
||||
toolbar.NavigationIcon = mutatedIcon;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
toolbar.NavigationIcon = icon;
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual async Task UpdateDrawerArrowFromFlyoutIcon(Context context, ActionBarDrawerToggle actionBarDrawerToggle)
|
||||
protected virtual Task UpdateDrawerArrowFromFlyoutIcon(Context context, ActionBarDrawerToggle actionBarDrawerToggle)
|
||||
{
|
||||
Element item = Page;
|
||||
ImageSource icon = null;
|
||||
while (!Application.IsApplicationOrNull(item))
|
||||
{
|
||||
if (item is IShellController shell)
|
||||
{
|
||||
icon = shell.FlyoutIcon;
|
||||
if (icon != null)
|
||||
{
|
||||
var drawable = await context.GetFormsDrawableAsync(icon);
|
||||
actionBarDrawerToggle.DrawerArrowDrawable = new FlyoutIconDrawerDrawable(context, TintColor, drawable, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
item = item?.Parent;
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual void UpdateMenuItemIcon(Context context, IMenuItem menuItem, ToolbarItem toolBarItem)
|
||||
|
@ -564,6 +605,9 @@ namespace Xamarin.Forms.Platform.Android
|
|||
bool pressed = false;
|
||||
if (_iconBitmap != null)
|
||||
{
|
||||
ADrawableCompat.SetTint(_iconBitmap, _defaultColor.ToAndroid());
|
||||
ADrawableCompat.SetTintMode(_iconBitmap, PorterDuff.Mode.SrcAtop);
|
||||
|
||||
_iconBitmap.SetBounds(Bounds.Left, Bounds.Top, Bounds.Right, Bounds.Bottom);
|
||||
_iconBitmap.Draw(canvas);
|
||||
}
|
||||
|
|
|
@ -75,8 +75,18 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
protected virtual async void OnBackButtonBehaviorPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == BackButtonBehavior.CommandParameterProperty.PropertyName)
|
||||
if (e.PropertyName == BackButtonBehavior.CommandProperty.PropertyName)
|
||||
return;
|
||||
else if (e.PropertyName == BackButtonBehavior.CommandParameterProperty.PropertyName)
|
||||
return;
|
||||
else if (e.PropertyName == BackButtonBehavior.IsEnabledProperty.PropertyName)
|
||||
{
|
||||
if (NavigationItem?.LeftBarButtonItem != null)
|
||||
NavigationItem.LeftBarButtonItem.Enabled = BackButtonBehavior.IsEnabled;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await UpdateToolbarItems().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
@ -199,79 +209,78 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
items.Reverse();
|
||||
NavigationItem.SetRightBarButtonItems(items.ToArray(), false);
|
||||
|
||||
if (BackButtonBehavior != null)
|
||||
{
|
||||
var behavior = BackButtonBehavior;
|
||||
var command = behavior.Command;
|
||||
var commandParameter = behavior.CommandParameter;
|
||||
var image = behavior.IconOverride;
|
||||
var enabled = behavior.IsEnabled;
|
||||
var behavior = BackButtonBehavior;
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
var text = BackButtonBehavior.TextOverride;
|
||||
NavigationItem.LeftBarButtonItem =
|
||||
new UIBarButtonItem(text, UIBarButtonItemStyle.Plain, (s, e) => LeftBarButtonItemHandler(ViewController, command, commandParameter, IsRootPage)) { Enabled = enabled };
|
||||
}
|
||||
else
|
||||
{
|
||||
var icon = await image.GetNativeImageAsync();
|
||||
NavigationItem.LeftBarButtonItem =
|
||||
new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, (s, e) => LeftBarButtonItemHandler(ViewController, command, commandParameter, IsRootPage)) { Enabled = enabled };
|
||||
}
|
||||
}
|
||||
else if (IsRootPage && _flyoutBehavior == FlyoutBehavior.Flyout)
|
||||
{
|
||||
var image = behavior.GetPropertyIfSet<ImageSource>(BackButtonBehavior.IconOverrideProperty, null);
|
||||
var enabled = behavior.GetPropertyIfSet(BackButtonBehavior.IsEnabledProperty, true);
|
||||
var text = behavior.GetPropertyIfSet(BackButtonBehavior.TextOverrideProperty, String.Empty);
|
||||
|
||||
UIImage icon = null;
|
||||
|
||||
await SetDrawerArrowDrawableFromFlyoutIcon();
|
||||
}
|
||||
else
|
||||
if (image == null && String.IsNullOrWhiteSpace(text) && (!IsRootPage || _flyoutBehavior != FlyoutBehavior.Flyout))
|
||||
{
|
||||
NavigationItem.LeftBarButtonItem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(text) && image == null)
|
||||
{
|
||||
Element item = Page;
|
||||
while (!Application.IsApplicationOrNull(item))
|
||||
{
|
||||
if (item is IShellController shell)
|
||||
{
|
||||
image = shell.FlyoutIcon;
|
||||
item = null;
|
||||
}
|
||||
item = item?.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (image != null)
|
||||
icon = await image.GetNativeImageAsync();
|
||||
else if (String.IsNullOrWhiteSpace(text))
|
||||
icon = DrawHamburger();
|
||||
|
||||
if (icon == null)
|
||||
{
|
||||
NavigationItem.LeftBarButtonItem =
|
||||
new UIBarButtonItem(text, UIBarButtonItemStyle.Plain, (s, e) => LeftBarButtonItemHandler(ViewController, IsRootPage)) { Enabled = enabled };
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationItem.LeftBarButtonItem =
|
||||
new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, (s, e) => LeftBarButtonItemHandler(ViewController, IsRootPage)) { Enabled = enabled };
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(image?.AutomationId))
|
||||
NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = "OK";
|
||||
else
|
||||
NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = image.AutomationId;
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
NavigationItem.LeftBarButtonItem.SetAccessibilityHint(image);
|
||||
NavigationItem.LeftBarButtonItem.SetAccessibilityLabel(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LeftBarButtonItemHandler(UIViewController controller, ICommand command, object commandParameter, bool isRootPage)
|
||||
void LeftBarButtonItemHandler(UIViewController controller, bool isRootPage)
|
||||
{
|
||||
var behavior = BackButtonBehavior;
|
||||
var command = behavior.GetPropertyIfSet(BackButtonBehavior.CommandProperty, new Command(() => OnMenuButtonPressed(this, EventArgs.Empty)));
|
||||
var commandParameter = behavior.GetPropertyIfSet<object>(BackButtonBehavior.CommandParameterProperty, null);
|
||||
|
||||
if (command == null && !isRootPage && controller?.ParentViewController is UINavigationController navigationController)
|
||||
{
|
||||
navigationController.PopViewController(true);
|
||||
return;
|
||||
}
|
||||
|
||||
command?.Execute(commandParameter);
|
||||
}
|
||||
|
||||
async Task SetDrawerArrowDrawableFromFlyoutIcon()
|
||||
{
|
||||
Element item = Page;
|
||||
ImageSource image = null;
|
||||
while (!Application.IsApplicationOrNull(item))
|
||||
{
|
||||
if (item is IShellController shell)
|
||||
{
|
||||
image = shell.FlyoutIcon;
|
||||
item = null;
|
||||
}
|
||||
item = item?.Parent;
|
||||
}
|
||||
|
||||
UIImage icon = null;
|
||||
|
||||
if (image != null)
|
||||
icon = await image.GetNativeImageAsync();
|
||||
else
|
||||
icon = DrawHamburger();
|
||||
|
||||
var barButtonItem = new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, OnMenuButtonPressed);
|
||||
|
||||
barButtonItem.AccessibilityIdentifier = "OK";
|
||||
NavigationItem.LeftBarButtonItem = barButtonItem;
|
||||
if (image == null)
|
||||
return;
|
||||
NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = image.AutomationId;
|
||||
NavigationItem.LeftBarButtonItem.SetAccessibilityHint(image);
|
||||
NavigationItem.LeftBarButtonItem.SetAccessibilityLabel(image);
|
||||
}
|
||||
|
||||
UIImage DrawHamburger()
|
||||
{
|
||||
|
@ -323,19 +332,29 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
return;
|
||||
|
||||
if (BackButtonBehavior != null)
|
||||
{
|
||||
BackButtonBehavior.PropertyChanged -= OnBackButtonBehaviorPropertyChanged;
|
||||
}
|
||||
|
||||
BackButtonBehavior = value;
|
||||
|
||||
if (BackButtonBehavior != null)
|
||||
{
|
||||
BackButtonBehavior.PropertyChanged += OnBackButtonBehaviorPropertyChanged;
|
||||
}
|
||||
|
||||
await UpdateToolbarItems().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
void OnBackButtonCommandCanExecuteChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (NavigationItem?.LeftBarButtonItem == null)
|
||||
return;
|
||||
|
||||
bool isEnabled = BackButtonBehavior.GetPropertyIfSet<bool>(BackButtonBehavior.IsEnabledProperty, true);
|
||||
|
||||
if (isEnabled && sender is ICommand command)
|
||||
isEnabled = command.CanExecute(BackButtonBehavior?.CommandParameter);
|
||||
|
||||
NavigationItem.LeftBarButtonItem.Enabled = isEnabled;
|
||||
}
|
||||
|
||||
public class TitleViewContainer : UIContainerView
|
||||
{
|
||||
public TitleViewContainer(View view) : base(view)
|
||||
|
@ -588,11 +607,15 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
Page.PropertyChanged -= OnPagePropertyChanged;
|
||||
((INotifyCollectionChanged)Page.ToolbarItems).CollectionChanged -= OnToolbarItemsChanged;
|
||||
((IShellController)_context.Shell).RemoveFlyoutBehaviorObserver(this);
|
||||
|
||||
if (BackButtonBehavior != null)
|
||||
BackButtonBehavior.PropertyChanged -= OnBackButtonBehaviorPropertyChanged;
|
||||
|
||||
}
|
||||
|
||||
SearchHandler = null;
|
||||
Page = null;
|
||||
SetBackButtonBehavior(null);
|
||||
BackButtonBehavior = null;
|
||||
_rendererRef = null;
|
||||
NavigationItem = null;
|
||||
_searchHandlerAppearanceTracker = null;
|
||||
|
|
Загрузка…
Ссылка в новой задаче