Kotlin ListView Button Android Tutorial With Example Click Listener

kotlin recyclerview, kotlin listview checkbox, kotlin listview button

Android Kotlin ListView Button Tutorial With Example is covered in this article.

In this example, we will make a listview with button and textview in every child row of the listview.

You will learn how to manage clicklistener for every button.

There are some common problems like,

  • You have clicked the button of first row but it affects last row.
  • When you scroll down through the listview, click effect is gone

In this tutorial, we will solve above problems.
After following all the steps, you should have following output for kotlin listview button example

There are two buttons and one textview in every row of the listview. Textview will represent the counter(an integer number).

We will update the counter with two buttons – plus and minus.

Before you start

Make sure you are familiar with the model method to implement listview.

If you do not know about model structure for listview then read how to make model in listview example with kotlin.

When you need to put checkbox in listview then visit kotlin listview with checkbox tutorial.

Step 1. Model Class

Open a new class with name Model.kt

Source code for this class contains following lines.

/**
 * Created by hardik on 9/1/17.
 */
class Model {

    var number: Int = 0
    var fruit: String? = null

    fun getNumbers(): Int {
        return number
    }

    fun setNumbers(number: Int) {
        this.number = number
    }

    fun getFruits(): String {
        return fruit.toString()
    }

    fun setFruits(fruit: String) {
        this.fruit = fruit
    }

}

We will create various objects of model class and will set them in one arraylist.

This arraylist will give the data like name of the fruit and the quantity of the fruits for each row of listview.

Step 2. Creating row layout file

We need to create one layout resource file, which will represent the each row layout of the listview.

Make a file and give it a name lv_item.xml

Add below code in it.

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

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="20dp">


        <TextView
            android:id="@+id/animal"
            android:layout_width="130dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="animal"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="#000"
            android:textSize="20sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/number"
            android:layout_marginLeft="20dp"
            android:text="1"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="#000" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/plus"
            android:layout_marginLeft="20dp"
            android:text="Plus"
            android:textColor="#000" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/minus"
            android:text="Minus"
            android:textColor="#000" />
    </LinearLayout>
</LinearLayout>

Step 3: Integer Resource File

Now make one integer resource file named integer.xml

This file includes constant integer values with specific key names.

To create integer.xml file, right click on values folder -> New -> Value resource file

listview with button android integer, kotlin listview button
How to create integer.xml

Following is the source code for this file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
     <integer name="btn_plus_view">1</integer>
     <integer name="btn_plus_pos">2</integer>
     <integer name="btn_minus_view">3</integer>
     <integer name="btn_minus_pos">4</integer>
</resources>

Here, btn_plus_view, btn_plus_pos etc. are the keys and 1,2 are the values for their keys.

Step 4. Preparing Custom Adapter

Custom Adapter will send data to th listview about button names and textview’s value in string format.

Open a fresh new class with name CustomAdapter.kt

Source code should look like following

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.Button
import android.widget.TextView


/**
 * Created by hardik on 9/1/17.
 */
class CustomAdapter(private val context: Context) : BaseAdapter() {



    override fun getViewTypeCount(): Int {
        return count
    }

    override fun getItemViewType(position: Int): Int {

        return position
    }

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

    override fun getItem(position: Int): Any {
        return MainActivity.modelArrayList.get(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.lv_item, null, true)


            holder.tvFruit = convertView!!.findViewById(R.id.animal) as TextView
            holder.tvnumber = convertView.findViewById(R.id.number) as TextView
            holder.btn_plus = convertView.findViewById(R.id.plus) as Button
            holder.btn_minus = convertView.findViewById(R.id.minus) as Button

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

        holder.tvFruit!!.setText(MainActivity.modelArrayList.get(position).getFruits())
        holder.tvnumber!!.setText(MainActivity.modelArrayList.get(position).getNumbers().toString())

        holder.btn_plus!!.setTag(R.integer.btn_plus_view, convertView)
        holder.btn_plus!!.setTag(R.integer.btn_plus_pos, position)
        holder.btn_plus!!.setOnClickListener {
            val tempview = holder.btn_plus!!.getTag(R.integer.btn_plus_view) as View
            val tv = tempview.findViewById(R.id.number) as TextView
            val pos = holder.btn_plus!!.getTag(R.integer.btn_plus_pos) as Int

            val number = Integer.parseInt(tv.text.toString()) + 1
            tv.text = number.toString()

            MainActivity.modelArrayList.get(pos).setNumbers(number)
        }

        holder.btn_minus!!.setTag(R.integer.btn_minus_view, convertView)
        holder.btn_minus!!.setTag(R.integer.btn_minus_pos, position)
        holder.btn_minus!!.setOnClickListener {
            val tempview = holder.btn_minus!!.getTag(R.integer.btn_minus_view) as View
            val tv = tempview.findViewById(R.id.number) as TextView
            val pos = holder.btn_minus!!.getTag(R.integer.btn_minus_pos) as Int

            val number = Integer.parseInt(tv.text.toString()) - 1
            tv.text = number.toString()

            MainActivity.modelArrayList.get(pos).setNumbers(number)
        }

        return convertView
    }

    private inner class ViewHolder {

        var btn_plus: Button? = null
        var btn_minus: Button? = null
        var tvFruit: TextView? = null
        internal var tvnumber: TextView? = null

    }

}

For updating counter with plus and minus button clicks, we need to capture button of which row is clicked.

For this purpose, we will set tags to each button in every row of listview. Then we will retrieve position of clicked by getting those tags.

This is the main logic of this whole tutorial.

For setting tags, setTag() method is used and getTag() method will give access to clicked button.

Consider following code lines

 holder.btn_minus!!.setTag(R.integer.btn_minus_view, convertView)
 holder.btn_minus!!.setTag(R.integer.btn_minus_pos, position)

With every minus button, view and position are tagged with unique key.

Now following code will get this tag.

 val tempview = holder.btn_minus!!.getTag(R.integer.btn_minus_view) as View
            val tv = tempview.findViewById(R.id.number) as TextView
            val pos = holder.btn_minus!!.getTag(R.integer.btn_minus_pos) as Int

            val number = Integer.parseInt(tv.text.toString()) - 1
            tv.text = number.toString()

            MainActivity.modelArrayList.get(pos).setNumbers(number)

As you can see, first of all we will get view of whole row layout and we store it in the tempview variable.

Then, with the help of tempview, we will get the textview and will update it’s value.

We need to update the quantity of fruits with plus and minus button click. This is done by following line

MainActivity.modelArrayList.get(pos).setNumbers(number)

Here, modelArrayList is defined in the Main Activity and it’s access is defines as public, so we can use it in any class of whole application.

Step 5. Next Activity To Send Data

Prepare a new activity named NextActivity.

We will send data to this next activity.

It will generate two file : NextActivity.kt and activity_next.xml

Put below code into the NextActivity.kt

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class NextActivity : AppCompatActivity() {

    private var tv: TextView? = null

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

        tv = findViewById(R.id.tv) as TextView

        for (i in 0..4) {
            val text = tv!!.text.toString()
            tv!!.text = text + MainActivity.modelArrayList.get(i).getFruits() + " -> " + MainActivity.modelArrayList.get(i).getNumbers() + "\n"
        }
    }
}

Now add following into the activity_next.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#000"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="20dp"/>

</RelativeLayout>

Step 6. Changing Main Activity

There are some necessary changes needed to be done in MainActivity.kt class.

Replace your existing source code with below one.

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.ListView
import java.util.ArrayList

class MainActivity : AppCompatActivity() {

    private var lv: ListView? = null
    private var customAdapter: CustomAdapter? = null
    private var btnnext: Button? = null
    private val fruitlist = arrayOf("Apples", "Oranges", "Potatoes", "Tomatoes", "Grapes")

    private val model: ArrayList<Model>
        get() {
            val list = ArrayList<Model>()
            for (i in 0..4) {

                val model = Model()
                model.setNumbers(1)
                model.setFruits(fruitlist[i])
                list.add(model)
            }
            return list
        }

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

        lv = findViewById(R.id.lv) as ListView
        btnnext = findViewById(R.id.next) as Button

        modelArrayList = model
        customAdapter = CustomAdapter(this)
        lv!!.adapter = customAdapter

        btnnext!!.setOnClickListener {
            val intent = Intent(this@MainActivity, NextActivity::class.java)
            startActivity(intent)
        }
    }

    companion object {
        lateinit var modelArrayList: ArrayList<Model>
    }
}

Now change your activity_main.xml file’s code with below

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

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/lv"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:id="@+id/next"
            android:text="Next Activity"/>
    </LinearLayout>
</LinearLayout>

So it was all the details about making kotlin listview button in android studio.

If you have any queries then comment it out, We will respond you quickly.

Do not forget to share DemoNut’s resources in your social media.

Download the Source code for Kotlin ListView Button Tutorial

[sociallocker]Download Kotlin ListView With Button[/sociallocker]