【问题标题】:Xamarin Forms MasterDetail Center TitleXamarin Forms MasterDetail 中心标题
【发布时间】:2016-12-06 11:15:30
【问题描述】:

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

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

有人能做到吗?

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

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 弄错了

【问题讨论】:

  • 您能否提供一些关于您如何构建MasterDetailPage 的代码?您的问题仅附有屏幕截图,很难知道我们将如何为您提供帮助。另外,请注意Xamarin.Forms 使用各自平台的默认行为。当涉及到 Android 主从页面的标题时,标题通常总是左对齐。
  • @Demitrian,我已经用一些源代码更新了这个问题
  • @YuraBabiy,感谢您的回复-但是我已经阅读了该帖子,但没有帮助
  • 这个案子你解决了吗?我已经调查了这个问题几天,只有我可以有一个解决方法,而且这个方法对我来说不是很优雅......我现在面临的最大问题是我无法获得渲染的ToolBar' s context,我用的是MainActivity作为它的context,但是好像打错了。

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


【解决方案1】:

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

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

  1. Title不是android项目中Toolbar的标题,而是ContentPage的标题。您可以通过在MainActivityOnCreate 方法中注释掉代码ToolbarResource = Resource.Layout.Toolbar; 来检查这一点,或者删除每个ContentPageTitle 的值。所以在这里修改Toolbar的样式是行不通的。

  2. 1234563 /li>

工具栏.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渲染部分可以参考Customizing a ContentPage,我添加了这样的组件:

[assembly: ExportRenderer(typeof(ContactsPage), typeof(MyPageRenderer))]
[assembly: ExportRenderer(typeof(ReminderPage), typeof(MyPageRenderer))]
[assembly: ExportRenderer(typeof(TodoListPage), typeof(MyPageRenderer))]

解决了这个问题,我们可以像这样在OnElementChanged方法中获取ContentPage的名字:

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);

它可以找到TextViewTextView的文本是“11111”,在xml中设置用于测试,但是新的Text永远设置不成功。

首先我认为UI操作应该在UIThread中完成,所以我将代码放在RunOnUiThreadnew Handler(Looper.MainLooper)中,但还是不行。然后我想我可能因为错误的Contextvar factory = LayoutInflater.From(this); 而弄错了Toolbar,但我在这里永远找不到正确的上下文。由于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 时,我将永远无法成功设置工具栏。

最后我想也许我可以改变MainActivityglobal::Xamarin.Forms.Platform.Android.FormsApplicationActivity继承而不是从global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,所以我们可以自己设置Toolbar,仍然失败,它会在该行抛出一个NullReferenceException LoadApplication(new App()); 我又陷入了死胡同。

所以来到我的解决方法,为MasterDetailPage创建一个自定义渲染,在OnElementChanged中,创建一个TextView或其他东西并将这个控件放在顶部中心,也从自定义渲染更改文本ContentPage

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

【讨论】:

  • 嗨,Grace,很棒的发现,您在那里节省了数小时的研究工作,您找到其他解决方案了吗?
【解决方案2】:

我知道这是一个很老的问题,我在寻找其他东西时发现了它。 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>

【讨论】:

    猜你喜欢
    • 2016-06-06
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 2016-09-29
    • 1970-01-01
    相关资源
    最近更新 更多