中介者模式下的Android底部導航欄

Mediator Pattern: 中介者模式, 用一箇中介對象來封裝一系列的其他對象的交互,使各個對象不需要顯示的相互調用,使其耦合鬆散,降低多個對象類之間的通信複雜性。

詳細流程以後補充, 有點忙,
代碼上傳了 代碼

非常好理解,從字面意思中就能明白什麼是中介者模式,那麼對於Android底部導航欄有很多種實現方式,爲什麼還需要自己去設計呢?並且是使用中介者模式,典型的簡單功能複雜化,是這樣嗎?

答案肯定是不。

從入行程序開發開始,就或聽或寫各種開發模式,開發模式能提升開發效率,擴展性、易維護等等,也從側面明白了提升代碼質量的方式之一就是多在業務邏輯中使用開發模式,熟練之後代碼的質量自然高很多。

一 中介者模式下的Android底部導航欄

目標: 使用中介者模式實現Android底部導航欄

對於一般的具有底部導航欄的產品都可以用 底部導航欄 + ViewPager + Fragment 實現,我的思路是將ViewPager 和自定義的底部導航欄使用中介者模式完成他們的交互,在邏輯代碼中簡單的實現改功能,

NavLayoutMediator(mainVp,mainNav,object :NavLayoutMediator.OnConfigureNavCallback{
            override fun onConfigureNav(nav: NavLayout.Nav, position: Int) {
            }
            //設置底部導航欄的數據
            override fun navData(): MutableList<NavLayout.Nav> {
                val list = arrayListOf<NavLayout.Nav>()
                list.add(NavLayout.Nav(R.drawable.selector_nav_picture,"圖片", true))
                list.add(NavLayout.Nav(R.drawable.selector_nav_picture,"視頻", true))
                list.add(NavLayout.Nav(R.drawable.selector_nav_picture,"音樂", true))
                list.add(NavLayout.Nav(R.drawable.selector_nav_picture,"我的", false))
                return list
            }
        }).attach()

只需要在主頁面 調用NavLayoutMediator 傳入底部導航欄和ViewPager即可, 大大減少主頁面中的邏輯代碼

<-- 配置顏色等操作 -->
<com.sunnyweather.android.widget.NavLayout
            android:id="@+id/mainNav"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            app:navBackground="#fff5f5f5"
            app:layout_constraintBottom_toBottomOf="parent">
        </com.sunnyweather.android.widget.NavLayout>

1.1 底部導航欄 – NavLayout

自定義ConstraintLayout View,使用RecyclerView 完成底部導航欄的部署

class NavLayout : ConstraintLayout {
    private var mList = arrayListOf<Nav>()
    private var adapter: NavLayoutAdapter = NavLayoutAdapter(mList)
    private var onNavSelectedListener: OnNavSelectedListener? = null
    private var navBackground = Color.WHITE
    private var normalColor = Color.BLACK
    private var selectColor = Color.BLUE

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        val ta = context?.obtainStyledAttributes(attrs, R.styleable.NavLayout)
      //...
        ta?.recycle()
    }

    init {
        /**
         * 可以是使用recyclerView 回調position ,利用position 更新adapter
         */
        val view = LayoutInflater.from(context).inflate(R.layout.nav_layout, this)
        val navRV = view.findViewById<RecyclerView>(R.id.navRV)
        initRv(navRV)
        bindEvent()
    }

    private fun bindEvent() {
        adapter.setOnItemClickListener { adapter, view, position ->
           // 回調點擊事件
        }
    }

    fun registerOnNavSelectedListener(onNavSelectedListener: OnNavSelectedListener) {
        this.onNavSelectedListener = onNavSelectedListener
    }

    fun unRegisterOnNavSelectedListener() {
        this.onNavSelectedListener = null
    }

    fun bindToViewPager(position: Int) {
        this.mList.size
        for (i in 0 until this.mList.size) {
            this.mList[i].isSelect = position == i
        }
        adapter.notifyDataSetChanged()
    }

    fun addData(navList: MutableList<Nav>) {
        this.mList.clear()
        this.mList.addAll(navList)
        adapter.notifyDataSetChanged()
    }

    private fun initRv(navRV: RecyclerView?) {
        checkNotNull(navRV) { "RecyclerView is null" }
        navRV.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
        navRV.adapter = adapter
    }

    interface OnNavSelectedListener {
        fun onNavSelected(position: Int)
    }

    inner class NavLayoutAdapter(data: MutableList<Nav>) :
        BaseQuickAdapter<Nav, BaseViewHolder>(R.layout.nav_item, data) {
        override fun convert(holder: BaseViewHolder, item: Nav) {
            //....
        }


    }
	/*
	* 底部按鈕實體
	*/
    class Nav(
        val icon: Int,
        val text: String,
        var isSelect: Boolean
    )
}

詳細流程以後補充, 有點忙,
代碼上傳了 代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章