在 Xamarin Forms 3.1 中,当使用带有 4 个选项卡的选项卡式页面时,如何防止选项卡栏对 Android 的 "sliding" 影响?
In Xamarin Forms 3.1, when using tabbed page with 4 tabs, how can I prevent "sliding" effect of tab bar on Android?
我有一个有四个页面的应用程序,我希望它看起来与我的 (non-Xamarin) iOS 应用程序相似,因此工具栏位于底部。这是我的 MainPage.xaml 文件:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XaBLE1"
x:Class="XaBLE1.MainPage"
Title="Safe-T Sim" HeightRequest="768" WidthRequest="512"
BarBackgroundColor="#F1F1F1"
BarTextColor="Gray"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
android:TabbedPage.BarItemColor="#666666"
android:TabbedPage.BarSelectedItemColor="Black"
>
<NavigationPage Title="Test" Icon="ElectTest.png"
HasNavigationBar="False">
<x:Arguments>
<local:TestPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Review" Icon="Review.png"
HasNavigationBar="False">
<x:Arguments>
<local:ReviewPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Setup" Icon="Gear.png"
HasNavigationBar="False">
<x:Arguments>
<local:SetupPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Info" Icon="Info.png"
HasNavigationBar="False">
<x:Arguments>
<local:InfoPage />
</x:Arguments>
</NavigationPage>
</TabbedPage>
我不喜欢Oreo现在的look-and-feel,就是把选中的页面tab变大放标题,把其他tab推到一边去掉页面title
有没有办法禁用这种行为,让它只有 4 个标签。请注意,如果有 3 个选项卡,则不会发生此行为 -- 只有图标和文本变暗和略微放大,但两者都是可见的。
编辑:我尝试了评论中建议的答案,但如前所述,我不确定这是在尝试解决相同的问题,并且在任何情况下都不会改变行为。
要禁用选项卡滑动,您可以在 TabbedPage 中使用 PlatformConfiguration class
public partial class MyTabbedPage : TabbedPage
{
public MainTabbedPage ()
{
InitializeComponent();
this.On<Xamarin.Forms.PlatformConfiguration.Android>().SetIsSwipePagingEnabled(false);
}
}
如果您没有 MyTabbedPage class,添加它,您的 axml 文件结构将如下所示
<?xml version="1.0" encoding="utf-8" ?>
<MyTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XaBLE1.MainPage">
</MyTabbedPage>
看起来您正在寻找这个(尚未实现)功能:[Enhancement] Implement fixed mode for Bottom Navigation Bar Android (Github)
我可以按照这个 James Montemagno tutorial: Removing BottomNavigationView’s Icon Shifting in Xamarin.Android 并实现我自己的标签页自定义渲染器来解决它:
using Android.Content;
using Android.Support.Design.Internal;
using Android.Views;
using FixedTabbedPage.Droid.CustomRenderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))]
namespace FixedTabbedPage.Droid.CustomRenderers
{
public class CustomTabbedPageRenderer : TabbedPageRenderer
{
public CustomTabbedPageRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
if (ViewGroup != null && ViewGroup.ChildCount > 0)
{
BottomNavigationMenuView bottomNavigationMenuView = FindChildOfType<BottomNavigationMenuView>(ViewGroup);
if (bottomNavigationMenuView != null)
{
var shiftMode = bottomNavigationMenuView.Class.GetDeclaredField("mShiftingMode");
shiftMode.Accessible = true;
shiftMode.SetBoolean(bottomNavigationMenuView, false);
shiftMode.Accessible = false;
shiftMode.Dispose();
for (var i = 0; i < bottomNavigationMenuView.ChildCount; i++)
{
var item = bottomNavigationMenuView.GetChildAt(i) as BottomNavigationItemView;
if (item == null) continue;
item.SetShiftingMode(false);
item.SetChecked(item.ItemData.IsChecked);
}
if (bottomNavigationMenuView.ChildCount > 0) bottomNavigationMenuView.UpdateMenuView();
}
}
}
private T FindChildOfType<T>(ViewGroup viewGroup) where T : Android.Views.View
{
if (viewGroup == null || viewGroup.ChildCount == 0) return null;
for (var i = 0; i < viewGroup.ChildCount; i++)
{
var child = viewGroup.GetChildAt(i);
var typedChild = child as T;
if (typedChild != null) return typedChild;
if (!(child is ViewGroup)) continue;
var result = FindChildOfType<T>(child as ViewGroup);
if (result != null) return result;
}
return null;
}
}
}
您只需将此代码添加到您的 Android 解决方案(重构命名空间),结果如下:
看起来,自 Android 9.
以来,有一个更简单的替代方案
我有一个有四个页面的应用程序,我希望它看起来与我的 (non-Xamarin) iOS 应用程序相似,因此工具栏位于底部。这是我的 MainPage.xaml 文件:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XaBLE1"
x:Class="XaBLE1.MainPage"
Title="Safe-T Sim" HeightRequest="768" WidthRequest="512"
BarBackgroundColor="#F1F1F1"
BarTextColor="Gray"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
android:TabbedPage.BarItemColor="#666666"
android:TabbedPage.BarSelectedItemColor="Black"
>
<NavigationPage Title="Test" Icon="ElectTest.png"
HasNavigationBar="False">
<x:Arguments>
<local:TestPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Review" Icon="Review.png"
HasNavigationBar="False">
<x:Arguments>
<local:ReviewPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Setup" Icon="Gear.png"
HasNavigationBar="False">
<x:Arguments>
<local:SetupPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Info" Icon="Info.png"
HasNavigationBar="False">
<x:Arguments>
<local:InfoPage />
</x:Arguments>
</NavigationPage>
</TabbedPage>
我不喜欢Oreo现在的look-and-feel,就是把选中的页面tab变大放标题,把其他tab推到一边去掉页面title
有没有办法禁用这种行为,让它只有 4 个标签。请注意,如果有 3 个选项卡,则不会发生此行为 -- 只有图标和文本变暗和略微放大,但两者都是可见的。
编辑:我尝试了评论中建议的答案,但如前所述,我不确定这是在尝试解决相同的问题,并且在任何情况下都不会改变行为。
要禁用选项卡滑动,您可以在 TabbedPage 中使用 PlatformConfiguration class
public partial class MyTabbedPage : TabbedPage
{
public MainTabbedPage ()
{
InitializeComponent();
this.On<Xamarin.Forms.PlatformConfiguration.Android>().SetIsSwipePagingEnabled(false);
}
}
如果您没有 MyTabbedPage class,添加它,您的 axml 文件结构将如下所示
<?xml version="1.0" encoding="utf-8" ?>
<MyTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XaBLE1.MainPage">
</MyTabbedPage>
看起来您正在寻找这个(尚未实现)功能:[Enhancement] Implement fixed mode for Bottom Navigation Bar Android (Github)
我可以按照这个 James Montemagno tutorial: Removing BottomNavigationView’s Icon Shifting in Xamarin.Android 并实现我自己的标签页自定义渲染器来解决它:
using Android.Content;
using Android.Support.Design.Internal;
using Android.Views;
using FixedTabbedPage.Droid.CustomRenderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))]
namespace FixedTabbedPage.Droid.CustomRenderers
{
public class CustomTabbedPageRenderer : TabbedPageRenderer
{
public CustomTabbedPageRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
if (ViewGroup != null && ViewGroup.ChildCount > 0)
{
BottomNavigationMenuView bottomNavigationMenuView = FindChildOfType<BottomNavigationMenuView>(ViewGroup);
if (bottomNavigationMenuView != null)
{
var shiftMode = bottomNavigationMenuView.Class.GetDeclaredField("mShiftingMode");
shiftMode.Accessible = true;
shiftMode.SetBoolean(bottomNavigationMenuView, false);
shiftMode.Accessible = false;
shiftMode.Dispose();
for (var i = 0; i < bottomNavigationMenuView.ChildCount; i++)
{
var item = bottomNavigationMenuView.GetChildAt(i) as BottomNavigationItemView;
if (item == null) continue;
item.SetShiftingMode(false);
item.SetChecked(item.ItemData.IsChecked);
}
if (bottomNavigationMenuView.ChildCount > 0) bottomNavigationMenuView.UpdateMenuView();
}
}
}
private T FindChildOfType<T>(ViewGroup viewGroup) where T : Android.Views.View
{
if (viewGroup == null || viewGroup.ChildCount == 0) return null;
for (var i = 0; i < viewGroup.ChildCount; i++)
{
var child = viewGroup.GetChildAt(i);
var typedChild = child as T;
if (typedChild != null) return typedChild;
if (!(child is ViewGroup)) continue;
var result = FindChildOfType<T>(child as ViewGroup);
if (result != null) return result;
}
return null;
}
}
}
您只需将此代码添加到您的 Android 解决方案(重构命名空间),结果如下:
看起来,自 Android 9.
以来,有一个更简单的替代方案