一、概述&效果图
项目上有一个需求根据不同的图片个数展示不同的的布局样式,且图片个数不能超过四个。要说起来手动写也挺方便的,就是代码看起来比较臃肿,考虑了两秒决定用自定义布局试实现
思路:
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