Android EditText Using Kotlin

Filed Under: Android

In this tutorial, we’ll be implementing EditText using Kotlin in our Android Application. We’ll create EditText using XML as well as programmatically. Furthermore, we’ll look at the ease of Kotlin extension functions in our code.

Android EditText

EditText is a subclass of TextView that allows user input and editting. It’s commonly used in login screens and forms.
An EditText is defined in the xml in the following way:


<EditText
        android:id="@+id/inNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:hint="@string/enter_a_number_here"
        android:imeOptions="actionNext"
        android:inputType="number" />
  • android:id is used to set a unique identifier on the EditText
  • layout_margin is used to set the margin outside the EditText view.
  • hint is used to set the hint of the EditText.
  • imeOptions is used to set the behaviour of the bottom rightmost keyboard button. It can be set to done, search, next etc. Setting it to next would take the cursor to the next EditText present in the screen.
  • inputType is used to specify the input format allowed. By default it is text. email, number, numberDecimal etc can be set as per our needs.

For more details on customizing EditText in using XML do refer to the JournalDev Android EditText Tutorial.

Creating an Android EditText programmatically

Following syntax in your activity would create an EditText.


val editText = EditText(this)
linearLayout.addView(editText)

EditText TextWatcher

TextWatcher is an interface which listens to changes in the EditText before, after and during an input is being typed.
It contains three functions that need to be overridden.

  • afterTextChanged : Gets triggered immediately after something is typed
  • beforeTextChanged : Gets triggered before the next input.
  • onTextChanged : Gets triggered during an input.

To set a TextWatcher on the EditText we invoke the interface inside an addTextChangedListener function.


editText.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                toast(message = "Number is $s")
            }

        })

Kotlin Objects aren’t the same as the Java objects.
onTextChanged differs from afterTextChanged in terms of the arguments they have.

Let’s jump onto the business end of this tutorial. Our application would listen for changes in EditText input and update them in a TextView defined programmatically.

Project Structure

android-edittext-kotlin-project-structure

Layout Code

The code for the activity_main.xml layout is given below.


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

    <EditText
        android:id="@+id/inNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:hint="@string/enter_a_number_here"
        android:imeOptions="actionNext"
        android:inputType="number" />

</LinearLayout>

Activity code

The code for the MainActivity.kt class is given below:


package net.androidly.androidlyedittext

import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.text.Editable
import android.text.TextWatcher
import android.view.inputmethod.EditorInfo
import android.widget.*
import kotlinx.android.synthetic.main.activity_main.*
import android.widget.LinearLayout


class MainActivity : AppCompatActivity() {


    val txtAfter by lazy { TextView(this) }
    val txtOn by lazy { TextView(this) }
    val txtBefore by lazy { TextView(this) }

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

        val inNumber = findViewById(R.id.inNumber)

        inNumber.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                toast(message = "Number is $s")
            }

        })


        val editText = EditText(this)
        editText.apply {
            setText("Androidly EditText")
            hint = "Keep entering"
            val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            lp.setMargins(8, 8, 8, 8)
            layoutParams = lp
            imeOptions = EditorInfo.IME_ACTION_NEXT
            setTextColor(ContextCompat.getColor(this@MainActivity, android.R.color.holo_purple))
            smartTextWatcher(
                    on = { txtOn.apply { text = "onTextChanged: $it" } },
                    after = { txtAfter.apply { text = "smartTextWatcher: $it" } },
                    before = { txtBefore.apply { text = "beforeTextChanged: $it" } }
            )
        }


        linearLayout.addView(editText)

        val editText2 = EditText(this)
        editText2.apply {
            hint = "Enter something"
            val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            lp.setMargins(8, 8, 8, 8)
            layoutParams = lp
            setBackgroundColor(ContextCompat.getColor(this@MainActivity, android.R.color.holo_green_dark))
            imeOptions = EditorInfo.IME_ACTION_DONE
            smartTextWatcher(
                    on = { txtOn.apply { text = "onTextChanged: $it" } },
                    after = { txtAfter.apply { text = "smartTextWatcher: $it" } },
                    before = { txtBefore.apply { text = "beforeTextChanged: $it" } }
            )
        }

        linearLayout.addView(editText2)

        txtAfter.text = "AfterTextChanged :"
        txtAfter.setPadding(8, 8, 8, 8)
        linearLayout.addView(txtAfter)

        txtOn.text = "OnTextChanged :"
        txtOn.setPadding(8, 8, 8, 8)
        linearLayout.addView(txtOn)

        txtBefore.text = "BeforeTextChanged :"
        txtBefore.setPadding(8, 8, 8, 8)
        linearLayout.addView(txtBefore)
    }

    fun Context.toast(context: Context = applicationContext, message: String, duration: Int = Toast.LENGTH_SHORT) {
        Toast.makeText(context, message, duration).show()
    }

    fun EditText.smartTextWatcher(on: (String) -> Unit, after: (String) -> Unit, before: (String) -> Unit) {
        this.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                after.invoke(s.toString())
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                before.invoke(s.toString())
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                on.invoke(s.toString())
            }
        })
    }
}

In the above code:
We’ve created the TextViews programmatically and lazily using by lazy. That means that the instance of TextView would be created only when it gets invoked in the class.
findViewById<EditText> is used to get the EditText from the xml.
We display a toast when the text in the EditText is changed. The toast function is an extension function in Kotlin.
apply lambda expression is used to set the attributes on the EditText without the need to invoke the instance every time.
To set the layout parameters programmatically, we do:


val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
lp.setMargins(8, 8, 8, 8)
layoutParams = lp

fun EditText.smartTextWatcher is an Extension function created to shorten the verbose code of the TextWatcher interface by using lambda expressions.
For each of its arguments, we update the respective textviews inside the lambda expressions.

The output of the above application in action is given below.

android-edittext-kotlin-output

This brings an end to this tutorial on Android EditText. You can download the AndroidlyEditText Project from the link below.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages