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

我试图找出正确的方式来使用自定义字体的工具栏标题,并居中在工具栏(客户端要求)。

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

有没有更好的方法来做到这一点? 使用新的工具栏作为我的ActionBar。

要在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> 

这意味着你可以设置TextView样式,不过你可能会喜欢,因为它只是一个普通的TextView 。 所以在你的活动中,你可以像这样访问标题:

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

工具栏标题是可风化的。 您所做的任何自定义都必须在主题中进行。 我会给你一个例子。

工具栏布局:

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

样式:

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

我们没有直接访问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; } 

这只是为了帮助@Jonik和@Rick Sanchez用@ MrEngineer13回答所有作品的评论以正确的顺序来帮助实现以标题为中心的easly!

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> 

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

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

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

这是一个示例项目ToolbarCenterTitleSample

在这里输入图像描述

希望能帮助别人;)

这里是标题文本从属方法从Toolbar查找TextView实例。

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

没有人提到过这个,但是Toolbar有一些属性:

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

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

app:titleMargin设置边距

还有其他的特定边缘,如marginStart

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

没有工具栏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); } 

我使用这个解决方案:

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

布局:

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

码:

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

你可以像下面一样使用

  <android.support.v7.widget.Toolbar android:id="@+id/top_actionbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppThemeToolbar"> <TextView android:id="@+id/pageTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" /> </android.support.v7.widget.Toolbar> 

我不知道在appcompat库中是否有任何改变,但它是相当微不足道的,不需要反思。

 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // loop through all toolbar children right after setting support // action bar because the text view has no id assigned // also make sure that the activity has some title here // because calling setText() with an empty string actually // removes the text view from the toolbar TextView toolbarTitle = null; for (int i = 0; i < toolbar.getChildCount(); ++i) { View child = toolbar.getChildAt(i); // assuming that the title is the first instance of TextView // you can also check if the title string matches if (child instanceof TextView) { toolbarTitle = (TextView)child; break; } } 

我用于这个问题的解决方案:

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

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

 tv.setGravity(Gravity.CENTER); 

我解决了这个解决方案,这是一个下面的代码:

 <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:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Order History" android:layout_gravity="center" android:id="@+id/toolbar_title" android:textSize="17sp" android:textStyle="bold" android:textColor="@color/colorWhite" /> </android.support.v7.widget.Toolbar> 

你可以改变标题/标签,在活动中,写下面的代码:

 Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top); 

TextView mTitle =(TextView)toolbarTop.findViewById(R.id.toolbar_title); mTitle.setText( “@串/ ……”);

定义以下类:

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

…然后只是使用它,而不是像这样的常规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> 

您的活动中仍然需要这两行代码(与标准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); 

而已! 您不需要隐藏标准的左对齐标题,也不需要一遍又一遍地重复使用相同的XML代码,只需使用CenteredToolbar好像它是默认的Toolbar 。 您也可以编程设置您的自定义字体,因为您现在可以直接访问TextView 。 希望这可以帮助。

由于android.support.v7.appcompat 24.2 Toolbar有方法setTitleTextAppearance ,你可以设置它的字体没有外部textview

在styles.xml中创建新的样式

 <style name="RobotoBoldTextAppearance"> <item name="android:fontFamily">@font/roboto_condensed_bold</item> </style> 

并使用它

 mToolbar.setTitleTextAppearance(this, R.style.RobotoBoldTextAppearance); 

即使向工具栏添加文本视图也可以解决标题样式限制的问题,但存在一个问题。 既然我们没有把它添加到布局,我们没有太多的宽度控制。 我们可以使用wrap_content或match_parent。

现在考虑一下我们在工具栏的右边有一个searchView作为按钮的场景。 如果标题内容更多,则会在按钮顶部遮挡它。 没有办法控制这个标签的宽度,如果你想有一个响应式设计,你不想做的事情。

所以,这里有一个为我工作的解决方案,与向工具栏中添加文本视图稍有不同。 取而代之,将工具栏和文本视图添加到相对布局,并确保文本视图位于工具栏的顶部。 然后,我们可以使用适当的边距,并确保文本视图显示在我们希望显示的位置。

确保您将工具栏设置为不显示标题。

这里是这个解决方案的XML:

 <RelativeLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary"> <android.support.v7.widget.Toolbar android:theme="@style/ThemeOverlay.AppCompat.Dark" android:id="@+id/activity_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:titleTextAppearance="@style/AppTheme.TitleTextView" android:layout_marginRight="40dp" android:layoutMode="clipBounds"> <android.support.v7.widget.SearchView android:id="@+id/search_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:foregroundTint="@color/white" /> </android.support.v7.widget.Toolbar> <TextView android:id="@+id/toolbar_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="90dp" android:text="@string/app_name" android:textSize="@dimen/title_text_size" android:textColor="@color/white" android:lines="1" android:layout_marginLeft="72dp" android:layout_centerVertical="true" /> </RelativeLayout> 

解决上面提到的@ ankur-chaudhary的问题。

尝试

 @Override public void onBackPressed() { if(getTitle().equals(getResources().getString(R.string.app_name))) { super.onBackPressed();} else { //set visiblity } } 
 private void makeTitleCenter(String title, Toolbar toolbar) { if (title != null && !TextUtils.isEmpty(title.trim())) { final String tag = " "; if (getSupportActionBar() != null) { getSupportActionBar().setTitle(tag); } TextView titleTv = null; View leftBtn = null; for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); CharSequence text = null; if (view instanceof TextView && (text = ((TextView) view).getText()) != null && text.equals(tag)) { titleTv = (TextView) view; } else if (view instanceof ImageButton) { leftBtn = view; } } if (titleTv != null) { final TextView fTitleTv = titleTv; final View fLeftBtn = leftBtn; fTitleTv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { fTitleTv.getViewTreeObserver().removeOnGlobalLayoutListener(this); int leftWidgetWidth = fLeftBtn != null ? fLeftBtn.getWidth() : 0; fTitleTv.setPadding(DimenUtil.getResources().getDisplayMetrics().widthPixels / 2 - leftWidgetWidth - fTitleTv.getWidth() / 2, 0, 0, 0); fTitleTv.requestLayout(); } }); } } } 

设置android:gravity="center"为我工作

没有什么造型。 工具栏基本上是一个ViewGroup你需要做的就是设置元素的重力。

  <android.support.v7.widget.Toolbar android:id="@+id/htab_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_gravity="top" android:background="@color/partial_transparent" android:gravity="center" app:layout_collapseMode="pin" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> 
  <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:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Toolbar Title" android:textSize="25sp" android:textStyle="bold" android:textColor="@color/white" android:layout_gravity="center" android:id="@+id/toolbar_title" /> </android.support.v7.widget.Toolbar> 

上述解决方案都不适合我。 我发现只有重写默认的Actionbar行为才能实现我的自定义视图。

试试这个代码:

getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); getSupportActionBar().setCustomView(R.layout.toolbar_home);

 Typeface face= Typeface.createFromAsset(getAssets(), "font/font.ttf"); // your custom font Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTypeface(face); setSupportActionBar(toolbar); 

其他教程:

  1. Android工具栏示例
  2. 在Android中使用自定义字体
  3. ActionBar教程与例子