如何使用渲染器更改 Android 选项卡的背景颜色,同时使用自定义渲染器添加一些填充

Ala*_*an2 7 xamarin xamarin.forms

在我的应用程序中,我设置了底部标签栏的背景颜色,如下所示:

<Shell xmlns="http://xamarin.com/schemas/2014/forms" 
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
       x:Class="M.Views.AppShell"
       NavBarIsVisible="True"
       xmlns:local="clr-namespace:Memorise"
       BackgroundColor="{DynamicResource ShellBackgroundColor}"
       TabBarBackgroundColor="{DynamicResource TabBarBackgroundColor}" 
       TabBarDisabledColor="{DynamicResource TabBarDisabledColor}" 
       TabBarForegroundColor="{DynamicResource TabBarForegroundColor}" 
       TabBarTitleColor="{DynamicResource TabBarTitleColor}" 
       TabBarUnselectedColor="{DynamicResource TabBarUnselectedColor}"
Run Code Online (Sandbox Code Playgroud)

我创建了一个自定义渲染器来向 Android 上的选项卡添加一些侧边距:

public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context)
        : base(context)
    {
    }

    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new MarginedTabBarAppearance();
    }
}

public class MarginedTabBarAppearance : IShellBottomNavViewAppearanceTracker
{
    public void Dispose()
    {
    }

    public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        if (App.devWidth == SIZE.L)
            bottomView.SetPadding(400, 0, 400, 0);
    }

    public void ResetAppearance(BottomNavigationView bottomView)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这也有一个副作用,因为它将选项卡的背景颜色设置为白色。

有没有人知道我如何使用此渲染器并将背景颜色更改为与 DynamicResource ShellBackgroundColor 相同?

带有渲染器的代码注释掉了:

public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context)
        : base(context)
    {
    }

    //protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    //{
    //    return new MarginedTabBarAppearance();
    //}
}

public class MarginedTabBarAppearance : IShellBottomNavViewAppearanceTracker
{
    public void Dispose()
    {
    }

    public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        //if (App.devWidth == SIZE.L)
        //    bottomView.SetPadding(400, 0, 400, 0);
        //if (Application.Current.Resources["TabBarBackgroundColor"] is Xamarin.Forms.Color color1)
        //{
        //    bottomView.SetBackgroundColor(color1.ToAndroid());
        //}
    }

    public void ResetAppearance(BottomNavigationView bottomView)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

带有渲染器的标签栏注释掉了:

在此处输入图片说明

** 带有渲染器的代码未注释掉:**

public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context)
        : base(context)
    {
    }

    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new MarginedTabBarAppearance();
    }
}

public class MarginedTabBarAppearance : IShellBottomNavViewAppearanceTracker
{
    public void Dispose()
    {
    }

    public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        if (App.devWidth == SIZE.L)
            bottomView.SetPadding(400, 0, 400, 0);
        if (Application.Current.Resources["TabBarBackgroundColor"] is Xamarin.Forms.Color color1)
        {
            bottomView.SetBackgroundColor(color1.ToAndroid());
        }
    }

    public void ResetAppearance(BottomNavigationView bottomView)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

带有未注释掉的渲染器的标签栏:

在此处输入图片说明

Mihail 建议的更新代码:

public class MarginedTabBarAppearance :    ShellBottomNavViewAppearanceTracker
{

public MarginedTabBarAppearance(IShellContext shellContext, ShellItem shellItem)
    : base(shellContext, shellItem)
{
}

public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
    base.SetAppearance(bottomView, appearance);

    bottomView.SetPadding(400, 0, 400, 0);

    if (Application.Current.Resources.ContainsKey("TabBarBackgroundColor") && 
        Application.Current.Resources["TabBarBackgroundColor"] is Color tabColor)
    {
        bottomView.SetBackgroundColor(tabColor.ToAndroid());
    }
}
}
Run Code Online (Sandbox Code Playgroud)

Mih*_*hev 6

在您的SetAppearance方法中,您可以像这样设置背景颜色:

bottomView.SetBackgroundColor(Android.Graphics.Color.Red);
Run Code Online (Sandbox Code Playgroud)

但是,SetBackgroundColor需要一个类型的颜色,Android.Graphics.Color我看到您希望从DynamicResource获取颜色,它将返回一个Xamarin.Forms.Color. 好消息是两个颜色类都可以轻松转换,因此我们只需要获取DynamicResource的当前值:

if (Application.Current.Resources["CustomTabBackgroundColor"] is Xamarin.Forms.Color color)
{
    bottomView.SetBackgroundColor(color.ToAndroid());
}
Run Code Online (Sandbox Code Playgroud)

在这里,CustomTabBackgroundColor是颜色的关键,并color.ToAndroid()在 2 个类之间进行转换(从 Xamarin 到 Android 的一个)。

更新

由于对问题的更新,我将补充说,在这种情况下,样式/颜色重置的问题不是由于背景变化造成的,而是完全由其他原因造成的。设置新视图外观的方式 ( return new MarginedTabBarAppearance();) 重置所有默认样式。由于我们从接口实现所有内容而不是从基类派生,因此我们无法从已经预设的值中获取任何内容。为了解决这个问题,我们需要改变MarginedTabBarAppearance类的实现方式:

public class MarginedTabBarAppearance : ShellBottomNavViewAppearanceTracker
{
    public MarginedTabBarAppearance(IShellContext shellContext, ShellItem shellItem)
        : base(shellContext, shellItem)
    {
    }

    public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        base.SetAppearance(bottomView, appearance);

        bottomView.SetPadding(400, 0, 400, 0);

        if (Application.Current.Resources.ContainsKey("TabBarBackgroundColor") && 
            Application.Current.Resources["TabBarBackgroundColor"] is Color tabColor)
        {
            bottomView.SetBackgroundColor(tabColor.ToAndroid());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,您必须CreateBottomNavViewAppearanceTracker像这样更改方法:

protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
    return new MarginedTabBarAppearance(this, shellItem);
}
Run Code Online (Sandbox Code Playgroud)

这样,我们将采用我们已经设计好的所有内容,然后简单地更改我们需要的内容。