android kotlin - Create spinner programmatically

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.*
import androidx.constraintlayout.widget.ConstraintSet


class MainActivity : Activity() {
    private 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 rootLayout = findViewById<ConstraintLayout>(R.id.rootLayout)


        // initialize a new spinner widget
        val spinner = Spinner(context)

        // set spinner width and height
        val layoutParams = LayoutParams(
            LayoutParams.WRAP_CONTENT, // width
            LayoutParams.WRAP_CONTENT // height
        )
        spinner.layoutParams = layoutParams

        // generate an id for spinner
        spinner.id = View.generateViewId()

        // finally, add spinner to constraint layout
        rootLayout.addView(spinner)


        // initialize a new constraint set
        val constraintSet = ConstraintSet()
        constraintSet.clone(rootLayout)


        // this two block of code put spinner
        // horizontally center of parent
        // set spinner constraint start to start of parent
        constraintSet.connect(
            spinner.id, START, PARENT_ID, START)


        // set spinner constraint end to end of parent
        constraintSet.connect(spinner.id, END, PARENT_ID, END)


        // set spinner constraint top to top of parent with margin
        constraintSet.connect(
            spinner.id,TOP, PARENT_ID, TOP, 32.toDp(context)
        )

        // finally, apply the constraint set to constraint layout
        constraintSet.applyTo(rootLayout)


        // list of spinner items
        val list = mutableListOf(
            "Jungle green",
            "Light periwinkle",
            "Lemon glacier",
            "Kelly green",
            "Lemon yellow",
            "Lavender blush"
        )


        // initialize an array adapter for spinner
        val adapter:ArrayAdapter<String> = object: ArrayAdapter<String>(
            context,
            android.R.layout.simple_spinner_dropdown_item,
            list
        ){
            override fun getDropDownView(
                position: Int,
                convertView: View?,
                parent: ViewGroup
            ): View {
                val view:TextView = super.getDropDownView(
                    position,
                    convertView,
                    parent
                ) as TextView

                // set item text style and font
                view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD)

                // set spinner item padding
                view.setPadding(
                    25.toDp(context), // left
                    10.toDp(context), // top
                    50.toDp(context), // right
                    10.toDp(context) // bottom
                )

                // alternate item style
                if (position %2 == 1){
                    view.background = ColorDrawable(
                        Color.parseColor("#F0FFF0"))
                }else{
                    view.background = ColorDrawable(
                        Color.parseColor("#FFFFF0"))
                }

                return view
            }
        }


        // finally, data bind spinner with adapter
        spinner.adapter = adapter


        // spinner on item selected listener
        spinner.onItemSelectedListener =
            object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(
                parent: AdapterView<*>,
                view: View,
                position: Int,
                id: Long
            ) {
                val selectedItemText = parent
                    .getItemAtPosition(position).toString()
                Toast.makeText(
                    context,"Selected: $selectedItemText",
                    Toast.LENGTH_SHORT).show()
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {
                // another interface callback
            }
        }
    }
}



// extension method to convert values to dp
fun Int.toDp(context: Context):Int = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    this.toFloat(),
    context.resources.displayMetrics
).toInt()
activity_main.xml

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

</androidx.constraintlayout.widget.ConstraintLayout>