Kotlin Swipe To Delete ListView Android Example Like Gmail

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

Read on Kotlin Swipe To Delete ListView Android Example Like Gmail Example.

In this example, you will learn how to implement swipe to delete feature for listview using kotlin in android app.

Gmail android app has this feature and it creates an unique user experience.

When the user swipes right or left to delete, system will pop up an Undo button, if user clicks this button system will not delete the row.

First of all, see the below output youtube video.

 

Step 1. New Project With Gradle

Make a new project in android studio with empty activity. Select Kotlin as the primary source language.

Now in your build.gradle(Module:app) file, add the following code line

implementation 'com.hudomju:swipe-to-dismiss-undo:1.0'

This line is referencing this github library.

Using the above line, compiler will import the necessary classes of this library into the our android studio project.

We will be able to use coding of this library directly in our project with the help of gradle changes.

Step 2. Changing Colors

Go to app->res->values directory and open colors.xml file.

Add the below lines in this colors.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="gray_background">#757575</color>
    <color name="yellow">#FFBB33</color>
</resources>

Step 3. Adding Images

Navigate to app->res->drawable folder and add the following images in it.

Click me to download images.

Step 4. Model For Swipe and XML file

Make a new Kotlin class and give it a name like SwipeModel.kt

SwipeModel.kt file should have the below coding lines

class SwipeModel {

    var name: String? = null
    var image_drawable: Int = 0

    fun getImage_drawables(): Int {
        return image_drawable
    }

    fun setImage_drawables(image_drawable: Int) {
        this.image_drawable = image_drawable
    }


    fun getNames(): String {
        return name.toString()
    }

    fun setNames(name: String) {
        this.name = name
    }

}

This file have two variables : one is string and another is integer. String variable is representing the name of the vehicle while integer variable will give us idea about the image of the vehicle.

Our all vehicle images are in the drawable folder so we can reference them using integer value.

Now go to app->res->layout folder and make a new XML file which should have the name as list_item.xml

Copy the following code lines in this list_item.xml file.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/lyt_container"
    android:background="@color/gray_background">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:background="@android:color/white">

        <TextView
            android:id="@+id/tv"
            android:layout_width="0dp"
            android:height="100dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            android:gravity="center_vertical"
            android:layout_weight="4" />

        <ImageView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:id="@+id/image"
            android:src="@mipmap/ic_launcher_round"
            android:layout_weight="2"
            android:paddingTop="10dp"
            android:paddingBottom="10dp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:visibility="gone"
        android:height="100dp"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:weightSum="3">

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:id="@+id/txt_delete"
            android:gravity="center_vertical"
            android:text="Deleted"
            android:clickable="false"
            android:layout_weight="2"
            android:hapticFeedbackEnabled="true"
            android:textColor="@android:color/white"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:gravity="center"
            android:id="@+id/txt_undo"
            android:text="Undo"
            android:clickable="false"
            android:layout_weight="1"
            android:textColor="@color/yellow"/>

    </LinearLayout>

</FrameLayout>

In total, there are two linear layouts are there in the above file.

First linear layout has one text view and one image view in it. This is the view that list view will inherit for all it’s rows before user has swipe left or right.

When the user swipes at left or right side, system will change the view of that particular row. At this time, system will use the second linear layout from the above code.

Second linear layout has two text views. One is for Deleted button and another is for Undo.

Step 5. Swipe Adapter File

Now let us write the adapter for the list view. Create a new Kotlin file with the name like SwipeAdapter.kt

You should write down the following lines in SwipeAdapter.kt

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.TextView
import java.util.ArrayList

/**
 * Created by Parsania Hardik on 03-Jan-17.
 */
class SwipeAdapter(private val context: Context, private val ModelArrayList: ArrayList<SwipeModel>) : BaseAdapter() {

    fun remove(position: Int) {
        ModelArrayList.removeAt(position)
        notifyDataSetChanged()
    }

    override fun getViewTypeCount(): Int {
        return count
    }

    override fun getItemViewType(position: Int): Int {

        return position
    }

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

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

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

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        var convertView = convertView
        val holder: ViewHolder

        if (convertView == null) {
            holder = ViewHolder()
            val inflater = context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = inflater.inflate(R.layout.list_item, null, true)

            holder.tvname = convertView!!.findViewById(R.id.tv) as TextView
            holder.iv = convertView.findViewById(R.id.image) as ImageView

            convertView.tag = holder
        } else {
            // the getTag returns the viewHolder object set as a tag to the view
            holder = convertView.tag as ViewHolder
        }

        holder.tvname!!.setText(ModelArrayList[position].getNames())
        holder.iv!!.setImageResource(ModelArrayList[position].getImage_drawables())

        return convertView
    }

    private inner class ViewHolder {

         var tvname: TextView? = null
         var iv: ImageView? = null

    }

}

Look at the getView() method. Compiler will first inherit the list_item.xml file. Then it will find the two UI widgets : text view and image view using their IDs.

Then it will set the image name in text view and image preview in the image view. For this, it will use ModelArrayList.

ModelArrayList is the arraylist with the objects of the SwipeModel class. Adapter is getting this arraylist inside it’s parameters.

Now see the below code

  fun remove(position: Int) {
        ModelArrayList.removeAt(position)
        notifyDataSetChanged()
    }

A remove() function is used to remove the row which is swiped by the user.

Compiler will first remove the object from the ModelArrayList and then it will refresh the list view using notifyDataSetChanged() method.

We will call this remove() function from the Main Activity.

Step 6. Writing Main Classes

In your activity_main.xml file, write down the below lines

<?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"
              tools:context=".MainActivity">

    <ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/listview"/>

</LinearLayout>

This file contains only one UI widget : List View.

Now below is the source snippet for MainActivity.kt file.

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AbsListView
import android.widget.AdapterView
import android.widget.ListView
import android.widget.Toast
import com.hudomju.swipe.SwipeToDismissTouchListener
import com.hudomju.swipe.adapter.ListViewAdapter
import java.util.ArrayList
import android.widget.Toast.LENGTH_SHORT

class MainActivity : AppCompatActivity() {

    private var lv: ListView? = null
    private var customAdapter: SwipeAdapter? = null
    private var modelArrayList: ArrayList<SwipeModel>? = null
    private val myImageList = intArrayOf(
        R.drawable.benz,
        R.drawable.bike,
        R.drawable.car,
        R.drawable.carrera,
        R.drawable.ferrari,
        R.drawable.harly,
        R.drawable.lamborghini,
        R.drawable.silver
    )
    private val myImageNameList = arrayOf("Benz", "Bike", "Car", "Carrera", "Ferrari", "Harly", "Lamborghini", "Silver")

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

        lv = findViewById(R.id.listview) as ListView
        modelArrayList = populateList()
        customAdapter = SwipeAdapter(this, modelArrayList!!)
        lv!!.adapter = customAdapter

        val touchListener = SwipeToDismissTouchListener(
            ListViewAdapter(lv),
            object : SwipeToDismissTouchListener.DismissCallbacks<ListViewAdapter> {
                override fun canDismiss(position: Int): Boolean {
                    return true
                }

                override fun onDismiss(view: ListViewAdapter, position: Int) {
                    customAdapter!!.remove(position)
                }
            })

        lv!!.setOnTouchListener(touchListener)
        lv!!.setOnScrollListener(touchListener.makeScrollListener() as AbsListView.OnScrollListener)
        lv!!.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
            if (touchListener.existPendingDismisses()) {
                touchListener.undoPendingDismiss()
            } else {
                Toast.makeText(this@MainActivity, "Position $position", LENGTH_SHORT).show()
            }
        }

    }

    private fun populateList(): ArrayList<SwipeModel> {

        val list = ArrayList<SwipeModel>()

        for (i in 0..7) {
            val model = SwipeModel()
            model.setNames(myImageNameList[i])
            model.setImage_drawables(myImageList[i])
            list.add(model)
        }

        return list
    }
}

First of all, see the following code

 private var lv: ListView? = null
    private var customAdapter: SwipeAdapter? = null
    private var modelArrayList: ArrayList<SwipeModel>? = null
    private val myImageList = intArrayOf(
        R.drawable.benz,
        R.drawable.bike,
        R.drawable.car,
        R.drawable.carrera,
        R.drawable.ferrari,
        R.drawable.harly,
        R.drawable.lamborghini,
        R.drawable.silver
    )
    private val myImageNameList = arrayOf("Benz", "Bike", "Car", "Carrera", "Ferrari", "Harly", "Lamborghini", "Silver")

Compiler will first create the objects of list view and swipe adapter classes.

Then it will make the arraylist with the objects of the SwipeModel class. Then there is another arraylist which have the integer references to the drawable images.

Finally, last line is the string arraylist which contains the names of the vehicles.

Now see the below

 modelArrayList = populateList()
        customAdapter = SwipeAdapter(this, modelArrayList!!)
        lv!!.adapter = customAdapter

Compiler will fill the data into modelArrayList using the populateList() method.

Then it will bind the adapter to the list view after initializing it.

Following is the code lines for populateList() method.

  private fun populateList(): ArrayList<SwipeModel> {

        val list = ArrayList<SwipeModel>()

        for (i in 0..7) {
            val model = SwipeModel()
            model.setNames(myImageNameList[i])
            model.setImage_drawables(myImageList[i])
            list.add(model)
        }

        return list
    }

Compiler will have one for loop. In every iteration of loop, it will create the object of the SwipeModel class. Then it will set the name and drawable image reference to that object.

After this, it will add the object to the array list.

Now focus on the below

   val touchListener = SwipeToDismissTouchListener(
            ListViewAdapter(lv),
            object : SwipeToDismissTouchListener.DismissCallbacks<ListViewAdapter> {
                override fun canDismiss(position: Int): Boolean {
                    return true
                }

                override fun onDismiss(view: ListViewAdapter, position: Int) {
                    customAdapter!!.remove(position)
                }
            })

When the user swipes left or right, compiler will call the onDismiss() method.

Here, it will execute remove() method which have already written in the Swipe Adapter class.

Download For Kotlin Swipe To Delete Listview

https://github.com/demonuts/Kotlin-Swipe-To-Delete-ListView-Android-Example-Like-Gmail