构建安卓项目通用TitleBar

前言

每个项目的每个页面基本都会写头布局,但如果每个布局都写一遍头布局的话未免太过于麻烦,所以想着直接写一个吧。

第一种 include

一般这种情况首先想到的肯定是写好布局,然后直接用到的地方include即可。那就来吧!首先看下效果吧:

构建安卓项目通用TitleBar_第1张图片

一般布局的头部可以分为三个模块,左中右,中间一般都是标题,所以直接放上TextView即可,左右有可能是文字也有可能是图片,所以两种都写上,上代码:


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_70"
    android:background="@color/colorAccent"
    android:orientation="vertical"
    android:paddingTop="@dimen/dp_20">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:ignore="UselessParent">

        <ImageView
            android:id="@+id/imgBack"
            android:layout_width="@dimen/dp_40"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:paddingTop="@dimen/dp_14"
            android:paddingBottom="@dimen/dp_14"
            android:src="@drawable/img_back" />

        <ImageView
            android:id="@+id/imgRight"
            android:layout_width="@dimen/dp_40"
            android:layout_height="match_parent"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:paddingTop="@dimen/dp_14"
            android:paddingBottom="@dimen/dp_14"
            android:visibility="gone" />

        <TextView
            android:id="@+id/txtTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="玩安卓"
            android:textColor="@color/white"
            android:textSize="@dimen/sp_18" />

        <TextView
            android:id="@+id/txtRight"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:gravity="center"
            android:paddingEnd="@dimen/dp_7"
            android:paddingStart="@dimen/dp_7"
            android:paddingTop="@dimen/dp_14"
            android:paddingBottom="@dimen/dp_14"
            android:textColor="@color/white"
            android:textSize="@dimen/sp_16"
            android:visibility="gone"
            tools:ignore="RtlSymmetry" />

    RelativeLayout>

FrameLayout>

写好头布局之后,直接在需要的地方进行include即可:

<include
        layout="@layout/layout_title"/>

如果需要进行修改标题名称或者添加点击事件的话直接进行添加即可。

第二种 自定义View

其实直接include也是可以的,但是千万要记住,程序猿这个物种是非常懒的,能坐着绝对不站着、能躺着绝对不坐着。。。。

所以。。。就连那几行代码都不想写,那就自定义个View吧,因为标题栏的操作一般只有设置标题、返回按钮和确定按钮,所以咱们还可以把设置标题和返回操作直接做好,就不需要每个页面再去写了。

第一步

好了,说干就干,自定义View的第一步是干啥啊?对,创建View 啊!

class TitleBar @JvmOverloads constructor(
    private val mContext: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : RelativeLayout(mContext, attrs, defStyleAttr), View.OnClickListener {}

第二步

上面咱们已经定义好了布局,这里就可以直接进行使用了,直接将布局加载进来进行使用就行:

    init {
        initView()
    }

    /**
     * 初始化布局
     */
    private fun initView() {
        //加载布局
        View.inflate(mContext, R.layout.layout_title, this)

        //控制头布局,返回关闭页面
        mImgBack = findViewById(R.id.imgBack)
        //控制标题
        mTitleTv = findViewById(R.id.txtTitle)
        //右边图片
        mImgRight = findViewById(R.id.imgRight)
        //右边文字
        mTxtRight = findViewById(R.id.txtRight)
        mImgBack.setOnClickListener(this)
    }

第三步

好了,这基本已经完成了。很简单吧?但是需要的操作咱们还没干呢,上面说过,咱们需要给一个设置标题的接口:

    /**
     * 设置标题栏标题
     *
     * @param title 标题
     */
    fun setTitle(title: String?) {
        mTitleTv.text = title
    }

标题已经设置好了,接下来就是关闭页面:

    override fun onClick(v: View) {
        if (v.id == R.id.imgBack) {
            //关闭页面
            if (KeyboardUtils.isSoftInputVisible(mContext as Activity)) KeyboardUtils.hideSoftInput(this)
            mContext.finish()
        }
    }

这里除了关闭页面之外还加了一个操作:关闭输入法弹出框。

第四步

除了这些还要再预留一些接口,比如右边文字的设置以及点击操作、右边按钮的设置以及点击操作等等:

    /**
     * 设置返回按钮图片
     *
     * @param imageId 图片id
     */
    fun setBackImage(imageId: Int) {
        if (imageId != 0) {
            mImgBack.setImageResource(imageId)
        }
    }

    /**
     * 设置返回按钮图片是否显示
     *
     * @param imageVisiable 是否显示
     */
    fun setBackImageVisiable(imageVisiable: Boolean) {
        if (imageVisiable) {
            mImgBack.visibility = View.VISIBLE
        } else {
            mImgBack.visibility = View.GONE
        }
    }

    /**
     * 设置右边图片
     *
     * @param imageId 图片id
     */
    fun setRightImage(imageId: Int) {
        if (imageId != 0) {
            require(mTxtRight.visibility != View.VISIBLE) { "文字和图片不可同时设置" }
            mImgRight.visibility = View.VISIBLE
            mImgRight.setImageResource(imageId)
        }
    }

    /**
     * 设置右边文字
     *
     * @param text 文字
     */
    fun setRightText(text: String?) {
        if (text != null) {
            require(mImgRight.visibility != View.VISIBLE) { "文字和图片不可同时设置" }
            mTxtRight.visibility = View.VISIBLE
            mTxtRight.text = text
        }
    }

    /**
     * 设置右边文字背景
     *
     * @param color 颜色
     */
    fun setRightBackColor(color: Int) {
        mTxtRight.setBackgroundColor(color)
    }

    /**
     * 设置右边文字禁止点击
     *
     * @param click 是否可以点击
     */
    fun setRightTextClick(click: Boolean) {
        mTxtRight.isClickable = click
    }
    
    fun setRightTextOnClickListener(onClickListener: OnClickListener) {
        mTxtRight.setOnClickListener(onClickListener)
    }

    fun setRightImgOnClickListener(onClickListener: OnClickListener) {
        mImgRight.setOnClickListener(onClickListener)
    }

使用

好了,写的差不多了,看看如何使用吧?

在需要使用的地方写上布局:

    <com.zj.core.util.TitleBar
        android:id="@+id/articleListTitleBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

然后在页面中直接进行需要的操作即可,例如重新设置下标题,并且需要展示返回按钮:

articleListTitleBar.setTitle(keyword)
articleListTitleBar.setBackImageVisiable(true)

是不是很简单呢?

继续优化

刚才说了,程序猿都非常懒,即使封装成这样也是不行的,每个类都需要去代码中设置,直接在布局中写好不得了。。。

好,那就在布局中写好吧。。。。

首先需要在res->values中创建一个attrs.xml文件:


<resources>
resources>

创建完成之后大概是这样的,然后加入咱们需要设置的操作:标题和返回按钮是否显示:

    <declare-styleable name="TitleBar">
        <attr name="titleName" format="string" />
        <attr name="backImageVisiable" format="boolean" />
    declare-styleable>

好了,这就完事了,下面在自定义View中找到进行使用即可:

		private var titleName: String? = null
    private var backImageVisiable: Boolean? = null

    init {
        val attr = context.obtainStyledAttributes(attrs, R.styleable.TitleBar)
        titleName = attr.getString(R.styleable.TitleBar_titleName)
        backImageVisiable = attr.getBoolean(R.styleable.TitleBar_backImageVisiable,true)
    }

上面代码很简单,找到标题的文字和是否显示返回按钮的参数,因为有可能为空,所以初始值定为了null。下面在initView方法中进行判断使用:

				if (titleName != null) {
            mTitleTv.text = titleName
        }
        if (backImageVisiable !=null){
            setBackImageVisiable(backImageVisiable!!)
        }

ok了,来试一下吧:

    <com.zj.core.util.TitleBar
        android:id="@+id/userTitleBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:titleName="关于我"
        app:backImageVisiable="true"/>

构建安卓项目通用TitleBar_第2张图片

好嘞,已经实现了咱们需要的基本功能了。

总结

本篇文章很简单,只是一个基本工具,大家可以在此之上多添加一些attrs中的值,多添加一些功能。

本文所有代码都在我写的一个MVVM的玩安卓的工具包中:https://github.com/zhujiang521/PlayAndroid/blob/master/core/src/main/java/com/zj/core/util/TitleBar.kt

文章中如果描述有误欢迎指出,不胜感激。

看完记得三连,感谢。

你可能感兴趣的:(安卓进阶之旅)