• 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

  • 相关阅读:
    inndo 表与存储逻辑_1
    msyql master thread
    redo log重做日志缓冲
    redo log 重做日志
    Latex 写算法伪代码
    Just for test
    ASP.NET Web API 2 OData v4教程
    MVC系统过滤器 OutputCacheAttribute
    MVC系统过滤器、自定义过滤器
    .NET如何从配置文件中获取连接字符串
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/13938278.html
Copyright © 2020-2023  润新知