0

我正在启动我的第一个 Xamarin Forms 应用程序 - 目前只是 Hello World - 但是我需要能够将标题栏中的文本居中。我正在使用一个 MasterDetailPage,它有一个 ContentPage 作为 Master,一个 NavigationPage 作为 Detail。从下面的屏幕截图中,我希望能够将“主页”居中。

我已经尝试过标记,例如在 AppCompact 主题中更改操作栏选项卡文本大小的答案,但是似乎没有任何影响文本的位置。我还尝试了自定义渲染器,但是没有用。

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

用一些代码更新我的问题。我的 MasterDeutil.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
                    }
                }
            };
        }
    }

样式.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

在此处输入图像描述

4

2 回答 2

0

我知道这是一个很老的问题,我在寻找其他东西时发现了它。Xamarin Forms 中的解决方案非常简单。只需将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>
于 2020-08-24T15:06:51.443 回答
0

在这里我将发布我对这个问题的研究,所以我们可以继续挖掘这个问题并避免再次犯我的错误。

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

  1. Title不是Toolbarandroid 项目的标题,而是ContentPage. 您可以通过注释掉'方法ToolbarResource = Resource.Layout.Toolbar;中的代码或删除for each的值来检查这一点。所以修改 的样式 在这里永远行不通。MainActivityOnCreateTitleContentPageToolbar

  2. 基于第一个结果,自然而然的想法是我们可以删除Titlefor each的值,并像这样ContentPage一起修改布局。Toolbar

工具栏.axml:

<?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>

看起来不错,标题在中间,但现在又来了第二个问题:如何在选择详情页时更改标题文本。

  1. 为了解决第二个问题,我为 3 个细节创建了一个客户渲染,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,这正是我现在坚持的关键问题。

MainActivity我这样编码:

var factory = LayoutInflater.From(this);
var bar = factory.Inflate(ToolbarResource, null);
var tv = (TextView)bar.FindViewById(Resource.Id.mytitle);
tv.SetText("sdff", TextView.BufferType.Normal);

它可以找到TextView,并且文本TextView是“11111”,这是在xml中设置的用于测试,但新的Text永远无法设置成功。

一开始我认为UI操作应该在UIThread中完成,所以我把代码放在了RunOnUiThreador中new Handler(Looper.MainLooper),但是还是不行。然后我想我可能Toolbar因为错误Context:弄错了var factory = LayoutInflater.From(this);,但我在这里永远找不到正确的上下文。我也试图找到从 used 的源代码以来的片段MasterDetailPageFragment都失败了。

然后我开始想,我们为什么不创建我们的工具栏,而不是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继承 fromglobal::Xamarin.Forms.Platform.Android.FormsApplicationActivity而不是 from global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,所以我们可以自己设置Toolbar,仍然失败,它会抛出 a NullReferenceExceptionLoadApplication(new App());我又陷入了死胡同。

所以来到我的解决方法MasterDetailPageOnElementChanged为.TextViewContentPage

但我认为这是一个愚蠢、固执的想法,而不是一种解决方法,因为做了所有这些大量的工作,为什么不使用原生 android 控件而不是使用 xamarin 来构建我们自己的视图MasterDetailPage呢?除非我们能找到一种方法来设置Textoriginal Toolbar,否则为 android 应用程序创建我们自己的主详细信息视图也应该是一种解决方法,我认为这是一个更好的解决方法。

于 2016-12-15T06:30:19.160 回答