前言
实际项目开发中,每个界面对应的头部导航栏样式都大差不差,如果通过布局文件include
的方式添加显示,当需求改动时,就不是很方便,那我们能不能打造一套通用的导航栏,通过代码来进行约束实现呢?
具体实现
定义导航栏接口规范
interface INavigation {
/**
* 绑定布局ID
*/
fun bindLayoutId(): Int
/**
* 给View设置参数
*/
fun <T : AbsNavigationBar.Builder> applyView(builder: T)
}
定义导航栏抽象类
abstract class AbsNavigationBar(private val builder: Builder) : INavigation {
private var view: View? = null
init {
//创建和绑定布局
view = LayoutInflater.from(builder.context).inflate(bindLayoutId(), builder.parent, false)
builder.parent.addView(view, 0)
applyView(builder)
}
fun getString(id: Int): String {
return builder.context.getString(id)
}
fun getColor(id: Int): Int {
return ContextCompat.getColor(builder.context, id)
}
fun setText(vid: Int, text: CharSequence) {
val tv = findViewById<TextView>(vid)
if (tv.visibility != View.VISIBLE) {
tv.visibility = View.VISIBLE
}
tv.text = text
}
fun setImageResource(vid: Int, resId: Int) {
val imageView = findViewById<ImageView>(vid)
if (imageView.visibility != View.VISIBLE) {
imageView.visibility = View.VISIBLE
}
imageView.setImageResource(resId)
}
fun setOnClickListener(vid: Int, listener: View.OnClickListener?) {
val view = findViewById<View>(vid)
if (view.visibility != View.VISIBLE) {
view.visibility = View.VISIBLE
}
view.setOnClickListener(listener)
}
private fun <T : View> findViewById(id: Int): T {
return view!!.findViewById(id)
}
/**
* 构建导航栏
*/
abstract class Builder(val context: Context, val parent: ViewGroup) {
/**
* 构建导航栏方法
*/
abstract fun build(): AbsNavigationBar
}
}
打造通用的NavigationBar
class CommonNavigationBar private constructor(builder: Builder) : AbsNavigationBar(builder) {
/**
* 绑定布局
*/
override fun bindLayoutId(): Int {
return R.layout.common_navigation_bar
}
/**
* 绑定资源
*/
override fun <T : AbsNavigationBar.Builder> applyView(builder: T) {
val result = builder as Builder
setText(R.id.tv_title, result.title)
setText(R.id.tv_left, result.leftTitle)
setText(R.id.tv_right, result.rightTitle)
setOnClickListener(R.id.tv_right,result.rightOnClickListener)
}
class Builder(context: Context, parent: ViewGroup) : AbsNavigationBar.Builder(context,parent) {
//中间标题
var title: String = ""
//左边图片
var leftIcon: Int = 0
//右边图片
var rightIcon: Int = 0
//左边文字
var leftTitle: String = ""
//右边文字
var rightTitle: String = ""
//整体背景颜色
var bgColor: Int = 0
//左侧点击事件
var leftOnClickListener: OnClickListener? = null
//右侧点击事件
var rightOnClickListener: OnClickListener? = null
fun setTitle(title: String): Builder {
this.title = title
return this
}
fun setLeftTitle(leftTitle: String): Builder {
this.leftTitle = leftTitle
return this
}
fun setRightTitle(rightTitle: String): Builder {
this.rightTitle = rightTitle
return this
}
fun setLeftIcon(leftIcon: Int): Builder {
this.leftIcon = leftIcon
return this
}
fun setRightIcon(rightIcon: Int): Builder {
this.rightIcon = rightIcon
return this
}
fun setBgColor(bgColor: Int): Builder {
this.bgColor = bgColor
return this
}
fun setLeftOnClickListener(leftOnClickListener: OnClickListener): Builder {
this.leftOnClickListener = leftOnClickListener
return this
}
fun setRightOnClickListener(rightOnClickListener: OnClickListener): Builder {
this.rightOnClickListener = rightOnClickListener
return this
}
override fun build(): CommonNavigationBar {
return CommonNavigationBar(this)
}
}
}
实践使用
CommonNavigationBar.Builder(this, findViewById(android.R.id.content))
.setTitle("This is Title")
.setRightTitle("Right Title")
.setRightOnClickListener {
Toast.makeText(this@MainActivity, "Click Right", Toast.LENGTH_LONG).show()
}
.build()
小结
通过使用Builder
建造者模式,我们将复杂对象的建造过程和它的表示进行分离,对于本文中的导航栏构建就十分适用。
结语
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )