Android: 如何将标题居中显示在工具栏中

22

我第一次在我的项目中使用ToolBar,不知道如何自定义android中的工具栏。我需要将标题居中到工具栏中,请告诉我如何做。

提前感谢。


1
可能是重复的问题:Android toolbar center title and custom font - Petter Friberg
20个回答

40

在工具栏中心只添加一个TextView的问题在于,如果在工具栏中添加菜单项,这将使居中文本偏移。

为了解决这个问题,我将文本放置在Toolbar的顶部,而不是内部。这样无论您添加多少图标,都不会偏移居中文本:

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

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

        <TextView
            android:layout_centerInParent="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/app_name"/>

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

这样做就不需要为工具栏上的返回按钮/溢出菜单/搜索图标等的偏移间距编写任何额外的逻辑,因为居中的文本在其上方而不是其中。


1
这很有用,谢谢你的想法。我实现它时没有使用额外的AppBarLayout层。 - jk7
但是如果将其从工具栏中移除,您将无法在其上使用工具栏动画或应用栏行为。 - Mahdi

35

记住,Toolbar只是像其他ViewGroup一样的一个。所以你可以把View放进去。在你的情况下,你需要在Toolbar中放置一个TextView

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Some Fancy Title"
        android:gravity = "center"
        android:id="@+id/toolbar_title" />

</android.support.v7.widget.Toolbar>

现在,通过首先检索它,然后使用setSupportActionBar()Toolbar设置为您的操作栏。

由于TextView的重力设置为center,因此文本必须居中显示。


16
我的情况是将工具栏设置为操作栏,并在左侧放置了一个导航图标。这样一来,工具栏的标题不再居中,会稍微向右倾斜。怎么修复呢? - Lạng Hoàng
7
应该使用layout_gravity而不是gravity。gravity用于定义视图内部内容的放置方式,而layout_gravity用于指定视图相对于其父容器的位置。 - D V Ramana
@LạngHoàng,你解决了你的问题吗?我也遇到了同样的问题,似乎没有什么办法可以解决它。 - Eggman87
6
尝试将您的textview的宽度设置为WRAP_CONTENT,并将其LAYOUT_GRAVITY设置为CENTER。这样,即使显示主页按钮,textview也会在父视图中居中对齐。 - momoja
3
您还应为“工具栏”设置“gravity”和“layout_gravity”。 - Vahid Amiri
显示剩余2条评论

11
您可以通过对标题和级别右侧填充进行包装并使其具有标题的默认左填充,从而将工具栏强制居中。然后将父级工具栏的背景颜色设置为相同的颜色,在我的示例中为白色,这样被包装标题截断的部分就与其余部分保持一致。
<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white">

            <android.support.v7.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="wrap_content"
               android:layout_height="56dp"
               android:layout_gravity="center_horizontal"
               android:paddingEnd="15dp"
               android:paddingRight="15dp"
               android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
               app:titleTextColor="@color/black"/>

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

问题是,返回箭头按钮也会居中。 - Andrew

10

ToolBar是一个视图组。要使文本居中对齐,请使用

app_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/in.chabu"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    app:theme="@style/ToolBarTheme" 
    android:minHeight="?attr/actionBarSize">

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/title_activity_sign_up"
        android:layout_gravity="center"
        android:id="@+id/toolbar_title" 
        android:textStyle="bold"
        android:textColor="@android:color/white"/>

</android.support.v7.widget.Toolbar>

活动报名

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="in.chabu.activities.SignUpActivity" >

    <include 
        android:id="@+id/tool_bar"
        layout="@layout/app_bar"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tool_bar"
        android:text="@string/hello_world" />

</RelativeLayout>

活动

public class SignUpActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sign_up);

        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);

        setSupportActionBar(toolbar);

        getSupportActionBar().setDisplayShowTitleEnabled(false);
    }


}

9
最终的用户界面如下: enter image description here 在我的项目中,我在左侧设置了导航图标,在右侧设置了菜单(不止一个),并想将标题放在中心。
我使用了setSupportActionBar(toolbar)_actionBar.setCustomView(R.layout.actionbar_filter);。我的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/lib_action_bar_filter_view_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/selectableItemBackgroundBorderless"
                android:gravity="center">

    <TextView
        android:id="@id/lib_action_bar_filter_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:maxLines="2"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:textColor="@android:color/white"
        android:textSize="15sp"/>

</RelativeLayout>

我的工具栏扩展了android.support.v7.widget.Toolbar,然后(有点硬编码)测量RelativeLayout的大小,最后将其布局在水平中心。

/**
 * Customized the <code>RelativeLayout</code> inside the <code>Toolbar</code>.
 * Because by default the custom view in the <code>Toolbar</code> cannot set
 * width as our expect value. So this class allows setting the width of the
 * <code>RelativeLayout</code> to take up any percentage of the screen width.
 */
public class CenteredToolbar extends Toolbar {

private static final double WIDTH_PERCENTAGE = 0.8;

private TextView titleView;

public CenteredToolbar(Context context) {
    this(context, null);
}

public CenteredToolbar(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, android.support.v7.appcompat.R.attr.toolbarStyle);
}

public CenteredToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        View view = this.getChildAt(i);
        if (view instanceof RelativeLayout) {
            int width = getMeasuredWidth();
            ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
            layoutParams.width = (int) (width * WIDTH_PERCENTAGE);
            view.setLayoutParams(layoutParams);
            break;
        }
    }
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        View view = this.getChildAt(i);
        if (view instanceof RelativeLayout) {
            forceTitleCenter(view);
            break;
        }
    }
}

/**
 * Centering the layout.
 *
 * @param view The view to be centered
 */
private void forceTitleCenter(View view) {
    int toolbarWidth = getMeasuredWidth();
    int relativeLayoutWidth = view.getMeasuredWidth();
    int newLeft = (int) (toolbarWidth - relativeLayoutWidth) / 2;
    int top = view.getTop();
    int newRight = newLeft + relativeLayoutWidth;
    int bottom = view.getBottom();
    view.layout(newLeft, top, newRight, bottom);
}
}

附上我的工具栏布局。也许你并不需要这个,我只是将它粘贴在这里供其他人参考:

<?xml version="1.0" encoding="utf-8"?>
<com.chinalwb.CenteredToolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/vmosolib_toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    app:contentInsetEnd="0dp"
/>

9
只是在 Toolbar 中再放置一个 TextView 是不足以使标题相对于屏幕居中的,它的位置将取决于工具栏中的其他项目(后退按钮、菜单项)。
为了让标题居中,您可以手动设置其位置:
扩展 android.support.v7.widget.Toolbar 类并进行以下更改:
1. 添加 TextView 2. 覆盖 onLayout() 并将 TextView 的位置设置为居中 (titleView.setX((getWidth() - titleView.getWidth())/2)) 3. 覆盖 setTitle() 在其中将标题文本设置为新文本视图
在布局文件中,您可以像这样使用此类:
<com.example.CenteredToolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    android:theme="@style/ToolbarTheme"/>

此外,为了使新的标题文本看起来像标准标题,您应该将 titleTextAppearance 样式应用到新的 TextView 上(titleView.setTextAppearance(context, textAppearanceStyleResId))。

这种调整似乎更好。是否可以通过覆盖一些函数,在工具栏中的默认标题TextView的确切位置上添加另一个TextView?[链接](http://stackoverflow.com/questions/42315935/how-to-add-textview-in-same-location-of-title-in-toolbar) - Mehmed
@Mehmed,您的工具栏中需要两个TextView(一个居中,一个在默认位置)还是只需要一个自定义TextView在默认位置? 如果选择第二个选项,则只需删除重写的onLayout方法并在构造函数中自定义titleView TextView即可。 - user2137020
我需要两个TextView。我不想删除工具栏中的默认标题TextView,以便能够在代码中使用toolbar.setTitle()。我想在其上方添加另一个TextView。我的目标是在打开抽屉时在标题之间进行动画。我的抽屉必须位于工具栏下面,这就是为什么我正在尝试这样做的原因。顺便说一句,谢谢您的回复。 - Mehmed
在答案中使用的代码,原始TextView仍然存在,但是它是空的,因为我们覆盖了setTitle()方法而没有调用super.setTitle() - user2137020
这个评论启发了我解决项目中的问题。我会把我的代码作为答案发布。 - LiuWenbin_NO.
显示剩余3条评论

8
当您将主页或返回按钮与居中标题一起使用时,如果标题不再居中并稍微向右移动,请将您的TextView设置为width=wrap_content和layout_gravity=center。
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"/>

wrap_content 对我很有帮助,之前我只尝试过 layout_gravity。谢谢。 - nilsi

5

这真的很有帮助,可以消除自定义实现。 - Parth Patel

4

我稍微修改了工具栏的源代码,使标题居中对齐。

public class CenterTitleToolbar extends Toolbar {
    private AppCompatTextView titleTextView;


    public CenterTitleToolbar(Context context) {
        super(context);
    }

    public CenterTitleToolbar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public CenterTitleToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setTitle(CharSequence title) {
        if (!TextUtils.isEmpty(title)) {
            if (titleTextView == null) {
                final Context context = getContext();
                titleTextView = new AppCompatTextView(context);
                titleTextView.setSingleLine();
                titleTextView.setEllipsize(TextUtils.TruncateAt.END);
                titleTextView.setTextAppearance(context, R.style.TextAppearance_MaterialComponents_Headline6);
                final LayoutParams lp = generateDefaultLayoutParams();
                lp.gravity = Gravity.CENTER;
                titleTextView.setLayoutParams(lp);
            }
            if (titleTextView.getParent() != this) {
                addSystemView(titleTextView);
            }
        } else if (titleTextView != null && titleTextView.getParent() == this) {
            removeView(titleTextView);
        }
        if (titleTextView != null) {
            titleTextView.setText(title);
        }
    }

    private void addSystemView(View v) {
        final ViewGroup.LayoutParams vlp = v.getLayoutParams();
        final LayoutParams lp;
        if (vlp == null) {
            lp = generateDefaultLayoutParams();
        } else if (!checkLayoutParams(vlp)) {
            lp = generateLayoutParams(vlp);
        } else {
            lp = (LayoutParams) vlp;
        }
        addView(v, lp);
    }

}

新的Android Material library中已经包含了TextAppearance_MaterialComponents_Headline6文本样式。


generateDefaultLayoutParams 返回什么? - Vincent Paing
1
@Vincent_Paing protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); }generateDefaultLayoutParams 方法在超类中声明。 - Sourav Bagchi

3

根据@LiuWenbin_NO的说法,我创建了一个自定义工具栏,不需要额外的视图来把标题居中在文本视图中。

import android.content.Context
import android.util.AttributeSet
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import android.view.Gravity

class CenteredToolbar(context: Context, attrs: AttributeSet?, defStyleAttr: Int):
Toolbar(context, attrs, defStyleAttr) {

constructor(context: Context) : this(context, null, 0)

constructor(context: Context, attrs: AttributeSet) : this(context, attrs, androidx.appcompat.R.attr.toolbarStyle)

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
    super.onLayout(changed, l, t, r, b)

    val childCount = childCount
    for (i in 0 until childCount) {
        val view = this.getChildAt(i)
        if (view is TextView) {
            forceTitleCenter(view,l, r)
            break
        }
    }
}

/**
 * Centering the layout.
 *
 * @param view The view to be centered
 */
private fun forceTitleCenter(view: TextView, l: Int,  r: Int) {
    val top = view.getTop()
    val bottom = view.getBottom()
    view.layout(l, top, r, bottom)
    navigationIcon?.let{
        view.setPadding(it.intrinsicWidth,0,0,0)
    }
    view.gravity = Gravity.CENTER
}

}

 <ui.customView.CenteredToolbar
                android:id="@+id/apd_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:navigationIcon="@drawable/ic_search"
                app:title="Check Title"
                app:elevation="4dp"/>

返回图标垂直居中。 - Bagus Aji Santoso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接