Android自定義ViewGroup多行多列效果
本文實例為大傢分享瞭Android自定義ViewGroup多行多列的具體代碼,供大傢參考,具體內容如下
先看下效果圖
每行兩個子孩子
每行一個子孩子
實現思路
自定義viewGroup,實現測量和佈局,使控件適應業務場景。
測量
根據父控件的寬度,平均分給每個子孩子固定的寬度。高度就是行數乘以一個子孩子的高度,再加上空隙的高度。
根據子孩子個數計算行數
val rows = if (childCount % perLineChild == 0) { childCount / perLineChild } else { childCount / perLineChild + 1 }
代碼示例
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val width = MeasureSpec.getSize(widthMeasureSpec) for (i in 0 until childCount) { val child: View = getChildAt(i) if (child.visibility != GONE) { val lp = child.layoutParams val childWidthMeasureSpec = getChildMeasureSpec( widthMeasureSpec, 0, (width - (perLineChild - 1) * space) / perLineChild ) val childHeightMeasureSpec = getChildMeasureSpec( heightMeasureSpec, 0, lp.height ) child.measure(childWidthMeasureSpec, childHeightMeasureSpec) } } val rows = if (childCount % perLineChild == 0) { childCount / perLineChild } else { childCount / perLineChild + 1 } if (childCount > 0) { setMeasuredDimension( width, getChildAt(0).measuredHeight * rows + (rows - 1) * space ) } }
佈局
需要註意擺放的順序和位置,每行擺放固定的個數,達到個數之後換行繼續擺放
代碼示例
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { var left = l var top = t children.forEachIndexed { index, view -> if (index % perLineChild == 0) { left = 0 if (index != 0) { top += view.measuredHeight top+=space } view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight) } else { view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight) } left += view.measuredWidth left += space } }
完整代碼
class MultiLineViewG @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : ViewGroup(context, attrs, defStyleAttr) { var perLineChild = 2 /** * 子孩子之間的空隙 */ var space = 10 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val width = MeasureSpec.getSize(widthMeasureSpec) for (i in 0 until childCount) { val child: View = getChildAt(i) if (child.visibility != GONE) { val lp = child.layoutParams val childWidthMeasureSpec = getChildMeasureSpec( widthMeasureSpec, 0, (width - (perLineChild - 1) * space) / perLineChild ) val childHeightMeasureSpec = getChildMeasureSpec( heightMeasureSpec, 0, lp.height ) child.measure(childWidthMeasureSpec, childHeightMeasureSpec) } } val rows = if (childCount % perLineChild == 0) { childCount / perLineChild } else { childCount / perLineChild + 1 } if (childCount > 0) { setMeasuredDimension( width, getChildAt(0).measuredHeight * rows + (rows - 1) * space ) } } override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { var left = l var top = t children.forEachIndexed { index, view -> if (index % perLineChild == 0) { left = 0 if (index != 0) { top += view.measuredHeight top+=space } view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight) } else { view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight) } left += view.measuredWidth left += space } } }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Android自定義View原理(實戰)
- Android 深入探究自定義view之流式佈局FlowLayout的使用
- Android中FlowLayout組件實現瀑佈流效果
- JavaSwing基礎之Layout佈局相關知識詳解
- Android實現無限循環滾動