Xamarin表示MasterDetail中心标题

时间:2016-12-06 11:15:31

标签: xamarin xamarin.android xamarin.forms xamarin.forms-styles

我正在开始我的第一个Xamarin Forms应用程序 - 目前只比Hello World更多 - 但是我需要能够将标题栏中的文本居中。我正在使用MasterDetailPage,其中ContentPage为Master,NavigationPage为Detail。从下面的屏幕截图中,我希望能够以'Home'为中心。

我尝试过标记,就像来自Changing Actionbar Tab Text Size in AppCompact Theme的答案一样,但似乎没有任何影响文本的位置。我也尝试过自定义渲染器,但是没有用。

有没有人能够做到这一点?

使用一些代码更新我的问题。我的MasterDeatil.cs:

public class MasterDetail : MasterDetailPage
    {
        Master master;

        public MasterDetail()
        {
            master = new Master();

            Master = master;
            Detail = new NavigationPage(new Home());

            master.ListView.ItemSelected += ListView_ItemSelected;

            ToolbarItem cart = new ToolbarItem()
            {
                Text = "Test",
                Icon = "shoppingcart.png"
            };

            cart.Clicked += async (object sender, System.EventArgs e) =>
            {
                await DisplayAlert("Done", "Msg", "Ok", "Can");
            };

            ToolbarItems.Add(cart);
        }

        private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            MasterItem item = e.SelectedItem as MasterItem;

            if (item != null)
            {
                Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
                master.ListView.SelectedItem = null;
                IsPresented = false;
            }
        }
    }

Master.cs代码:

public class MasterDetail : MasterDetailPage
    {
        Master master;

        public MasterDetail()
        {
            master = new Master();

            Master = master;
            Detail = new NavigationPage(new Home());

            master.ListView.ItemSelected += ListView_ItemSelected;

            ToolbarItem cart = new ToolbarItem()
            {
                Text = "Test",
                Icon = "shoppingcart.png"
            };

            cart.Clicked += async (object sender, System.EventArgs e) =>
            {
                await DisplayAlert("Done", "Msg", "Ok", "Can");
            };

            ToolbarItems.Add(cart);
        }

        private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            MasterItem item = e.SelectedItem as MasterItem;

            if (item != null)
            {
                Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
                master.ListView.SelectedItem = null;
                IsPresented = false;
            }
        }
    }

Detail.cs代码:

public class Detail : ContentPage
    {
        public Detail()
        {
            Title = "Shaves2U";
            Content = new StackLayout
            {
                Children = {
                    new Label {
                        Text = "Detail data goes here",
                        HorizontalOptions = LayoutOptions.Center,
                        VerticalOptions = LayoutOptions.CenterAndExpand
                    }
                }
            };
        }
    }

style.xml:

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme" parent="Theme.AppCompat">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="windowActionModeOverlay">true</item>

    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
  </style>

  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
</resources>

我尝试了以下style.xml:

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <!-- Base theme applied no matter what API -->
  <style name="MainTheme" parent="Theme.AppCompat">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="windowActionModeOverlay">true</item>

    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
    <item name="android:actionBarTabTextStyle">@style/CustomTab</item>
  </style>

  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
  <style name="CustomTab" parent="@android:style/Widget.AppCompat.ActionBar.TabText">
        <item name="android:gravity">center</item>
    </style>
</resources>

我希望我的XML错误

enter image description here

2 个答案:

答案 0 :(得分:0)

在这里,我将发表关于这个问题的研究,因此我们可以继续挖掘这个问题,避免再犯错误。

请记住这种情况的两个重要条件:1。MasterDetailPage控制主/细节布局; 2. ContentPage控制详细页面的布局。

  1. Title不是android项目中Toolbar的标题,它是ContentPage的标题。您可以通过在ToolbarResource = Resource.Layout.Toolbar;的{​​{1}}方法中注释掉代码MainActivity或删除每个OnCreate的{​​{1}}值来检查此问题。因此,修改Title的样式将永远不会在这里工作。

  2. 根据第一个结果,我们可以删除每个ContentPage Toolbar的值,然后一起修改Title的布局。

  3. Toolbar.axml:

    ContentPage

    看起来很好,标题位于中心,但现在它出现了第二个问题:如何在选择详细信息页面时更改标题文本。

    1. 为了解决第二个问题,我为3个细节Toolbar创建了一个客户渲染,并为此渲染添加了程序集。
    2. 对于自定义<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:popupTheme="@style/ThemeOverlay.AppCompat.Light"> <TextView android:id="@+id/mytitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_gravity="center" android:text="11111" android:textColor="@android:color/white" android:textSize="20sp" android:textStyle="bold" /> </android.support.v7.widget.Toolbar> 渲染的部分,您可以参考Customizing a ContentPage,我添加了这样的程序集:

      ContentPage

      它解决了问题,我们可以在ContentPage方法中获取[assembly: ExportRenderer(typeof(ContactsPage), typeof(MyPageRenderer))] [assembly: ExportRenderer(typeof(ReminderPage), typeof(MyPageRenderer))] [assembly: ExportRenderer(typeof(TodoListPage), typeof(MyPageRenderer))] 的名称,如下所示:

      ContentPage

      似乎没问题,现在回答我们的最后一个问题:如何将页面名称设置为OnElementChanged的标题,这是我现在坚持的确切关键问题。

      在我编码的var pageName = e.NewElement.GetType().FullName; 中:

      Toolbar

      它可以找到MainActivityvar factory = LayoutInflater.From(this); var bar = factory.Inflate(ToolbarResource, null); var tv = (TextView)bar.FindViewById(Resource.Id.mytitle); tv.SetText("sdff", TextView.BufferType.Normal); 的文本是“11111”,它在xml中设置用于测试,但新的TextView永远不能成功设置。

      首先我认为UI操作应该在UIThread中完成,因此我将代码放在TextViewText中,但仍然无效。然后我想可能由于错误RunOnUiThreadnew Handler(Looper.MainLooper)而错误Toolbar,但我在这里找不到合适的上下文。我也试图找到这些片段,因为Context使用var factory = LayoutInflater.From(this);的源代码都失败了。

      然后我开始思考,为什么不创建我们的工具栏,而不是使用MasterDetailPage来创建工具栏。但是通过检查Fragment的源代码,我找到了这段代码:

      ToolbarResource = Resource.Layout.Toolbar;

      FormsAppCompatActivity继承自if (ToolbarResource != 0) { bar = LayoutInflater.Inflate(ToolbarResource, null).JavaCast<AToolbar>(); if (bar == null) throw new InvalidOperationException("ToolbarResource must be set to a Android.Support.V7.Widget.Toolbar"); } else bar = new AToolbar(this); SetSupportActionBar(bar); 时,我自己永远不会成功设置工具栏。

      最后我想也许我可以从MainActivity更改FormsAppCompatActivity继承而不是MainActivity,所以我们可以自己设置global::Xamarin.Forms.Platform.Android.FormsApplicationActivity,但仍然失败,它会在global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity行投掷Toolbar,我又陷入了死胡同。

      所以来我的解决方法,为NullReferenceException创建自定义呈现,并在LoadApplication(new App());中创建MasterDetailPage或其他内容并将此控件放在顶部中心,更改文本也来自OnElementChanged的自定义渲染。

      但我会称这是一个愚蠢的,顽固的想法,而不是一个解决方法,因为做了所有这些工作,为什么不使用本机android控件而不是使用xamarin的TextView来构建我们自己的视图?除非我们能找到设置原始ContentPage的{​​{1}}的方法,否则为Android应用创建我们自己的主要详细信息视图也应该是一种解决方法,我认为这是一个更好的方法。

答案 1 :(得分:0)

我知道这是一个非常老的问题,我在寻找其他东西时发现了它。该解决方案在Xamarin Forms中非常简单。只需在您的 ContentPage 中添加一个 NavigationPage.TitleView 标记。这样,您可以将任何样式的所需内容添加到导航栏:

ContentPage

<NavigationPage.TitleView>
    <Label Text="Centered Title" Style="{StaticResource TitleStyle}" />
</NavigationPage.TitleView>

样式可以是全局的(即:在App.xaml中):

<Style TargetType="Label" x:Key="TitleStyle">
  <Setter Property="TextColor" Value="WhiteSmoke" />
  <Setter Property="FontSize" Value="Medium" />
  <Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>