一、概述&效果圖
項目上有一個需求根據不同的圖片個數展示不同的的布局樣式,且圖片個數不能超過四個。要說起來手動寫也挺方便的,就是代碼看起來比較臃腫,考慮了兩秒決定用自定義布局試實現
思路:
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() }
三、使用方法
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initViews() } private fun initViews() { customMutiImageView.setAdapter(getDataViews(4), 0f) customMutiImageView2.setAdapter(getDataViews(4), 5f) customMutiImageViewOnLayout.setAdapter(getDataViews(1), 0f) customMutiImageViewTwoLayout.setAdapter(getDataViews(2), 5f) customMutiImageViewThreeLayout.setAdapter(getDataViews(3), 0f) customMutiOtherLayout.setAdapter(getCustomLayout(), 5f) } private fun getCustomLayout(): ArrayList<View> { val views = ArrayList<View>() for (index in 0 until 4) { val view = LayoutInflater.from(this).inflate(R.layout.item_mutillayout, null) val customView = view.findViewById<com.yw.custommutilimageadapter.widget.CustomMutiImageView>(R.id.customMutiImageLittle) customView.setAdapter(getDataViews(4), 0f) views.add(view) } return views } private fun getDataViews(size: Int): ArrayList<View> { val views = ArrayList<View>() val img1 = ImageView(this) img1.setImageResource(R.drawable.girl1) img1.scaleType = ImageView.ScaleType.CENTER_CROP val img2 = ImageView(this) img2.setImageResource(R.drawable.girl2) img2.scaleType = ImageView.ScaleType.CENTER_CROP val img3 = ImageView(this) img3.setImageResource(R.drawable.girl3) img3.scaleType = ImageView.ScaleType.CENTER_CROP val img4 = ImageView(this) img4.setImageResource(R.drawable.girl4) img4.scaleType = ImageView.ScaleType.CENTER_CROP when (size) { 1 -> { views.add(img4) } 2 -> { views.add(img3) views.add(img4) } 3 -> { views.add(img1) views.add(img2) views.add(img3) } 4 -> { views.add(img1) views.add(img2) views.add(img3) views.add(img4) } } return views } }
<?xml version="1.0" encoding="utf-8"?> <ScrollView 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"> <LinearLayout 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" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity"> <!-- 四張圖片不帶間距--> <com.yw.custommutilimageadapter.widget.CustomMutiImageView android:id="@+id/customMutiImageView" android:layout_width="200dp" android:layout_height="200dp" tools:ignore="MissingConstraints" /> <!-- 四張圖片帶間距--> <com.yw.custommutilimageadapter.widget.CustomMutiImageView android:id="@+id/customMutiImageView2" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="30dp" tools:ignore="MissingConstraints" /> <!-- 一張圖片--> <com.yw.custommutilimageadapter.widget.CustomMutiImageView android:id="@+id/customMutiImageViewOnLayout" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="30dp" tools:ignore="MissingConstraints" /> <!-- 兩張圖片--> <com.yw.custommutilimageadapter.widget.CustomMutiImageView android:id="@+id/customMutiImageViewTwoLayout" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="30dp" tools:ignore="MissingConstraints" /> <!-- 三張圖片--> <com.yw.custommutilimageadapter.widget.CustomMutiImageView android:id="@+id/customMutiImageViewThreeLayout" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="30dp" tools:ignore="MissingConstraints" /> <!--自定義填充其他布局--> <com.yw.custommutilimageadapter.widget.CustomMutiImageView android:id="@+id/customMutiOtherLayout" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="30dp" tools:ignore="MissingConstraints" /> </LinearLayout> </ScrollView>
如果要下載源代碼,請移步GitHub