Kotlin Select Multiple Images From Gallery And Show In GridView Android

kotlin sqlite multiple tables, kotlin recyclerview checkbox, kotlin recyclerview button, kotlin load html javascript, kotlin recyclerview searchview, kotlin recyclerview search using edittext, kotlin listview with edittext, kotlin recyclerview with edittext, kotlin swipe to delete listview, kotlin recyclerview swipe to delete, kotlin expandablelistview with checkbox, kotlin custom ratingbar, kotlin change tab, Kotlin Select Multiple Images From Gallery, Kotlin Custom Dialog With Image And Title, kotlin select multiple video

Kotlin Select Multiple Images From Gallery And Show In GridView Android Example.

Let us make an app which enables the user to select multiple images from the gallery of his android device.

After taking or selecting the multiple images, we will set them into the grid view.

First of all, see the following output material.

 

Step 1. Important Layout

Make a new project in the android studio and select Kotlin as the primary source language.

Now you will have one activity as the main one. For it’s layout file which is activity_main.xml , you should write the following code

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
              tools:context=".MainActivity">

    <GridView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:id="@+id/gv"
            android:numColumns="3"
            android:layout_weight="1">
    </GridView>

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn"
            android:text="Select Multiple Images"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
    />

</LinearLayout>

This file will create the main screen of our app. It has one grid view and one button.

Grid view will cover the most of the screen while button is located at the bottom of the screen.

Step 2. Kotlin Lines For Main

Write down the below lines in MainActivity.kt file.

import android.annotation.SuppressLint
import android.app.Activity
import android.content.ClipData
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.provider.MediaStore
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.GridView
import android.widget.Toast
import java.util.ArrayList

class MainActivity : AppCompatActivity() {

    private var btn: Button? = null
    internal var PICK_IMAGE_MULTIPLE = 1
    internal lateinit var imageEncoded: String
    internal lateinit var imagesEncodedList: MutableList<String>
    private var gvGallery: GridView? = null
    private var galleryAdapter: GalleryAdapter? = null

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

        btn = findViewById(R.id.btn)
        gvGallery = findViewById(R.id.gv) as GridView

        btn!!.setOnClickListener {
            val intent = Intent()
            intent.type = "image/*"
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
            intent.action = Intent.ACTION_GET_CONTENT
            startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_MULTIPLE)
        }

    }

    @SuppressLint("NewApi")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        try {
            // When an Image is picked
            if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == Activity.RESULT_OK
                && null != data
            ) {
                // Get the Image from data

                val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
                imagesEncodedList = ArrayList()
                if (data.data != null) {

                    val mImageUri = data.data

                    // Get the cursor
                    val cursor = contentResolver.query(
                        mImageUri!!,
                        filePathColumn, null, null, null
                    )
                    // Move to first row
                    cursor!!.moveToFirst()

                    val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                    imageEncoded = cursor.getString(columnIndex)
                    cursor.close()

                    val mArrayUri = ArrayList<Uri>()
                    mArrayUri.add(mImageUri)
                    galleryAdapter = GalleryAdapter(applicationContext, mArrayUri)
                    gvGallery!!.adapter = galleryAdapter
                    gvGallery!!.verticalSpacing = gvGallery!!.horizontalSpacing
                    val mlp = gvGallery!!
                        .layoutParams as ViewGroup.MarginLayoutParams
                    mlp.setMargins(0, gvGallery!!.horizontalSpacing, 0, 0)

                } else {
                    if (data.clipData != null) {
                        val mClipData = data.clipData
                        val mArrayUri = ArrayList<Uri>()
                        for (i in 0 until mClipData!!.itemCount) {

                            val item = mClipData.getItemAt(i)
                            val uri = item.uri
                            mArrayUri.add(uri)
                            // Get the cursor
                            val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
                            // Move to first row
                            cursor!!.moveToFirst()

                            val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                            imageEncoded = cursor.getString(columnIndex)
                            imagesEncodedList.add(imageEncoded)
                            cursor.close()

                            galleryAdapter = GalleryAdapter(applicationContext, mArrayUri)
                            gvGallery!!.adapter = galleryAdapter
                            gvGallery!!.verticalSpacing = gvGallery!!.horizontalSpacing
                            val mlp = gvGallery!!
                                .layoutParams as ViewGroup.MarginLayoutParams
                            mlp.setMargins(0, gvGallery!!.horizontalSpacing, 0, 0)

                        }
                        Log.v("LOG_TAG", "Selected Images" + mArrayUri.size)
                    }
                }
            } else {
                Toast.makeText(
                    this, "You haven't picked Image",
                    Toast.LENGTH_LONG
                ).show()
            }
        } catch (e: Exception) {
            Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
                .show()
        }

        super.onActivityResult(requestCode, resultCode, data)
    }
}

Deep Reading

Let us see what Main activity file is telling to the compiler.

First of all, see the following

  private var btn: Button? = null
    internal var PICK_IMAGE_MULTIPLE = 1
    internal lateinit var imageEncoded: String
    internal lateinit var imagesEncodedList: MutableList<String>
    private var gvGallery: GridView? = null
    private var galleryAdapter: GalleryAdapter? = null

First line is making the object of the button class. Then second line will make one variable whose value is 1.

Then compiler will create one string variable. After this, it will create one Mutable list variable.

Finally, compiler will make the object of the Grid View class and of Gallery adapter.

When the user clicks the button, compiler will run the following lines

  btn!!.setOnClickListener {
            val intent = Intent()
            intent.type = "image/*"
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
            intent.action = Intent.ACTION_GET_CONTENT
            startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_MULTIPLE)
        }

Compiler will create one intent and will set it’s type as an image. Then it will enable the intent to allow the user to select multiple images.

Finally, it will start the intent. Starting of the intent will make a new screen and it will show all the gallery images.

From here, user needs to select single or multiple images.

When the user is finished with selection of the images, compiler will execute the onActivityResult() method.

Below is the code lines for onActivityResult() method.

@SuppressLint("NewApi")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        try {
            // When an Image is picked
            if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == Activity.RESULT_OK
                && null != data
            ) {
                // Get the Image from data

                val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
                imagesEncodedList = ArrayList()
                if (data.data != null) {

                    val mImageUri = data.data

                    // Get the cursor
                    val cursor = contentResolver.query(
                        mImageUri!!,
                        filePathColumn, null, null, null
                    )
                    // Move to first row
                    cursor!!.moveToFirst()

                    val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                    imageEncoded = cursor.getString(columnIndex)
                    cursor.close()

                    val mArrayUri = ArrayList<Uri>()
                    mArrayUri.add(mImageUri)
                    galleryAdapter = GalleryAdapter(applicationContext, mArrayUri)
                    gvGallery!!.adapter = galleryAdapter
                    gvGallery!!.verticalSpacing = gvGallery!!.horizontalSpacing
                    val mlp = gvGallery!!
                        .layoutParams as ViewGroup.MarginLayoutParams
                    mlp.setMargins(0, gvGallery!!.horizontalSpacing, 0, 0)

                } else {
                    if (data.clipData != null) {
                        val mClipData = data.clipData
                        val mArrayUri = ArrayList<Uri>()
                        for (i in 0 until mClipData!!.itemCount) {

                            val item = mClipData.getItemAt(i)
                            val uri = item.uri
                            mArrayUri.add(uri)
                            // Get the cursor
                            val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
                            // Move to first row
                            cursor!!.moveToFirst()

                            val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                            imageEncoded = cursor.getString(columnIndex)
                            imagesEncodedList.add(imageEncoded)
                            cursor.close()

                            galleryAdapter = GalleryAdapter(applicationContext, mArrayUri)
                            gvGallery!!.adapter = galleryAdapter
                            gvGallery!!.verticalSpacing = gvGallery!!.horizontalSpacing
                            val mlp = gvGallery!!
                                .layoutParams as ViewGroup.MarginLayoutParams
                            mlp.setMargins(0, gvGallery!!.horizontalSpacing, 0, 0)

                        }
                        Log.v("LOG_TAG", "Selected Images" + mArrayUri.size)
                    }
                }
            } else {
                Toast.makeText(
                    this, "You haven't picked Image",
                    Toast.LENGTH_LONG
                ).show()
            }
        } catch (e: Exception) {
            Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
                .show()
        }

        super.onActivityResult(requestCode, resultCode, data)
    }

This code has the main logic of the example. There is one if() condition in this onActivityResult() method.

For Single Image

When the user have selected only one image, if() condition is true and compiler will run the following

 if (data.data != null) {

                    val mImageUri = data.data

                    // Get the cursor
                    val cursor = contentResolver.query(
                        mImageUri!!,
                        filePathColumn, null, null, null
                    )
                    // Move to first row
                    cursor!!.moveToFirst()

                    val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                    imageEncoded = cursor.getString(columnIndex)
                    cursor.close()

                    val mArrayUri = ArrayList<Uri>()
                    mArrayUri.add(mImageUri)
                    galleryAdapter = GalleryAdapter(applicationContext, mArrayUri)
                    gvGallery!!.adapter = galleryAdapter
                    gvGallery!!.verticalSpacing = gvGallery!!.horizontalSpacing
                    val mlp = gvGallery!!
                        .layoutParams as ViewGroup.MarginLayoutParams
                    mlp.setMargins(0, gvGallery!!.horizontalSpacing, 0, 0)

                }

In this, compiler will first get the URI from the data. Then there is one cursor. This cursor will fill the arraylist with the image URIs.

Then it will bind this arraylist to the adapter object. After this, compiler will attach the adapter to the Grid view.

When the user have selected multiple images, compiler will run the following

else {
                    if (data.clipData != null) {
                        val mClipData = data.clipData
                        val mArrayUri = ArrayList<Uri>()
                        for (i in 0 until mClipData!!.itemCount) {

                            val item = mClipData.getItemAt(i)
                            val uri = item.uri
                            mArrayUri.add(uri)
                            // Get the cursor
                            val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
                            // Move to first row
                            cursor!!.moveToFirst()

                            val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                            imageEncoded = cursor.getString(columnIndex)
                            imagesEncodedList.add(imageEncoded)
                            cursor.close()

                            galleryAdapter = GalleryAdapter(applicationContext, mArrayUri)
                            gvGallery!!.adapter = galleryAdapter
                            gvGallery!!.verticalSpacing = gvGallery!!.horizontalSpacing
                            val mlp = gvGallery!!
                                .layoutParams as ViewGroup.MarginLayoutParams
                            mlp.setMargins(0, gvGallery!!.horizontalSpacing, 0, 0)

                        }
                        Log.v("LOG_TAG", "Selected Images" + mArrayUri.size)
                    }
                }

Here, compiler will also do the same thing as for single image, retrieving image URIs.

Because there are multiple images, compiler will run one for loop and then it will collect all the URIs.

Then after it will attach the adapter to the grid view.

Step 3. Making Grid View

Make a new resource XML file in app->res->layout directory. You should give this file a name like gv_item.xml

Below are the source lines for gv_item.xml file.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:layout_height="130dp"
        android:layout_width="130dp"
        android:padding="10dp"
        android:id="@+id/ivGallery"
        android:src="@mipmap/ic_launcher_round"
        android:scaleType="fitXY"
        />

</LinearLayout>


This file will make the look and feel for every cell of the grid view.

There is one image view in this file so every cell will have one image view in grid view.

Now make a new Kotlin file with the name like GalleryAdapter.kt

Below is the source snippet for GalleryAdapter.kt file.

import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import java.util.ArrayList

class GalleryAdapter(private val ctxs: Context, internal var mArrayUris: ArrayList<Uri>) : BaseAdapter() {

    private var pos: Int = 0
    private var inflater: LayoutInflater? = null
    private var ivGallery: ImageView? = null
    lateinit var ctx: Context
    lateinit var mArrayUri:  ArrayList<Uri>

    init {
        mArrayUri = mArrayUris
        ctx = ctxs
    }

    override fun getCount(): Int {
        return mArrayUri.size
    }

    override fun getItem(position: Int): Any {
        return mArrayUri[position]
    }

    override fun getItemId(position: Int): Long {
        return 0
    }

    @SuppressLint("ViewHolder")
    override fun getView(position: Int, p1: View?, parent: ViewGroup?): View? {

        pos = position
        inflater = ctx
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

        val itemView: View? =  this.inflater!!.inflate(R.layout.gv_item, parent, false)

        ivGallery = itemView?.findViewById(R.id.ivGallery) as ImageView

        ivGallery!!.setImageURI(mArrayUri[position])

        return itemView
    }
}

First of all, compiler will create the objects of LayoutInflater and ImageView class.

Inside the init() method, compiler will initialize the context and arraylist of URIs object.

Following is the code for getView() method.

  @SuppressLint("ViewHolder")
    override fun getView(position: Int, p1: View?, parent: ViewGroup?): View? {

        pos = position
        inflater = ctx
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

        val itemView: View? =  this.inflater!!.inflate(R.layout.gv_item, parent, false)

        ivGallery = itemView?.findViewById(R.id.ivGallery) as ImageView

        ivGallery!!.setImageURI(mArrayUri[position])

        return itemView
    }

Compiler will first inflate the layout file gv_item.xml

Then it will find the imageView using it’s ID. Then it will set the image preview in the image view.

Download Kotlin Select Multiple Images From Gallery

https://github.com/demonuts/Kotlin-Select-Multiple-Images-From-Gallery-And-Show-In-GridView-Android