本篇文章主要记录昨天学习的组合布局实现底部导航栏的效果
显示效果:
image.png
主要知识点结构:
- 如何添加子控件到指定的布局容器
- 如何实现布局界面之间的交互
那么如何添加子控件到指定的布局容器呢?
/**
* 知识点:
* 当继承于系统自带的layout时 已经规定好了规则
* 只关心如何添加自己的子控件进去
* 在哪里添加子控件?
* 创建的时候添加
* */
如何实现布局界面之间的交互
/**
这里可以通过子控件的点击事件回调来实现
* */
下面我们开始具体实现如上效果,大致流程如下
- 首先导入我们需要的项目资源到
drawable
或mipmap
包下 - 然后实现单个控件的显示和点按功能
- 最后组合多个控件实现自己想要的效果
导入项目资源就不提了,我们首先先实现单个控件的显示和点按功能
BarItem.Kotlin
类
class BarItem: LinearLayout {
//正常状态的icon资源
var normalIcon:Int = 0
//选中状态的icon资源
var selectIcon:Int = 0
//显示标题
var text:String = ""
set(value) {
field = value
titleTextView?.text = value
}
//字体颜色
var textColor:Int = 0
//是否选中
var mIsSelected:Boolean = false
set(value) {
field = value
updateUI()
}
//更新UI
private fun updateUI() {
if (mIsSelected){
iconImageView?.setBackgroundResource(selectIcon)
titleTextView?.setTextColor(textColor)
}else{
iconImageView?.setBackgroundResource(normalIcon)
titleTextView?.setTextColor(Color.BLACK)
}
}
private var iconImageView:ImageView? = null
private var titleTextView:TextView? = null
constructor(context: Context):super(context){
initView()
}
constructor(context: Context,attrs:AttributeSet?):super(context, attrs){
initView()
initAttr(context, attrs)
}
//提取自定义属性
private fun initAttr(context: Context,attrs:AttributeSet?){
val array = context.obtainStyledAttributes(attrs,R.styleable.BarItem)
normalIcon = array.getResourceId(R.styleable.BarItem_normalIcon,R.mipmap.home)
selectIcon = array.getResourceId(R.styleable.BarItem_selectIcon,R.mipmap.home_selected)
text = array.getString(R.styleable.BarItem_text).toString()
textColor = array.getInteger(R.styleable.BarItem_textColor, Color.RED)
mIsSelected = array.getBoolean(R.styleable.BarItem_selected,false)
array.recycle()
}
//布局子控件
private fun initView(){
//横向布局
orientation = VERTICAL
//居中对齐
gravity = Gravity.CENTER
iconImageView = ImageView(context).also {
val lp = LayoutParams(dp2px(32),dp2px(32))
addView(it,lp)
}
titleTextView = TextView(context).also {
val lp = LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)
addView(it,lp)
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (!mIsSelected){
mIsSelected = true
}
return true
}
//dp值 转 px值
private fun dp2px(dp:Int) = (context.resources.displayMetrics.density * dp).toInt()
}
在这里,我们在布局创建的时候添加子控件,也就是initView()
方法在构造方法里使用,然后声明了对应的属性,mIsSelected
属性用于判断是否选中,当出现点击事件时,它的值设置为true
,这里我们设置了updateUI方法,用于更改对应显示的样式,这里没有设置属性私有化的目的是便于外部设置对应的属性值,我们使用xml布局显示下效果
activity_main.xml
布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<me.jrl.demo1.BarItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:normalIcon="@mipmap/home"
app:selectIcon="@mipmap/home_selected"
app:text="主页"
app:textColor="@android:color/holo_red_light"
app:selected="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
显示效果
image.png
下面我们组合实现底部导航栏
BarItem
里声明的回调方法
//回调
var callBack:((p:Int)->Unit)? = null
在点击事件中回调我们想要的position值
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN){
if (!mIsSelected) {
mIsSelected = true
callBack?.let {
it(position)
}
}
}
return true
}
网友评论