Android标题居中的Toolbar
来源:互联网 发布:视频编辑软件中文版 编辑:程序博客网 时间:2024/06/06 10:46
2017年特意写第一篇博客开个头。之前一直不写博客的原因,一个是懒,另一个是因为觉得自己没那个能力,会误导别人。但是最近特别想听听别人的意见,所以就下定决心开始写博客。废话不说,赶快开波。
前言
用过Toolbar的都知道标题是在左边的,但通常UI都要求我们把标题居中。没用过的童鞋可以看看泡网的一篇文章android:ToolBar详解(手把手教程)。我并不想自己写一个布局来充当Toolbar,因为那样会增加不少工作量。但怎样才能把Toolbar的标题居中?
有问题先google。如果你还在百度的话,我也没什么办法了。谷歌后找到这样一种方法。在原来的Toolbar里面加上一个TextView,标题居中的关键是第12行,将layout_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"> <TextView android:id="@+id/toolbar_title" style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"/> </android.support.v7.widget.Toolbar>
接着再来个helper类。很简单的一个类,看看init方法就可以过了。
public class ToolbarHelper { private TextView mTitleTextView; private Toolbar mToolbar; public void init(AppCompatActivity activity, Toolbar toolbar, TextView titleTextView) { if (activity == null) { return; } mTitleTextView = titleTextView; mToolbar = toolbar; activity.setSupportActionBar(toolbar); // titleTextView不为null才设置actionbar不显示Title if (titleTextView != null) { ActionBar actionBar = activity.getSupportActionBar(); if (actionBar != null) { // 不显示title和subTitle actionBar.setDisplayShowTitleEnabled(false); } } } public void setTitle(@StringRes int resid) { if (mTitleTextView != null) { mTitleTextView.setText(resid); } } public void setTitle(CharSequence title) { if (mTitleTextView != null) { mTitleTextView.setText(title); } } public void setTitleTextColor(@ColorInt int color) { if (mTitleTextView != null) { mTitleTextView.setTextColor(color); } } public Toolbar getToolbar() { return mToolbar; } public TextView getTitleTextView() { return mTitleTextView; }}
然后在Activity中,最好是BaseActivity,创建一个ToolbarHelper
对象。在初始化View的时候,调用toolbarHelper的init()方法。
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);TextView titleView = (TextView) findViewById(R.id.toolbar_title);mToolbarHelper.init(this, toolbar, titleView);
接下来才是重点,重写onTitleChanged方法
@Override protected void onTitleChanged(CharSequence title, int color) { super.onTitleChanged(title, color); if (mToolbarHelper != null) { mToolbarHelper.setTitle(title); } }
这样标题居中的Toolbar就搞定了。但有一点值得注意的是,不要调用toolbar自身的setTitle()方法。否则的话Toolbar自身的标题也会显示。
重点来了,CenterTitleToolbar
这样就满足了吗?不,上面这种方法太麻烦了。又要在xml里面加东西,又要改activity。能不能只改动Toolbar里面的代码,不需要动Toolbar以外的任何代码就能实现标题居中?
基于这个思路,我们要创建一个Toolbar的子类。使Toolbar的title居中有两种做法。
- 通过反射获取其
mTitleTextView
属性,并修改其LayoutParams的gravity属性 - 重写toolbar的setTitle方法,自己维护一个titleTextView,并将其居中显示。
这里我选择第二种。因为第一种使用了反射,且mTitleTextView
是通过懒加载形式创建的,要考虑好反射获取的时机。OK,想好了就开工了。
先来看看Toolbar源码里的setTitle()方法
public void setTitle(CharSequence title) { if (!TextUtils.isEmpty(title)) { if (mTitleTextView == null) { final Context context = getContext(); mTitleTextView = new TextView(context); mTitleTextView.setSingleLine(); mTitleTextView.setEllipsize(TextUtils.TruncateAt.END); if (mTitleTextAppearance != 0) { mTitleTextView.setTextAppearance(context, mTitleTextAppearance); } if (mTitleTextColor != 0) { mTitleTextView.setTextColor(mTitleTextColor); } } if (!isChildOrHidden(mTitleTextView)) { addSystemView(mTitleTextView, true); } } else if (mTitleTextView != null && isChildOrHidden(mTitleTextView)) { removeView(mTitleTextView); mHiddenViews.remove(mTitleTextView); } if (mTitleTextView != null) { mTitleTextView.setText(title); } mTitleText = title; }
看到第3-14行就知道我刚刚为什么说mTitleTextView
是通过懒加载来创建了吧。其他都看懂了,isChildOrHidden,addSystemView这两个方法做了什么?继续看源码。
// 判断该view的父View是否为Toolbar private boolean isChildOrHidden(View child) { return child.getParent() == this || mHiddenViews.contains(child); } // 创建LayoutParams对象,并添加到Toolbar private void addSystemView(View v, boolean allowHide) { 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; } lp.mViewType = LayoutParams.SYSTEM; if (allowHide && mExpandedActionView != null) { v.setLayoutParams(lp); mHiddenViews.add(v); } else { addView(v, lp); } }
这两个方法中都有mHiddenViews
,这个对于我们的需求没什么用,忽略就好了。不必每句都看懂,我们知道它大概做了什么即可。
OK,开始写我们的CenterTitleToolbar。先继承Toolbar,声明和Title相关的属性
private TextView mTitleTextView; private CharSequence mTitleText; private int mTitleTextColor; private int mTitleTextAppearance;
重写setTitle()方法。
@Override public void setTitle(CharSequence title) { if (!TextUtils.isEmpty(title)) { if (mTitleTextView == null) { // 懒加载 final Context context = getContext(); mTitleTextView = new TextView(context); mTitleTextView.setSingleLine(); mTitleTextView.setEllipsize(TextUtils.TruncateAt.END); if (mTitleTextAppearance != 0) { mTitleTextView.setTextAppearance(context, mTitleTextAppearance); } if (mTitleTextColor != 0) { mTitleTextView.setTextColor(mTitleTextColor); } } if (mTitleTextView.getParent() != this) { // 添加到Toolbar并居中显示 addCenterView(mTitleTextView); } } else if (mTitleTextView != null && mTitleTextView.getParent() == this) { // 当title为空时,remove removeView(mTitleTextView); } if (mTitleTextView != null) { mTitleTextView.setText(title); } mTitleText = title; }
依照原来的思路稍微的修改。代码和原来的雷同,改动的地方就只有16,18,20和22行。关键是addCenterView这个方法。标题居中就看这里了。
private void addCenterView(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; } lp.gravity = Gravity.CENTER; addView(v, lp); }
该方法与Toolbar的addSystemView()方法雷同,我基本都是直接拷过来改要改的地方,去掉了一些无用的代码。看到第12行,没错,我们前面做了那么多,就为了将gravity设置为center。
细心的童鞋会发现,setTitle()方法里还有mTitleTextAppearance 和 mTitleTextColor
需要获取。没错,要想获取这两个值,我们需要重写setTitleTextAppearance()和setTitleTextColor()方法,只不过是将原来Toolbar的代码拷过来,这里就不说了。除此之外,还需要在构建方法中自己获取一次。
final TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs, R.styleable.Toolbar, defStyleAttr, 0); try { final int titleTextAppearance = a.getResourceId(R.styleable.Toolbar_titleTextAppearance, 0); if (titleTextAppearance != 0) { setTitleTextAppearance(context, titleTextAppearance); } if (a.hasValue(R.styleable.Toolbar_titleTextColor)) { setTitleTextColor(a.getColor(R.styleable.Toolbar_titleTextColor, 0xffffffff)); } } finally { a.recycle(); }
这里解释下为什么已经重写了setTitleTextAppearance()和setTitleTextColor()方法还需要在构造方法中获取这两个值。因为Toolbar的源码获取TextAppearance并没有调用setTitleTextAppearance()方法,导致我们自己的mTitleTextAppearance
和Toolbar的不一致。还要注意下调用那两个方法的顺序。
最后
有什么错漏的麻烦指出。感谢大家。
源码地址,喜欢的Star一下:
https://github.com/benioZhang/CenterTitleToolbar
参考:
http://blog.hwangjr.com/2015/07/10/Android-ToolBar-Widget-Usage/
- Android标题居中的Toolbar
- Android设置Toolbar的标题居中
- Android设置Toolbar的标题居中
- 【Android开发】Toolbar与标题居中
- ToolBar标题文字居中的方法
- Toolbar 标题居中
- toolbar标题居中
- 设置toolbar标题居中
- Toolbar设置标题居中
- toolbar标题设置居中
- Android自学之路,ToolBar的使用标题居中颜色设置
- Android-Toolbar标题居中与字体大小和颜色
- Toolbar标题居中怎么设置
- Android Toolbar标题居中和自定义字体(toolbar是和drawerlayout联动情况下)
- Android toolbar的标题设置无效
- Android 标题 居中
- android标题居中
- Android 标题 居中
- const,static,extern简介
- Chapter_one
- 《北风那个吹》观后
- 版本更新
- ZOOKEEPER解惑
- Android标题居中的Toolbar
- C库函数手册
- Spring Boot开发Web应用
- Apache多端口配置
- 0202.EBS-2TEC1701.WebADI开发技术总结(2/6)
- 教女友学编程-4-从打星星到面向对象
- jquery源码学习笔记1
- 走过的2016
- 敏捷其实很简单(12)Scrum中的计划会议