Android工具栏中心标题和自定义字体

Mat*_*hbl 347 android android-layout android-theme android-styles android-toolbar

我正在尝试找出使用自定义字体作为工具栏标题的正确方法,并将其置于工具栏中(客户端要求).

目前,我正在使用旧的ActionBar,我将标题设置为空值,并使用setCustomView自定义字体TextView并使用ActionBar.LayoutParams将其居中.

有没有更好的方法呢?使用新工具栏作为我的ActionBar.

MrE*_*r13 682

要在Toolbar你需要做的所有事情中使用自定义标题,请记住这Toolbar只是一个奇特的ViewGroup,所以你可以像这样添加一个自定义标题:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >


     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Toolbar Title"
        android:layout_gravity="center"
        android:id="@+id/toolbar_title" />


    </android.support.v7.widget.Toolbar>
Run Code Online (Sandbox Code Playgroud)

这意味着您可以根据TextView自己的喜好设计样式,因为它只是常规的TextView.因此,在您的活动中,您可以访问标题,如下所示:

Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top);
TextView mTitle = (TextView) toolbarTop.findViewById(R.id.toolbar_title);
Run Code Online (Sandbox Code Playgroud)

  • 如果其他人无法删除默认的应用名称标题,请执行以下操作:1.调用setSupportActionBar(yourToolbar)2.调用getSupportActionBar().setDisplayShowTitleEnabled(false); (179认同)
  • 要继续使用自定义TextView的默认样式,请尝试类似`style ="@ style/TextAppearance.AppCompat.Widget.ActionBar.Title"`([参见此答案](http://stackoverflow.com/questions/26455595/)越来越-动作条标题-的TextView与 - 程序兼容性-V7-R21/28034372#28034372)). (69认同)
  • 当工具栏上有汉堡图标时会发生什么?它不在完整工具栏宽度的中心,它将位于**ToolbarWidth - HamburgerIconWidth**的中心. (5认同)
  • 建议使用android:layout_width ="wrap_content"android:layout_height ="wrap_content"android:layout_gravity ="center". (4认同)
  • 如果你有一个按钮(家庭,导航抽屉等),添加android:paddingRight ="?attr/actionBarSize"可以帮助将文本居中放在屏幕中间 (4认同)
  • 对我来说,layout_gravity在工具栏中不起作用. (3认同)
  • 当它显然不起作用时,为什么这是接受的答案? (2认同)

Bin*_*abu 76

ToolBar标题是可设置的.您必须在主题中进行任何自定义.我给你举个例子.

工具栏布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    style="@style/ToolBarStyle.Event"
    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:minHeight="@dimen/abc_action_bar_default_height_material" />
Run Code Online (Sandbox Code Playgroud)

样式:

<style name="ToolBarStyle" parent="ToolBarStyle.Base"/>

<style name="ToolBarStyle.Base" parent="">
    <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
    <item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>

<style name="ToolBarStyle.Event" parent="ToolBarStyle">
    <item name="titleTextAppearance">@style/TextAppearance.Widget.Event.Toolbar.Title</item>
</style>

<style name="TextAppearance.Widget.Event.Toolbar.Title" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <!--Any text styling can be done here-->
    <item name="android:textStyle">normal</item>
    <item name="android:textSize">@dimen/event_title_text_size</item>
</style>
Run Code Online (Sandbox Code Playgroud)

  • 这不是文本的中心. (94认同)
  • 这是正确的方法.添加另一个`TextView`有点hacky,但反思的答案只是简单的邪恶. (57认同)
  • 你也不能改变标题的对齐方式. (15认同)
  • 清理,但您无法从样式设置自定义字体.可悲的是. (8认同)
  • @ user1560102没有任何关于将TextView添加到工具栏的问题.这就是它的设计目标. (7认同)
  • @Terry我想这是因为谷歌希望你坚持设计指南.就个人而言,我讨厌一些应用程序试图使ToolBar/ActionBar看起来很奇怪. (5认同)
  • 不要像OP要求的那样集中文本. (5认同)
  • @niqueco:您可以使用`<item name ="android:fontFamily"> @ font/your_font_here </ item>更改字体. (3认同)
  • 使用 styles.xml 无法使文本居中。我认为不可能使用样式更改文本对齐方式。 (2认同)

Gue*_*gon 65

这只是为了帮助加入所有作品,使用@ MrEngineer13答案与@Jonik和@Rick Sanchez评论正确的顺序,以帮助实现轻松集中!

布局TextAppearance.AppCompat.Widget.ActionBar.Title:

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <TextView
            android:id="@+id/toolbar_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"                      
            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
            android:layout_gravity="center" />

    </android.support.v7.widget.Toolbar>
Run Code Online (Sandbox Code Playgroud)

以正确的顺序实现的方式:

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);

    setSupportActionBar(toolbar);
    mTitle.setText(toolbar.getTitle());

    getSupportActionBar().setDisplayShowTitleEnabled(false);
Run Code Online (Sandbox Code Playgroud)

请不要忘记upvote @ MrEngineer13回答 !!!

这是一个示例项目ToolbarCenterTitleSample

在此输入图像描述

希望能帮助别人;)

  • 如果我设置setDisplayHomeAsUpEnabled(true)和setDisplayShowHomeEnabled(true); 向后箭头.然后标题不会成为中心.我试过设置actionBar.setTitle(""); 和setDisplayShowTitleEnabled(false).但仍然无法解决问题 (5认同)

Bug*_*yBR 52

我们无法直接访问ToolBar标题TextView,因此我们使用反射来访问它.

  private TextView getActionBarTextView() {
    TextView titleTextView = null;

    try {
        Field f = mToolBar.getClass().getDeclaredField("mTitleTextView");
        f.setAccessible(true);
        titleTextView = (TextView) f.get(mToolBar);
    } catch (NoSuchFieldException e) {
    } catch (IllegalAccessException e) {
    }
    return titleTextView;
}
Run Code Online (Sandbox Code Playgroud)

  • 注意:在设置工具栏标题后,您只能访问"mTitleTextView"字段!该字段首次使用时初始化为惰性字段. (5认同)
  • 虽然这很麻烦,但在尝试找到访问工具栏textview的方法后,此解决方案对我有用.谢谢. (3认同)
  • 如果你用ProGuard和`mTitleTextView`混淆你的代码会变成`abcde12345`怎么办? (2认同)

Nik*_*ski 30

这是从标题文本相关的方法来查找TextView实例Toolbar.

  public static TextView getToolbarTitleView(ActionBarActivity activity, Toolbar toolbar){
    ActionBar actionBar = activity.getSupportActionBar();
    CharSequence actionbarTitle = null;
    if(actionBar != null)
        actionbarTitle = actionBar.getTitle();
    actionbarTitle = TextUtils.isEmpty(actionbarTitle) ? toolbar.getTitle() : actionbarTitle;
    if(TextUtils.isEmpty(actionbarTitle)) return null;
    // can't find if title not set
    for(int i= 0; i < toolbar.getChildCount(); i++){
        View v = toolbar.getChildAt(i);
        if(v != null && v instanceof TextView){
            TextView t = (TextView) v;
            CharSequence title = t.getText();
            if(!TextUtils.isEmpty(title) && actionbarTitle.equals(title) && t.getId() == View.NO_ID){
                //Toolbar does not assign id to views with layout params SYSTEM, hence getId() == View.NO_ID
                //in same manner subtitle TextView can be obtained.
                return t;
            }
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)


fra*_*kee 21

定义以下类:

public class CenteredToolbar extends Toolbar {

    private TextView centeredTitleTextView;

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

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

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

    @Override
    public void setTitle(@StringRes int resId) {
        String s = getResources().getString(resId);
        setTitle(s);
    }

    @Override
    public void setTitle(CharSequence title) {
        getCenteredTitleTextView().setText(title);
    }

    @Override
    public CharSequence getTitle() {
        return getCenteredTitleTextView().getText().toString();
    }

    public void setTypeface(Typeface font) {
        getCenteredTitleTextView().setTypeface(font);
    }

    private TextView getCenteredTitleTextView() {
        if (centeredTitleTextView == null) {
            centeredTitleTextView = new TextView(getContext());
            centeredTitleTextView.setTypeface(...);
            centeredTitleTextView.setSingleLine();
            centeredTitleTextView.setEllipsize(TextUtils.TruncateAt.END);
            centeredTitleTextView.setGravity(Gravity.CENTER);
            centeredTitleTextView.setTextAppearance(getContext(), R.style.TextAppearance_AppCompat_Widget_ActionBar_Title);

            Toolbar.LayoutParams lp = new Toolbar.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            lp.gravity = Gravity.CENTER;
            centeredTitleTextView.setLayoutParams(lp);

            addView(centeredTitleTextView);
        }
        return centeredTitleTextView;
    }
}
Run Code Online (Sandbox Code Playgroud)

...然后只使用它而不是Toolbar像这样常规:

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent">

        <your.packagename.here.CenteredToolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="?attr/actionBarTheme"
            app:title="@string/reset_password_page_title"/>

        <!-- Other views -->

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

您仍然需要这两行代码Activity(与标准一样Toolbar):

Toolbar toolbar = (Toolbar) findViewByid(R.id.toolbar); // note that your activity doesn't need to know that it is actually a custom Toolbar
setSupportActionBar(binding.toolbar);
Run Code Online (Sandbox Code Playgroud)

而已!您不需要隐藏标准的左对齐标题,也不需要反复复制相同的XML代码等,只需使用CenteredToolbar它就像默认情况一样Toolbar.您也可以以编程方式设置自定义字体,因为您现在可以直接访问TextView.希望这可以帮助.

  • 谢谢!最好的解决方案,只是不要忘记将“v7.widget”导入到工具栏 (2认同)

Ab_*_*Ab_ 16

没有人提到这一点,但有一些属性Toolbar:

app:titleTextColor 用于设置标题文本颜色

app:titleTextAppearance 用于设置标题文本外观

app:titleMargin 用于设置保证金

还有其他特定方面的边缘,如marginStart等.

  • 我使用了这种方法,但是工具栏什么都没发生!我创建了一个新的'&lt;style&gt;'并将其设置为`android.support.v7.widget.Toolbar` TAG上的`app:titleTextAppearanc =“ style name”` (2认同)

ult*_*aon 12

我使用这个解决方案:

static void centerToolbarTitle(@NonNull final Toolbar toolbar) {
    final CharSequence title = toolbar.getTitle();
    final ArrayList<View> outViews = new ArrayList<>(1);
    toolbar.findViewsWithText(outViews, title, View.FIND_VIEWS_WITH_TEXT);
    if (!outViews.isEmpty()) {
        final TextView titleView = (TextView) outViews.get(0);
        titleView.setGravity(Gravity.CENTER);
        final Toolbar.LayoutParams layoutParams = (Toolbar.LayoutParams) titleView.getLayoutParams();
        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
        toolbar.requestLayout();
        //also you can use titleView for changing font: titleView.setTypeface(Typeface);
    }
}
Run Code Online (Sandbox Code Playgroud)


Aji*_*bey 10

没有工具栏TextView,我们可以使用下面的代码自定义字体

getSupportActionBar().setDisplayShowTitleEnabled(false);
or
getActionBar().setDisplayShowTitleEnabled(false);

public void updateActionbar(String title){
    SpannableString spannableString = new SpannableString(title);
    spannableString.setSpan(new TypefaceSpanString(this,  "futurastdmedium.ttf"),
            0, spannableString.length(),
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    mToolbar.setTitle(spannableString);
}
Run Code Online (Sandbox Code Playgroud)


Sha*_*one 8

    public class TestActivity extends AppCompatActivity {
    private Toolbar toolbar;

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

        toolbar = (Toolbar) findViewById(R.id.tool_bar); // Attaching the layout to the toolbar object
        setSupportActionBar(toolbar);

        customizeToolbar(toolbar);
    }

    public void customizeToolbar(Toolbar toolbar){
        // Save current title and subtitle
        final CharSequence originalTitle = toolbar.getTitle();
        final CharSequence originalSubtitle = toolbar.getSubtitle();

        // Temporarily modify title and subtitle to help detecting each
        toolbar.setTitle("title");
        toolbar.setSubtitle("subtitle");

        for(int i = 0; i < toolbar.getChildCount(); i++){
            View view = toolbar.getChildAt(i);

            if(view instanceof TextView){
                TextView textView = (TextView) view;


                if(textView.getText().equals("title")){
                    // Customize title's TextView
                    Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT);
                    params.gravity = Gravity.CENTER_HORIZONTAL;
                    textView.setLayoutParams(params);

                    // Apply custom font using the Calligraphy library
                    Typeface typeface = TypefaceUtils.load(getAssets(), "fonts/myfont-1.otf");
                    textView.setTypeface(typeface);

                } else if(textView.getText().equals("subtitle")){
                    // Customize subtitle's TextView
                    Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT);
                    params.gravity = Gravity.CENTER_HORIZONTAL;
                    textView.setLayoutParams(params);

                    // Apply custom font using the Calligraphy library
                    Typeface typeface = TypefaceUtils.load(getAssets(), "fonts/myfont-2.otf");
                    textView.setTypeface(typeface);
                }
            }
        }

        // Restore title and subtitle
        toolbar.setTitle(originalTitle);
        toolbar.setSubtitle(originalSubtitle);
    }
}
Run Code Online (Sandbox Code Playgroud)


Gab*_*tti 8

对于材质组件,从文档中描述的1.4.x版本开始,您可以使用.MaterialToolbar

只需将一个app:titleCentered和/或app:subtitleCentered多个属性添加到true您的MaterialToolbar.

就像是:

    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/topAppBar"
        app:titleCentered="true"
        ... />

Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

通过使用Material3包的Compose,您可以简单地使用:CenterAlignedTopAppBar

CenterAlignedTopAppBar(
    title = { Text("Centered TopAppBar") },
    navigationIcon = {
        IconButton(onClick = { /* doSomething() */ }) {
            Icon(
                imageVector = Icons.Filled.Menu,
                contentDescription = "Localized description"
            )
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您使用 Compose 和 Material2 包,则没有内置组件,但您可以自定义内部内容的布局,如本答案TopAppBar中所述。


vov*_*ost 6

一个非常快速简便的方法来设置自定义字体是使用自定义的titleTextAppearance一个fontFamily

添加到style.xml

<style name="ToolbarTitle" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <item name="android:textSize">16sp</item>
    <item name="android:textColor">#FF202230</item>
    <item name="android:fontFamily">@font/varela_round_regular</item>
</style>
Run Code Online (Sandbox Code Playgroud)

在您的res文件夹中创建一个字体文件夹(例如:varela_round_regular.ttf

阅读官方指南以了解更多https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html


Evg*_*nii 6

使用com.google.android.material.appbar.MaterialToolbarapp:titleCentered="true"标签

<com.google.android.material.appbar.MaterialToolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:titleCentered="true" />
Run Code Online (Sandbox Code Playgroud)


mar*_*136 5

布局:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >

     <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Toolbar Title"
        android:layout_gravity="center"
        android:gravity="center"
        android:id="@+id/toolbar_title" />
</android.support.v7.widget.Toolbar>
Run Code Online (Sandbox Code Playgroud)

码:

    Toolbar mToolbar = parent.findViewById(R.id.toolbar_top);
    TextView mToolbarCustomTitle = parent.findViewById(R.id.toolbar_title);

    //setup width of custom title to match in parent toolbar
    mToolbar.postDelayed(new Runnable()
    {
        @Override
        public void run ()
        {
            int maxWidth = mToolbar.getWidth();
            int titleWidth = mToolbarCustomTitle.getWidth();
            int iconWidth = maxWidth - titleWidth;

            if (iconWidth > 0)
            {
                //icons (drawer, menu) are on left and right side
                int width = maxWidth - iconWidth * 2;
                mToolbarCustomTitle.setMinimumWidth(width);
                mToolbarCustomTitle.getLayoutParams().width = width;
            }
        }
    }, 0);
Run Code Online (Sandbox Code Playgroud)


Mon*_*ski 5

我针对这个问题使用的解决方案:

 public static void applyFontForToolbarTitle(Activity a){
        Toolbar toolbar = (Toolbar) a.findViewById(R.id.app_bar);
        for(int i = 0; i < toolbar.getChildCount(); i++){
            View view = toolbar.getChildAt(i);
            if(view instanceof TextView){
                TextView tv = (TextView) view;
                if(tv.getText().equals(a.getTitle())){
                    tv.setTypeface(getRuneTypefaceBold(a));
                    break;
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

对于中心重力,我认为有必要将布局参数更改为水平 match_parent,然后:

tv.setGravity(Gravity.CENTER);
Run Code Online (Sandbox Code Playgroud)


use*_*008 5

MaterialToolbar来自Material Components 1.4.0-alpha02现在可以通过将titleCentered属性设置为来使工具栏的标题居中true

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/topAppBar"
        style="@style/Widget.MaterialComponents.Toolbar.Primary"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:titleCentered="true" />

</com.google.android.material.appbar.AppBarLayout>
Run Code Online (Sandbox Code Playgroud)