本篇文章主要記錄昨天學(xué)習(xí)的組合布局實現(xiàn)底部導(dǎo)航欄的效果
顯示效果:
image.png
主要知識點結(jié)構(gòu):
- 如何添加子控件到指定的布局容器
- 如何實現(xiàn)布局界面之間的交互
那么如何添加子控件到指定的布局容器呢酬荞?
/**
* 知識點:
* 當(dāng)繼承于系統(tǒng)自帶的layout時 已經(jīng)規(guī)定好了規(guī)則
* 只關(guān)心如何添加自己的子控件進去
* 在哪里添加子控件?
* 創(chuàng)建的時候添加
* */
如何實現(xiàn)布局界面之間的交互
/**
這里可以通過子控件的點擊事件回調(diào)來實現(xiàn)
* */
下面我們開始具體實現(xiàn)如上效果,大致流程如下
- 首先導(dǎo)入我們需要的項目資源到
drawable
或mipmap
包下 - 然后實現(xiàn)單個控件的顯示和點按功能
- 最后組合多個控件實現(xiàn)自己想要的效果
導(dǎo)入項目資源就不提了,我們首先先實現(xiàn)單個控件的顯示和點按功能
BarItem.Kotlin
類
class BarItem: LinearLayout {
//正常狀態(tài)的icon資源
var normalIcon:Int = 0
//選中狀態(tài)的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值 轉(zhuǎn) px值
private fun dp2px(dp:Int) = (context.resources.displayMetrics.density * dp).toInt()
}
在這里,我們在布局創(chuàng)建的時候添加子控件,也就是initView()
方法在構(gòu)造方法里使用,然后聲明了對應(yīng)的屬性边坤,mIsSelected
屬性用于判斷是否選中,當(dāng)出現(xiàn)點擊事件時谅年,它的值設(shè)置為true
茧痒,這里我們設(shè)置了updateUI方法,用于更改對應(yīng)顯示的樣式融蹂,這里沒有設(shè)置屬性私有化的目的是便于外部設(shè)置對應(yīng)的屬性值旺订,我們使用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
下面我們組合實現(xiàn)底部導(dǎo)航欄
BarItem
里聲明的回調(diào)方法
//回調(diào)
var callBack:((p:Int)->Unit)? = null
在點擊事件中回調(diào)我們想要的position值
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN){
if (!mIsSelected) {
mIsSelected = true
callBack?.let {
it(position)
}
}
}
return true
}