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.
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