Android自定义多图片适配器(根据图片的个数展示不同的布局)

一、概述&效果图

  项目上有一个需求根据不同的图片个数展示不同的的布局样式,且图片个数不能超过四个。要说起来手动写也挺方便的,就是代码看起来比较臃肿,考虑了两秒决定用自定义布局试实现

  思路:

  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

原文地址:https://www.cnblogs.com/tony-yang-flutter/p/13938278.html