Wednesday, March 7, 2018

android kotlin - ListView ViewHolder example

MainActivity.kt

package com.cfsuman.kotlinexamples

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

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

        // Get an instance of base adapter
        val adapter = ColorBaseAdapter()

        // Set the list view adapter
        list_view.adapter = adapter
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    >
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="#00ffffff"
        android:dividerHeight="7dp"
        />
</LinearLayout>
ColorBaseAdapter.kt

package com.cfsuman.kotlinexamples

import android.app.Activity
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.support.v7.widget.CardView
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 android.widget.Toast


class ColorBaseAdapter : BaseAdapter (){
    private val list = colors()

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

        if(convertView==null){
            // If convert view is null then inflate a custom view and use it as convert view
            convertView = LayoutInflater.from(parent?.context).
                    inflate(R.layout.custom_view,parent,false)

            // Create a new view holder instance using convert view
            viewHolder = ViewHolder(convertView)

            // Set the view holder as convert view tag
            convertView.tag = viewHolder
        }else{
            /*
                If convert view is not null then
                initialize the view holder using convert view tag.
            */
            viewHolder = convertView.tag as ViewHolder
        }

        // Display the current color name and value on view holder
        viewHolder.colorName.text = list[position].first
        viewHolder.imageView.setImageBitmap(drawCircle(list[position].second))

        // Set a click listener for card view
        viewHolder.card.setOnClickListener {
            // Show selected color in a toast message
            Toast.makeText(parent?.context,
                    "Clicked : ${list[position].first}", Toast.LENGTH_SHORT).show()

            // Get the activity reference from parent
            val activity = parent?.context as Activity

            // Get the activity root view
            val viewGroup = activity.findViewById<ViewGroup>(android.R.id.content)
                    .getChildAt(0)

            // Change the root layout background color
            viewGroup.setBackgroundColor(list[position].second)
        }

        // Finally, return the convert view
        return convertView!!
    }


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


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


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



    // Custom method to generate list of color name value pair
    private fun colors():List<Pair<String,Int>>{
        return listOf(
                Pair("INDIANRED",Color.parseColor("#CD5C5C")),
                Pair("LIGHTCORAL",Color.parseColor("#F08080")),
                Pair("SALMON",Color.parseColor("#FA8072")),
                Pair("DARKSALMON",Color.parseColor("#E9967A")),
                Pair("LIGHTSALMON",Color.parseColor("#FFA07A")),
                Pair("CRIMSON",Color.parseColor("#DC143C")),
                Pair("RED",Color.parseColor("#FF0000")),
                Pair("FIREBRICK",Color.parseColor("#B22222")),
                Pair("DARKRED",Color.parseColor("#8B0000")),

                Pair("PINK",Color.parseColor("#FFC0CB")),
                Pair("LIGHTPINK",Color.parseColor("#FFB6C1")),
                Pair("HOTPINK",Color.parseColor("#FF69B4")),
                Pair("DEEPPINK",Color.parseColor("#FF1493")),
                Pair("MEDIUMVIOLETRED",Color.parseColor("#C71585")),
                Pair("PALEVIOLETRED",Color.parseColor("#DB7093")),

                Pair("LIGHTSALMON",Color.parseColor("#FFA07A")),
                Pair("CORAL",Color.parseColor("#FF7F50")),
                Pair("TOMATO",Color.parseColor("#FF6347")),
                Pair("ORANGERED",Color.parseColor("#FF4500")),
                Pair("DARKORANGE",Color.parseColor("#FF8C00")),
                Pair("ORANGE",Color.parseColor("#FFA500")),

                Pair("GOLD",Color.parseColor("#FFD700")),
                Pair("YELLOW",Color.parseColor("#FFFF00")),
                Pair("LIGHTYELLOW",Color.parseColor("#FFFFE0")),
                Pair("LEMONCHIFFON",Color.parseColor("#FFFACD")),
                Pair("LIGHTGOLDENRODYELLOW",Color.parseColor("#FAFAD2")),
                Pair("PAPAYAWHIP",Color.parseColor("#FFEFD5")),
                Pair("MOCCASIN",Color.parseColor("#FFE4B5")),
                Pair("PEACHPUFF",Color.parseColor("#FFDAB9")),
                Pair("PALEGOLDENROD",Color.parseColor("#EEE8AA")),
                Pair("KHAKI",Color.parseColor("#F0E68C")),
                Pair("DARKKHAKI",Color.parseColor("#BDB76B"))
        )
    }



    private fun drawCircle(color:Int=Color.WHITE,width:Int=200):Bitmap{
        // Initialize a new Bitmap object
        val bitmap:Bitmap = Bitmap.createBitmap(
                width, // Width
        width, // Height
        Bitmap.Config.ARGB_8888 // Config
        )

        // Initialize a new Canvas instance
        val canvas:Canvas = Canvas(bitmap)

        // Draw a solid color to the canvas background
        canvas.drawColor(Color.TRANSPARENT)

        // Initialize a new Paint instance to draw the Circle
        val paint:Paint = Paint()
        paint.style =Paint.Style.FILL
        paint.color = color
        paint.isAntiAlias = true

        // Calculate the available radius of canvas
        val radius:Int = Math.min(canvas.width,canvas.height/2)

        // Set a pixels value to padding around the circle
        val padding:Int = 5

        // Finally, draw the circle on the canvas
        canvas.drawCircle(
                (canvas.width / 2).toFloat(), // cx
                (canvas.height / 2).toFloat(), // cy
                (radius - padding).toFloat(), // Radius
                paint // Paint
        )

        // Return the newly created bitmap
        return bitmap
    }
}



private class ViewHolder(view:View){
    var colorName: TextView = view.findViewById(R.id.color_name)
    var imageView: ImageView = view.findViewById(R.id.image_view)
    val card:CardView = view.findViewById(R.id.card_view)
}
custom_view.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="5dp"
    app:cardElevation="5dp"
    app:cardMaxElevation="7dp"
    app:contentPadding="5dp"
    android:layout_margin="5dp"
    app:cardBackgroundColor="#f7fff5"
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
        <ImageView
            android:id="@+id/image_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="25dp"
            />
        <TextView
            android:id="@+id/color_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:layout_gravity="center"
            />
    </LinearLayout>
</android.support.v7.widget.CardView>