HOW TO COMBINE MULTIPLE IMAGES TO A SINGLE IMAGE IN ANDROID

In this post we are going to learn how to display multiple images like facebook.

Let's start

Step 1: Create Android Application with Kotlin Enable

Step 2: Create Custom MultiIimageView class and add below code

package com.rrtutors.multiimageview

import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide
import java.util.ArrayList

class MultiImageView<T> : ViewGroup{
    private var mContext: Context? = null
    private var mGap: Int = 0//Spacing
    private var mSingleImgSize: Int = 0//Image Size
    private var mMaxSize = 3//Max Images
    private val mImageViewList = ArrayList<ImageView>()
    private var mImgDataList: List<Any>? = null
    private var mImageSize: Int = 0//Total Images
    private var mRowCount: Int = 0//No Of Rows
    private var mColumnCount: Int = 0//No Of Columns
    private var textView: TextView? = null

  
    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init(context,attrs)
    }


        private fun init(context: Context, attrs: AttributeSet?) {
        this.mContext = context

        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ThreeImageView)
        this.mGap = typedArray.getDimension(R.styleable.ThreeImageView_imgGap, 0f).toInt()
        this.mSingleImgSize = typedArray.getDimensionPixelSize(R.styleable.ThreeImageView_singleImgSize, -1)
        this.mMaxSize = typedArray.getInteger(R.styleable.ThreeImageView_maxSize, 3)
        typedArray.recycle()
    }

    private fun layoutChildrenView() {
        if (mImgDataList == null) return
        val showChildrenCount = getNeedShowCount(mImgDataList!!.size)
        layoutMaxCountChildrenView(showChildrenCount)
    }

    protected override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        layoutChildrenView()
    }

    protected override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val width = View.MeasureSpec.getSize(widthMeasureSpec)

        var height = View.MeasureSpec.getSize(heightMeasureSpec)

        val totalWidth = width - getPaddingLeft() - getPaddingRight()
        if (mImgDataList != null && mImgDataList!!.size > 0) {

            if (mImgDataList!!.size == 1 && mSingleImgSize != -1) {

                mImageSize = if (mSingleImgSize > totalWidth) totalWidth else mSingleImgSize
            } else {

                mImageSize = (totalWidth - mGap * (mColumnCount - 1)) / mColumnCount
            }

            height = mImageSize * mRowCount + mGap * (mRowCount - 1) + getPaddingTop() + getPaddingBottom()
        }

        setMeasuredDimension(width, height)
    }


    private fun layoutMaxCountChildrenView(childrenCount: Int) {
        var left = 0
        var top = 0
        var right = 0
        var bottom = 0
        for (i in 0 until childrenCount) {
            val childrenView = getChildAt(i) as ImageView
            childrenView.scaleType = ImageView.ScaleType.CENTER_CROP
            childrenView.setBackgroundResource(R.drawable.shape)
            left = getPaddingLeft() + i % 3 * mImageSize + i % 3 * mGap
            top = getPaddingTop() + i / 3 * mImageSize + i / 3 * mGap
            right = left + mImageSize
            bottom = top + mImageSize
            childrenView.layout(left, top, right, bottom)
            childrenView.setPadding(2,2,2,2)
            mContext?.let { Glide.with(it).load(mImgDataList?.get(i)).into(childrenView) };
        }
        showImageAndText(left, top, right, bottom)
    }

    private fun showImageAndText(left: Int, top: Int, right: Int, bottom: Int) {

        if (mImgDataList!!.size > mMaxSize) {
            if (textView != null) {
                textView!!.bringToFront()


                val k=(mImgDataList!!.size)

                val text = "+ " +( k.minus(mMaxSize)) + ""
                val textSize = px2sp(mContext!!, (mImageSize / 6).toFloat())
                textView!!.textSize = textSize.toFloat()
                textView!!.text = text


                textView!!.setTextColor(Color.WHITE)
                textView!!.setBackgroundColor(-0x80000000)


                val fontMetricsInt = textView!!.paint.fontMetricsInt
                val textHeight = fontMetricsInt.bottom - fontMetricsInt.top
                val paddingTop = (mImageSize - textHeight) / 2

                textView!!.setPadding(0, paddingTop, 0, paddingTop)
                textView!!.gravity = Gravity.CENTER



                textView!!.layout(left, top, right, bottom)


            }
        }
    }

    /**
     *
     *
     * @param size
     * @return
     */
    private fun getNeedShowCount(size: Int): Int {

        return if (mMaxSize > 0 && size > mMaxSize) {
            mMaxSize
        } else {

            size
        }
    }

    /**
     *
     *
     * @param list
     */
    fun setImagesData(list: List<Any>?) {
        mImgDataList = list
        removeAllViews()
        if (list == null || list.size == 0) {

            this.setVisibility(View.GONE)
        } else {

            this.setVisibility(View.VISIBLE)
        }

        val showCount = getNeedShowCount(list!!.size)

        val params = calculateParam(showCount)
        mRowCount = params[0]
        mColumnCount = params[1]
        for (i in 0 until showCount) {
            val iv = getImageView(i) ?: return
            addView(iv, generateDefaultLayoutParams())
            if (i == mMaxSize - 1 && list.size > mMaxSize) {
                textView = TextView(mContext)
                addView(textView, generateDefaultLayoutParams())
            }
        }
        requestLayout()
    }

    protected fun calculateParam(imageSize: Int): IntArray {
        val params = IntArray(2)
        params[0] = imageSize / 3 + if (imageSize % 3 == 0) 0 else 1
        params[1] = 3
        return params
    }

    private fun getImageView(position: Int): ImageView? {
        if (position < mImageViewList.size) {
            return mImageViewList[position]
        } else {
            val imageView = ImageView(mContext)
            mImageViewList.add(imageView)
            return imageView
        }
    }

    fun setGap(gap: Int) {
        this.mGap = gap
    }

    fun getGap(): Int {
        return mGap
    }

    /**
     *
     *
     * @param singleImgSize
     */
    fun setSingleImgSize(singleImgSize: Int) {
        mSingleImgSize = singleImgSize
    }

    /**
     *
     *
     * @param maxSize 
     */
    fun setMaxSize(maxSize: Int) {
        mMaxSize = maxSize
    }

    private fun px2sp(context: Context, pxValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (pxValue / fontScale + 0.5f).toInt()
    }
}

Step 3: Add resourses

attrs.xml file

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ThreeImageView">
        <attr name="singleImgSize" format="dimension"/>
        <attr name="imgGap" format="dimension"/>
        <attr name="maxSize" format="integer"/>
    </declare-styleable>
</resources>

Step 4: Update activity_main.xml file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="https://schemas.android.com/apk/res/android"
        xmlns:tools="https://schemas.android.com/tools"
        xmlns:app="https://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#FAFAFA"
        tools:context=".MainActivity">

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:textColor="#F30556"
              android:layout_margin="16dp"
              android:text="List oF imgaes Like Facebook"
    />

    <com.rrtutors.multiimageview.MultiImageView
            android:id="@+id/image_three"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:imgGap="10dp"
            app:maxSize="3"
            android:layout_gravity="center"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            app:singleImgSize="50dp"
            android:paddingBottom="10dp"
            tools:ignore="MissingConstraints"/>

</LinearLayout>

 

Step 5: Update MainActivity file

package com.rrtutors.multiimageview

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.ComponentActivity
import androidx.core.app.ComponentActivity.ExtraData
import androidx.core.content.ContextCompat.getSystemService
import android.icu.lang.UCharacter.GraphemeClusterBreak.T
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mList:ArrayList<Int>?=  ArrayList<Int>()

        mList?.add(R.drawable.images)
        mList?.add(R.drawable.images)
        mList?.add(R.drawable.images)
        mList?.add(R.drawable.images)
        mList?.add(R.drawable.images)
        mList?.add(R.drawable.images)
        mList?.add(R.drawable.images)
        image_three.setImagesData(mList)
    }
}

 

Step 6: Run Application

How to combine multiple Images to a single Image in android

 

How to combine multiple Images to a single Image in android


Subscribe For Daily Updates