在新的材料设计中,是不是有官方 API 用于工具栏上的中心标题,就像流行的 Android 应用程序一样?

Posted

技术标签:

【中文标题】在新的材料设计中,是不是有官方 API 用于工具栏上的中心标题,就像流行的 Android 应用程序一样?【英文标题】:Is there an official API for centered title on Toolbar like on popular Android apps, in the new material design?在新的材料设计中,是否有官方 API 用于工具栏上的中心标题,就像流行的 Android 应用程序一样? 【发布时间】:2019-07-19 00:55:26 【问题描述】:

背景

过去,Google 总是显示工具栏以使标题左对齐:

https://material.io/develop/android/components/app-bar-layout/

然而,最近,它的一些应用似乎标题居中,即使它的左右内容不是对称的。示例在"Messages" app:

"Google News" app 上:

它还更新了材料指南here。示例:

有些人喜欢称之为“材料设计 2.0”,因为它更新了很多东西。

问题

虽然从 *** 被称为“ActionBar”(例如 here )开始就有很多类似的问题,但这里有所不同,因为它应该有支持库(又名“Android-X”)有办法正确处理它,因为事情已经发生了变化,现在 Google 应该支持它,因为它是指南的一部分,也是各种 Android 应用程序的一部分。

我尝试过的

我尝试在工具栏中添加一个视图,但即使通过着色视图,您也可以看到它并没有真正居中,自动地,这是在添加更多操作项或向上按钮之前:

activity_main.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_
        android:layout_
        tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
            android:layout_
            android:layout_
            android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_
                android:layout_
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay">

            <TextView android:layout_ android:layout_ android:text="title"
                      android:gravity="center" android:background="#33ff0000"
                      android:id="@+id/titleTextView"/>
        </androidx.appcompat.widget.Toolbar>

    </com.google.android.material.appbar.AppBarLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

此解决方案与其他 *** 线程上与此问题类似的许多其他解决方案类似,就像那里一样,它无法真正使文本居中,而在 Google 的尝试中,无论操作项的数量如何,它都能正确居中和周围的其他景色。

我还想出了一个更好的解决方法:在每一侧都有一个工具栏,并使 TextView 的边距是两者的最大值。甚至还有一个库,“Toolbar-Center-Title”......但同样,这是一种解决方法。不是我要问的。

问题

现在有没有官方的方法可以让工具栏的标题居中,不管有多少操作项,也不管另一边有什么(例如向上按钮)?

如果是这样,如何做到这一点?

注意:同样,我对变通办法不感兴趣。有很多变通方法,我自己可以想到。

【问题讨论】:

【参考方案1】:

TL;DR:不,目前还没有官方方法可以让标题在工具栏上居中。


我认为没有正式的方法可以做到这一点,至少现在还没有。但我知道Flutter 框架支持它,而且非常简单:您只需将centerTitle: true 传递给appbar 构造函数,如answer 中所述。您在问题中提到的应用很有可能是使用 Flutter 构建的,因为它们都来自 Google。

我认为最接近您预期布局的解决方法是将 TextView 放在工具栏顶部,如图所示 here:

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar_layout"
    android:layout_
    android:layout_>
    <RelativeLayout
        android:layout_
        android:layout_>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_
            android:layout_
            android:theme="@style/ThemeOverlay.AppCompat.ActionBar">
        </android.support.v7.widget.Toolbar>

        <TextView
            android:layout_centerInParent="true"
            android:layout_
            android:layout_
            android:text="@string/app_name"/>

    </RelativeLayout>
</android.support.design.widget.AppBarLayout>

但是,如果官方的 Android API 可以像 Flutter 一样支持这一点,那就太好了。也许您想向Material Components Android Issue Tracker 发送功能请求?

【讨论】:

您编写的代码类似于我发现的其他解决方法。不能很好地工作,因为它可能会在这种情况下重叠。如果我想要一种解决方法,我会在每一侧都有一个工具栏,并使 TextView 的边距是两者的最大值。但我对解决方法不感兴趣。我已经更新了问题。 看来你是对的。没有官方的方法可以做到这一点。解决方法并不重要。所有这些可能都行不通。甚至还有一个图书馆:github.com/RaviKoradiya/Toolbar-Center-Title。不确定它的效果如何。我在问题跟踪器上找到了这个:issuetracker.google.com/issues/123303613 @androiddeveloper 我昨天 twitted this question 和 Chris Banes,他也在工具栏上工作过 mentioned overlaying it。让我们希望问题跟踪器上的功能请求成为实际功能。【参考方案2】:

textAlignment="center" 怎么样?当AppCompatTextView 设置了layout_width="match_parent" 时,RelativeLayout 就可以解决问题;例如:

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/customView"
        android:minHeight="?android:attr/actionBarSize"
        android:layout_
        android:layout_
        android:orientation="vertical"
        android:gravity="top">

        <RelativeLayout
            android:layout_
            android:layout_>

            <!-- Home Button -->
            <include
                layout="@layout/button_home_menu"
                android:layout_
                android:layout_
                android:layout_gravity="start"/>

            <androidx.appcompat.widget.LinearLayoutCompat
                android:layout_
                android:layout_
                android:orientation="vertical"
                android:padding="8dp">

                <androidx.appcompat.widget.AppCompatTextView
                    android:id="@+id/title"
                    android:layout_
                    android:layout_
                    android:text="@string/app_name"
                    android:textAlignment="center"
                    android:textAppearance="?android:attr/textAppearanceLarge"
                    android:textSize="18sp"
                    android:textStyle="bold"/>

                <androidx.appcompat.widget.AppCompatTextView
                    android:id="@+id/subtitle"
                    android:layout_
                    android:layout_
                    android:text="@string/app_version"
                    android:textAlignment="center"
                    android:textAppearance="?android:attr/textAppearanceMedium"
                    android:textSize="12sp"
                    android:textStyle="bold"/>

            </androidx.appcompat.widget.LinearLayoutCompat>

        </RelativeLayout>

    </androidx.appcompat.widget.LinearLayoutCompat>

</layout>

不利的一面是,当将多个菜单项显示为操作按钮时 - 或者当将非常长的字符串显示为标题时,标题可能会与它们重叠 - 但是当仅显示一个或两个操作按钮与标题的组合时适合视觉上可用的宽度,这很好用 - 那是因为菜单配置 ifRoom 将始终适用,因为有空间。否则只能测量工具栏的哪一侧具有最宽的项目容器 - 然后调整另一侧项目容器的宽度。根据可用房间缩放字体大小也可能是一种选择,以使其动态适应。

【讨论】:

再说一次,它不是官方的,不会总是按应有的方式工作......如果我想要一个解决方法,我会在每一侧都有一个工具栏,并使 TextView 有边距两者的最大值。但我对解决方法不感兴趣。我已经更新了问题。 @androiddeveloper 官方方法可能是使用不同的menu.xml,具体取决于屏幕大小和布局方向 - 或数据绑定app:showAsAction always/ifRoom。虽然由于空间不足而具有以... 结尾的居中标题,但这也不是最佳选择。您提供的示例最多有一个操作按钮。 app:showAsAction 是正确控制重叠的唯一方法。 "您提供的示例最多只有一个操作按钮" - 不正确。第一个(消息应用程序)至少有 2 。其他在溢出菜单项上。 @androiddeveloper 在视觉上,这仍然只是一个 app:showAsAction 或者 alwaysifRoom (加上菜单点)......但是用 XML 标记来控制它并不完全是一个动态布局。数据绑定操作按钮的可用宽度 - 或其可见计数 - 似乎仍然是最可靠的。我假设,没有默认方法将标题居中的原因是,ActionBarMenu 是两个独立的组件 - 因此必须将它们连接起来。 再一次,这是不正确的。至少有 2 个行动项目。一个是alwaysifRoom,其余的可能是never。要查看其余的操作项,请单击溢出按钮。如果只有一个操作项,溢出按钮也不会存在,使单个操作项向右移动一点。【参考方案3】:

没有正式的方法可以做到这一点,但子类化提供了大多数覆盖范围而没有疯狂的技巧。

https://gist.github.com/bmc08gt/40a151e93969f2633b9b92bca4b31e83

【讨论】:

很高兴展示它,但为什么不在这里写代码呢?它不是那么长。无论如何,我要求的是正式的方式。我甚至为此提到了一个库:github.com/RaviKoradiya/Toolbar-Center-Title 发帖时是移动设备,因此将更新我的帖子以包含代码 sn-p。此外,当您可以包含单个类以方便所需内容时,无需添加另一个依赖项。这提供了与官方工具栏相同的开箱即用方法和“行为”。【参考方案4】: app:contentInsetStart="@dimen/margin_64" //64dp app:contentInsetEnd="@dimen/margin_64" // 64dp

工具栏部分

 <com.google.android.material.appbar.AppBarLayout
        android:layout_
        android:layout_
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.appbar.MaterialToolbar
            android:layout_
            android:layout_
            android:gravity="center_horizontal"
            app:contentInsetEnd="@dimen/margin_64"
            app:contentInsetStart="@dimen/margin_64">
            <TextView
                android:layout_
                android:layout_
                android:text="Create"
                android:gravity="center_horizontal"
                android:textColor="@color/white"
                android:textSize="18sp" />

        </com.google.android.material.appbar.MaterialToolbar>
  </com.google.android.material.appbar.AppBarLayout>

【讨论】:

上面的“contentInsetStart”部分是什么?什么是“margin_64”?

以上是关于在新的材料设计中,是不是有官方 API 用于工具栏上的中心标题,就像流行的 Android 应用程序一样?的主要内容,如果未能解决你的问题,请参考以下文章

.NET WEB API 使用 FTP 在新的浏览器选项卡中打开图像文件

用于创建 API 文档/提案的平台无关工具 [关闭]

onActivityResult() 未在新的嵌套片段 API 中调用

需要学习用于剩余api自动化的Python机器人框架的材料

在新的 FlutterFire API 中使用 setData 和 merge: true

在新的 Gmail API 中批量提取电子邮件