android kotlin - selectableItemBackground programmatically

MainActivity.kt

package com.example.jetpack

import android.app.Activity
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

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

        // make the text view clickable
        materialTextView.apply {
            isClickable = true
            isFocusable = true
        }
        applySelectableItemBackground(materialTextView)
    }
}


// extension function to apply selectable item background
fun Activity.applySelectableItemBackground(v:View){
    val typedValue = TypedValue()
    this.theme.resolveAttribute(
        android.R.attr.selectableItemBackground,
        typedValue,
        true
    )
    if (typedValue.resourceId != 0) {
        v.setBackgroundResource(typedValue.resourceId)
    } else {
        v.setBackgroundColor(typedValue.data)
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.textview.MaterialTextView
        android:id="@+id/materialTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="32dp"
        android:padding="24dp"
        android:textAppearance=
            "@style/TextAppearance.MaterialComponents.Headline5"
        android:text="Material Text View"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

android kotlin - ListView alternate row color with ripple

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.RippleDrawable
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.*


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

        // get the widgets reference from XML layout
        val listView = findViewById<ListView>(R.id.listView)
        val textView = findViewById<TextView>(R.id.textView)


        // list to populate list view
        val list = mutableListOf(
            "Golden yellow",
            "Han purple",
            "Carrot orange",
            "Carnation pink",
            "Jungle green",
            "Lavender blush",
            "Lawn green"
        )

        // initialize an array adapter
        val adapter:ArrayAdapter<String> = object: ArrayAdapter<String>(
            this,
            android.R.layout.simple_dropdown_item_1line,
            list
        ){
            override fun getView(position: Int, convertView: View?,
                                 parent: ViewGroup): View {

                val tv =  super.getView(position,
                    convertView, parent) as TextView

                // list view item alternate color
                if (position % 2 == 0){
                    tv.background = getRippleDrawable()
                }else{
                    tv.background = getRippleDrawable(
                        rippleColor = Color.parseColor("#E30022"),
                        contentColor = Color.parseColor("#FEFEFA")
                    )
                }

                return tv
            }
        }


        // attach the array adapter with list view
        listView.adapter = adapter


        // list view item click listener
        listView.onItemClickListener = AdapterView.OnItemClickListener {
                parent, view, position, id ->

            val clickedItem = parent?.getItemAtPosition(position)
                .toString()
            textView.text = "Clicked : $clickedItem"
        }
    }
}



// method to generate ripple drawable
fun getRippleDrawable(
    rippleColor: Int = Color.parseColor("#007FFF"),
    contentColor: Int = Color.parseColor("#F0FFFF"),
    maskColor: Int = Color.RED
): RippleDrawable {
    return RippleDrawable(
        ColorStateList.valueOf(rippleColor),
        ColorDrawable(contentColor),
        ColorDrawable(maskColor)
    )
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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:id="@+id/rootLayout"
    android:background="#DCDCDC"
    android:padding="24dp">

    <ListView
        android:id="@+id/listView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="TextView" />

</androidx.constraintlayout.widget.ConstraintLayout>

android kotlin - Create ColorStateList programmatically

MainActivity.kt

package com.example.jetpack

import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

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

        // generate background tint list for button
        button2.backgroundTintList = generateColorStateList()

        // modify disabled color on method
        button3.backgroundTintList = generateColorStateList(
            // disabled color Alabaster
            disabledColor = Color.parseColor("#EDEAE0")
        )

        // background tint list for checkbox and radio button
        materialCheckBox1.buttonTintList = generateColorStateList()
        materialRadioButton.buttonTintList = generateColorStateList()
    }
}


// method to generate color state list programmatically
fun generateColorStateList(
    enabledColor:Int = Color.parseColor("#00BFFF"), // Capri
    disabledColor:Int = Color.parseColor("#A2A2D0"), // Blue bell
    checkedColor:Int = Color.parseColor("#7BB661"), // Bud green
    uncheckedColor:Int = Color.parseColor("#A3C1AD"), // Cambridge blue
    activeColor:Int = Color.parseColor("#1034A6"), // Egyptian blue
    inactiveColor:Int = Color.parseColor("#614051"), // Eggplant
    pressedColor:Int = Color.parseColor("#FFD300"), // Cyber yellow
    focusedColor:Int = Color.parseColor("#00FFFF") // Aqua
):ColorStateList{
    val states = arrayOf(
        intArrayOf(android.R.attr.state_enabled),
        intArrayOf(-android.R.attr.state_enabled),
        intArrayOf(android.R.attr.state_checked),
        intArrayOf(-android.R.attr.state_checked),
        intArrayOf(android.R.attr.state_active),
        intArrayOf(-android.R.attr.state_active),
        intArrayOf(android.R.attr.state_pressed),
        intArrayOf(android.R.attr.state_focused)
    )
    val colors = intArrayOf(
        enabledColor, // enabled
        disabledColor, // disabled
        checkedColor, // checked
        uncheckedColor, // unchecked
        activeColor, // active
        inactiveColor, // inactive
        pressedColor, // pressed
        focusedColor // focused
    )
    return ColorStateList(states, colors)
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Material Button Default"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Color States"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Disabled Button"
        android:enabled="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button2" />

    <com.google.android.material.checkbox.MaterialCheckBox
        android:id="@+id/materialCheckBox1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="24dp"
        android:text="Check Me"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button3" />

    <com.google.android.material.radiobutton.MaterialRadioButton
        android:id="@+id/materialRadioButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:text="Select Me"
        app:layout_constraintBottom_toBottomOf="@+id/materialCheckBox1"
        app:layout_constraintStart_toEndOf="@+id/materialCheckBox1" />

</androidx.constraintlayout.widget.ConstraintLayout>

android kotlin - ListView delete item on click

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.app.AlertDialog
import android.os.Bundle
import android.widget.*


class MainActivity : Activity() {
    lateinit var context:MainActivity

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

        // get the context
        context = this

        // get the widgets reference from XML layout
        val listView = findViewById<ListView>(R.id.listView)
        val listView2 = findViewById<ListView>(R.id.listView2)


        // list to populate list view
        val list = mutableListOf(
            "Golden yellow",
            "Han purple",
            "Hansa yellow",
            "Jazzberry jam"
        )

        // initialize an array adapter
        val adapter:ArrayAdapter<String> = ArrayAdapter<String>(
            context,
            android.R.layout.simple_dropdown_item_1line,
            list
        )

        // attach the array adapter with list view
        listView.adapter = adapter

        // list view item click listener
        listView.onItemClickListener = AdapterView.OnItemClickListener {
                parent, view, position, id ->

            // remove clicked item from list view
            list.removeAt(position)
            adapter.notifyDataSetChanged()
        }



        // another list to populate second list view
        val list2 = mutableListOf(
            "Android green",
            "Antique brass",
            "Antique white",
            "Avocado"
        )


        // initialize another array adapter
        val adapter2:ArrayAdapter<String> = ArrayAdapter<String>(
            context,
            android.R.layout.simple_dropdown_item_1line,
            list2
        )


        // attach the array adapter with second list view
        listView2.adapter = adapter2


        // second list view item click listener
        listView2.onItemClickListener = AdapterView.OnItemClickListener {
                parent, view, position, id ->

            val clickedItem = parent.getItemAtPosition(position).toString()

            // show an alert dialog to confirm
            AlertDialog.Builder(context).apply {
                setTitle("Item: $clickedItem")
                setMessage("Are you want to delete it from list view?")

                setPositiveButton("Delete"){_,_->
                    // remove clicked item from second list view
                    list2.removeAt(position)
                    adapter2.notifyDataSetChanged()
                }

                setNeutralButton("Cancel"){_,_->}
            }.create().show()
        }
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootLayout"
    android:background="#DCDCDC"
    android:padding="24dp">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:choiceMode="singleChoice"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ListView
        android:id="@+id/listView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:choiceMode="singleChoice"
        android:background="#F8F8F8"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/listView" />

</androidx.constraintlayout.widget.ConstraintLayout>

Android Kotlin: How to programmatically disable an item in ListView

This code demonstrates two approaches to disable items in a ListView within an Android application written in Kotlin. Disabling an item prevents the user from clicking it and performing any associated actions. The code includes a button that allows the user to manually disable an item and also showcases programmatic disabling during the list adapter initialization.

Breakdown of the Code

The code consists of two main parts: the MainActivity.kt file containing the Activity code and the activity_main.xml file defining the layout.

  • MainActivity.kt:
    • This file defines the MainActivity class which extends the Activity class.
    • It retrieves references to the UI elements (Button, ListView, TextView) from the layout using findViewById.
    • It creates a list of color names to populate the ListView.
    • An ArrayAdapter is initialized with the list data. This adapter provides a bridge between the data and the ListView.
      • The isEnabled method of the adapter overrides the default behavior. It returns false only for the item at position 4 (index starts from 0), effectively disabling clicks on that specific item.
      • The getView method additionally sets the text view color for the disabled item, but this doesn't actually prevent clicks.
    • The adapter is attached to the ListView.
    • An onItemClickListener is set for the ListView to capture user clicks and display the selected item in a TextView.
    • A button click listener is implemented. Clicking the button disables the button itself and then disables the third item (index 2) in the ListView by directly modifying its properties.

Summary

This code provides a comprehensive example of disabling ListView items in Kotlin. It demonstrates both programmatic control during adapter initialization and user interaction through a button click. By understanding the isEnabled method and direct view manipulation, developers can achieve different levels of item disabling functionality within their Android applications.


MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.*


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

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)
        val listView = findViewById<ListView>(R.id.listView)
        val textView = findViewById<TextView>(R.id.textView)


        // list to populate list view
        val list = mutableListOf(
            "Golden yellow",
            "Han purple",
            "Hansa yellow",
            "Jazzberry jam",
            "Jungle green",
            "Lavender blush",
            "Lawn green"
        )


        // initialize an array adapter
        val adapter:ArrayAdapter<String> = object: ArrayAdapter<String>(
            this,
            android.R.layout.simple_dropdown_item_1line,
            list
        ){
            override fun isEnabled(position: Int): Boolean {
                // disable adapter fifth item at array adapter initialization
                // this actually disable list view item click
                return position != 4
            }

            override fun getView(position: Int, convertView: View?,
                                 parent: ViewGroup): View {

                val tv =  super.getView(position,
                    convertView, parent) as TextView

                // show the disable text color for fifth item
                // this actually not disable the list view item click
                tv.isEnabled = position != 4

                return tv
            }
        }


        // attach the array adapter with list view
        listView.adapter = adapter


        // list view item click listener
        listView.onItemClickListener = AdapterView.OnItemClickListener {
                parent, view, position, id ->

            val selectedItem = parent?.getItemAtPosition(position)
                .toString()
            textView.text = selectedItem
        }


        // disable list view third item on button click
        button.setOnClickListener {
            // disable the button itself
            it.isEnabled = false

            // disable the third item of list view
            val view = listView.getChildAt(2)
            view.setOnClickListener { }
            view.isEnabled = false
        }
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootLayout"
    android:background="#DCDCDC"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Disable Third Item"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ListView
        android:id="@+id/listView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="24dp"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Select your favorite color"
        android:fontFamily="sans-serif"
        android:gravity="center"
        android:textColor="#333399"
        android:textSize="24sp"
        android:textStyle="italic"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>