Android自定義多圖片介面卡(根據圖片的個數展示不同的佈局)
阿新 • • 發佈:2020-11-06
一、概述&效果圖
專案上有一個需求根據不同的圖片個數展示不同的的佈局樣式,且圖片個數不能超過四個。要說起來手動寫也挺方便的,就是程式碼看起來比較臃腫,考慮了兩秒決定用自定義佈局試實現
思路:
1.讓佈局繼承ViewGroup
2.利用ViewGroup測量自己以及測量子View的寬高
3.根據寬高在layout方法中進行手動佈局
廢話不多說,大家可以看下效果圖
二、原始碼(主要部分)
測量自己和測量子View
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec)//測量子View measureChildren(widthMeasureSpec, heightMeasureSpec) //獲取ziView的數量 val childCount = childCount if (childCount > 4) { //如果元素超過四個就丟擲異常 throw IndexOutOfBoundsException("元素數量不能超過四個") } val widthMode = MeasureSpec.getMode(widthMeasureSpec) val width= MeasureSpec.getSize(widthMeasureSpec) val heightMode = MeasureSpec.getMode(heightMeasureSpec) val height = MeasureSpec.getSize(heightMeasureSpec) //佈局必須是固定寬高的,如果不是就丟擲異常 if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) { throw RuntimeException("主佈局必須指定寬高") } //指定佈局寬高範圍 setMeasuredDimension(width, height) //以下預設佈局都是有固定寬高的 for (index in 0 until childCount) { when (childCount) { //當只有一個子元素的時候,佈局的寬高就是子元素的寬高 1 -> { val childView = getChildAt(index) val params = ViewGroup.LayoutParams(width, height) childView.layoutParams = params } 2 -> { for (index in 0 until 2) { val childView = getChildAt(index) val params = ViewGroup.LayoutParams((width - margin) / 2, height) childView.layoutParams = params } } 3 -> { for (index in 0 until 3) { val childView = getChildAt(index) var childWidth = 0 var childHeight = 0 if (index == 0) { childWidth = (width - margin) / 2 childHeight = height } else { childWidth = (width - margin) / 2 childHeight = (height - margin) / 2 } val params = ViewGroup.LayoutParams(childWidth, childHeight) childView.layoutParams = params } } 4 -> { for (index in 0 until 4) { val childView = getChildAt(index) val params = ViewGroup.LayoutParams((width - margin) / 2, (width - margin) / 2) childView.layoutParams = params } } } } }
佈局子View
/** * @description 開始佈局 * @date: 2020/11/6 16:20 * @author: wei.yang * @param * @return */ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { Log.e("margin:", margin.toString()) val childCount = childCount when (childCount) { 1 -> { val childView = getChildAt(0) childView.layout(0, 0, childView.measuredWidth, childView.measuredHeight) } 2 -> { val childView1 = getChildAt(0) val childWidth = childView1.measuredWidth childView1.layout(0, 0, childWidth, childView1.measuredHeight) val childView2 = getChildAt(1) childView2.layout( childWidth + margin, 0, childWidth * 2 + margin, childView2.measuredHeight ) } 3 -> { val childView1 = getChildAt(0) val childWidth = childView1.measuredWidth childView1.layout(0, 0, childWidth, childView1.measuredHeight) val childView2 = getChildAt(1) childView2.layout( childWidth + margin, 0, childWidth * 2 + margin, childView2.measuredHeight ) val childView3 = getChildAt(2) childView3.layout( childWidth + margin, childWidth + margin, childWidth * 2 + margin, childView3.measuredHeight * 2 + margin ) } 4 -> { Log.e("CustomerMusdfj", "佈局了四個") val childView = getChildAt(0) val childWidth = childView.measuredWidth val childHeight = childView.measuredHeight childView.layout(0, 0, childWidth, childHeight) getChildAt(1).layout(childWidth + margin, 0, childWidth * 2 + margin, childHeight) getChildAt(2).layout(0, childHeight + margin, childWidth, childHeight * 2 + margin) getChildAt(3).layout( childWidth + margin, childHeight + margin, childWidth * 2 + margin, childHeight * 2 + margin ) } } }
設定資料來源
/** * @description 設定圖片的資料來源 * @date: 2020/11/6 16:39 * @author: wei.yang * @param margin 單位是dp * @return */ fun setAdapter(views: ArrayList<View>, margin: Float) { removeAllViews() this.margin = dp2px(margin) views?.apply { this.forEach { addView(it) } } requestLayout() }
三、下載地址