如何在Xamarin.Forms中使用不同颜色的顶部和底部工具栏

时间:2018-01-30 10:29:36

标签: c# xaml xamarin.forms uwp

在其中一个最新版本中,Xamarin.Forms添加了将工具栏放在底部(2009q4)并在ToolBarPlacement上设置属性BarBackgroundColor的可能性。工具栏可以更改。

不幸的是,当工具栏被拆分时(这是Windows 10 Mobile上的默认设置或NavigationPage是底部的),两个栏都具有相同的背景颜色。

在我的应用程序中,我希望实现顶部栏(带标题和汉堡菜单)具有系统的强调颜色,底栏(带有命令和弹出按钮)为灰色,因为此组合也被使用by many system apps (例如,Windows 10 Mobile上的邮件或日历)。 但是,如果不触及Xamarin.Forms中的核心实现,我无法弄清楚如何做到这一点。我已尝试过自定义ToolbarPlacement和自定义NavigationPageRenderer,但许多相关字段都是私有,密封或内部或正在访问内部接口。

两个条形图的背景颜色似乎绑定到相同的属性,因为在Visual Studio的Live XAML树视图中更改一个条形图的背景也会更改另一个条形图的颜色。

任何有关如何实现所需外观的帮助都将受到赞赏。

1 个答案:

答案 0 :(得分:1)

最后,我取得了理想的结果。

其中一个问题是我的RootPage是MasterDetailPage,因此我必须创建一个MasterDetailPageRenderer。此外,我假设Xamarin将使用实际的UWP页面的TopAppBarBottomAppBar属性。事实并非如此。

使用以下MasterDetailPageRenderer顶部栏(带有汉堡菜单按钮和标题)显示为绿色,而底栏保持默认灰色(基本上渲染器只删除代表StackPanel的Background绑定顶部栏并将其设置为绿色)。一个问题是,FindName和FindByName方法不起作用(总是返回null),所以我不得不使用VisualTreeHelper滚动我自己的实现。

[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(CustomMasterDetailPageRender))]
public class CustomMasterDetailPageRender : MasterDetailPageRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<MasterDetailPage> e)
    {
        base.OnElementChanged(e);

        if (Element != null)
        {                
            Element.Appearing += Element_Appearing;                         
        }
    }

    private void Element_Appearing(object sender, EventArgs e)
    {
        (sender as MasterDetailPage).Appearing -= Element_Appearing;

        if (Control != null)
        {
            var topBarArea = FindElementByName(Control, "TopCommandBarArea");
            if (topBarArea != null)
            {
                var topContent = FindElementByType<StackPanel>(topBarArea);
                if (topContent != null)
                {
                    topContent.Background = new SolidColorBrush(Colors.Green);
                }
            }          
        }
    }

    static DependencyObject FindElementByName(DependencyObject parent, string name)
    {            
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            var sub = VisualTreeHelper.GetChild(parent, i);
            if (sub is FrameworkElement)
            {
                if (((FrameworkElement)sub).Name == name)
                {
                    return sub;
                }
            }

            var r = FindElementByName(sub, name);
            if (r != null)
                return r;
        }

        return null;
    }

    static T FindElementByType<T>(DependencyObject parent)
        where T: DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            var sub = VisualTreeHelper.GetChild(parent, i);

            if (sub is T)
            {
                return (T)sub;
            }

            var r = FindElementByType<T>(sub);
            if (r != null)
                return r;
        }

        return null;
    }
}