基于原生Toolbar实现Title居中显示(代码量极少,易使用)

前言

在项目中经常会看到TitleBar是一个返回按钮+标题居中显示的设计页面,通常的做法如下:

 <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@android:color/white"
        app:navigationIcon="@drawable/ic_svg_back_ptc_24"
        >
           <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_gravity="center"
               android:singleLine="true"
               android:ellipsize="end"
               android:text="Documents"
               android:textSize="18sp"
               android:textColor="#ff333333"
               />

    </androidx.appcompat.widget.Toolbar>

其中返回按钮ic_svg_back_ptc_24对应的文件为:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="@dimen/dp_24"
    android:height="@dimen/dp_24"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="@android:color/black"
        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>
</vector>

这样做是可以实现效果,但是如果app中有大量这样的页面,我们就要在不同页面写很多这样重复的代码,有没有更简洁的方法呢?让我想想啊,Toolbar本身是带标题栏的,但标题栏不是居中显示的,原生Toolbar生成显示标题栏对应的代码如下:

   /**
     * Set the title of this toolbar.
     *
     * <p>A title should be used as the anchor for a section of content. It should
     * describe or name the content being viewed.</p>
     *
     * @param title Title to set
     */
    public void setTitle(CharSequence title) {
        if (!TextUtils.isEmpty(title)) {
            if (mTitleTextView == null) {
                final Context context = getContext();
                mTitleTextView = new AppCompatTextView(context);
                mTitleTextView.setSingleLine();
                mTitleTextView.setEllipsize(TextUtils.TruncateAt.END);
                if (mTitleTextAppearance != 0) {
                    mTitleTextView.setTextAppearance(context, mTitleTextAppearance);
                }
                if (mTitleTextColor != null) {
                    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;
    }

既然原生Toolbar不符合我们的要求,那我们就自定义一个Toolbar覆盖setTitle方法并在此方法里设置Title居中显示就好了,于是参考Toolbar源码,封装了一个Title居中显示的Toolbar ,完整代码如下:

import android.content.Context
import android.content.res.ColorStateList
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TextView
import androidx.annotation.NonNull
import androidx.annotation.StyleRes
import androidx.appcompat.R
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.Toolbar
import androidx.core.widget.TextViewCompat

/**
 * Title居中的Toolbar
 */
class CenterTitleToolbar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : Toolbar(context, attrs, defStyleAttr) {

    private var mTitleTextAppearance = 0
    private var mTitleTextColor: ColorStateList? = null
    private var mTitleTextView: TextView? = null
    private var mTitleText: CharSequence? = null

    init {

        val ta = getContext().obtainStyledAttributes(attrs, R.styleable.Toolbar, defStyleAttr, 0)
        mTitleTextAppearance = ta.getResourceId(R.styleable.Toolbar_titleTextAppearance, 0)
        mTitleText = ta.getText(R.styleable.Toolbar_title)
        if (!TextUtils.isEmpty(mTitleText)) {
            title = mTitleText
        }
        if (ta.hasValue(R.styleable.Toolbar_titleTextColor)) {
            setTitleTextColor(ta.getColorStateList(R.styleable.Toolbar_titleTextColor)!!)
        }
        ta.recycle()
    }

    override fun setTitle(title: CharSequence?) {
        if (!TextUtils.isEmpty(title)) {
            if (mTitleTextView == null) {
                mTitleTextView = AppCompatTextView(context).apply {
                    isSingleLine = true
                    ellipsize = TextUtils.TruncateAt.END
                    addView(this, LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER))
                }
            }
            if (mTitleTextAppearance != 0) {
                mTitleTextView?.apply {
                    TextViewCompat.setTextAppearance(this,mTitleTextAppearance)
                }
            }
            if (mTitleTextColor != null) {
                mTitleTextView?.setTextColor(mTitleTextColor)
            }
        }
        else if(mTitleTextView!=null){
            removeView(mTitleTextView)
        }
        mTitleTextView?.text = title
        mTitleText = title
    }

    override fun getTitle(): CharSequence? {
        return mTitleText
    }

    override fun setTitleTextColor(@NonNull color: ColorStateList) {
        mTitleTextColor = color
        mTitleTextView?.setTextColor(color)
    }

    override fun setTitleTextAppearance(context: Context, @StyleRes resId: Int) {
        mTitleTextAppearance = resId
        mTitleTextView?.apply {
            TextViewCompat.setTextAppearance(this,resId)
        }
    }
}

使用

  • 定义Toolbar Style
   <style name="TKToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">?attr/actionBarSize</item>
        <item name="android:background">@android:color/white</item>
        <item name="android:clickable">true</item>
        <item name="navigationIcon">@drawable/ic_svg_back_ptc_24</item>
        <item name="titleTextAppearance">@style/TKToolbarTitleAppearance</item>
    </style>
    <style name="TKToolbarTitleAppearance" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
        <item name="android:textSize">18sp</item>
        <item name="android:textColor">#ff333333</item>
    </style>
  • 在layout文件中引用CenterTitleToolbar
 <CenterTitleToolbar
        style="@style/TKToolbarStyle"
        app:title="Documents"
        />

显示效果如下:


Toolbar.png

总结

我们通过继承原生Toolbar,并覆盖setTitle方法,优雅简单的实现了一个Title居中显示的CenterTitleToolbar ,该类可复用简化大量模版代码,同时又继承了原生Toolbar所有的特性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容