Android TextView Using Kotlin – A Comprehensive Tutorial

Filed Under: Android

Kotlin is the official programming language for Android apps development. In this tutorial, we’ll be discussing TextViews in Android applications using Kotlin programming. We’ll create and change TextViews code in Kotlin programming.

Android TextView Overview

Android TextView is a subclass of the View class. The View class typically occupy our window. TextView is used to display text on the screen. We can do a lot of fancy things using TextView.

Let’s start with a fresh project in Android Studio.

Create a new project and make sure you’ve enabled Kotlin in the setup wizard.

android textview kotlin project

Creating TextView in XML Layout

TextView is created in an xml layout in the following manner.

<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

The four attributes defined above are the core attributes of the TextView widget.

  1. The id property is used to set a unique identifier. It’s set as @+id/ followed by the name you assign. The same name would be used to retrieve the TextView property in our Kotlin Activity class.
  2. The text property is used to set the string text to be displayed in the TextView.
  3. As it is evident from the names itself, layout_width and layout_height are used to set the boundaries of the TextView. The wrap_content means wrapping the width, height to the length of the text. The match_parent means the TextView matches the width/height of the enclosed parent view. We can also set hardcoded values in dp (device independent pixels).

Clean Code Tips: Instead of hardcoding the string, define it inside the strings.xml and set the text in the layout as follows.

android:text="@string/app_name"

Let’s apply some attributes over the TextView in XML.

TextView XML Attributes

Let’s give you a quick tour of some of the popular attributes of TextView widget.

  • android:textSize: sets the size of the TextView. It’s recommended to use sp instead of dp. The sp stands for scale independent pixels and scales the font. Example: 16sp.
  • The android:textColor is used to set a color for the text. Typically it is of the format #rgb, #rrggbb, #aarrggbb.
  • The android:background attribute is used to set the background color of the TextView.
  • The android:textStyle is used to set the style among bold, italic, and normal. If you want to set bold and italic, use android:textStyle = “bold|italic”.
  • The android:textAppearance attribute is used to set the style on a TextView, which includes its own color, font, and size. We can create custom styles in the styles.xml file.
  • android:visibility is used to set the visibililty of the text, possible values are visible, invisible, and gone. The gone makes the textview invisible and removes it from the current position in the layout.
  • The android:ellipsize is used to handle situations when the length of the text exceeds the limit.
  • android textview ellipisize.

  • The end adds dots when the text reaches the limit width of the TextView. The start adds the dots at the beginning. The marquee is used to make the text continously slide left and right to show the full text.
  • The android:onClick is the method name in the Kotlin Activity class that’ll be invoked on TextView click. We need to ensure android:clickable is set to true for this attribute.
  • android:typeface is used to set the typeface of the text.
  • android textview xml typeface

  • android:drawableLeft is used to set a drawable/mipmap image or vector asset besides the TextView.
  • The android:gravity is used to set the position of the text relative to its dimensions.
  • android:layout_margin is used to set the spacing of the TextView from the other views present in the layout. The layout_marginLeft, layout_marginRight, layout_marginTop, layout_marginBottom are used for setting margins on the individiual sides.
  • The android:padding is used to add spacing inside the four sides of the TextView. The possible values are paddingLeft, paddingRight, paddingTop, and paddingBottom.

Let’s use the xml attributes on a TextView in our layout.

<?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:gravity="center"
    android:id="@+id/linearLayout"
    android:orientation="vertical"
    tools:context="net.androidly.androidtextviewkotlin.MainActivity">


    <TextView
        android:id="@+id/textViewEllipsize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:text="@string/long_string"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/textViewClickMe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:background="@color/colorPrimaryDark"
        android:padding="@android:dimen/app_icon_size"
        android:shadowColor="@android:color/black"
        android:text="TextView Click Me" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Android TextView Color"
        android:textAllCaps="true"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="#234568"
        android:textStyle="bold|italic" />

    <TextView
        android:id="@+id/textViewOpacity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:drawableLeft="@mipmap/ic_launcher"
        android:drawablePadding="16dp"
        android:gravity="center"
        android:text="Android TextView Opacity is 50 percent"
        android:textColor="#50234568"
        android:textSize="14sp"
        android:typeface="serif" />


</LinearLayout>

Note: We’ve replaced the ConstraintLayout with a LinearLayout to make things easier.

android textview XML output

Notice the opacity in the last TextView

For more info on XML attributes for Android TextView, visit the Google docs attached at the end of this page or JournalDev Android TextView tutorial.

In the following section, we’ll create TextView programmatically using Kotlin and set Kotlin functions, properties, and use lambda functions over the TextView.

Creating Android TextView using Kotlin

We can get the TextView in our MainActivity.kt Kotlin class using findViewById.

The findViewById is used to get a view from the XML in the Activity class using the id specified. It works like a dictionary – key/value pair.

package net.androidly.androidtextviewkotlin

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

class MainActivity : AppCompatActivity() {

    val TAG = "MainActivity"

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

        var textView = findViewById<textview>(R.id.textView)
        
        //text property is equivalent to getText() or setText() in Java.
        Log.d(TAG,"TextView text is ${textView.text}") //Logs TextView text is Android TextView Color
        
        //setting the text.
        textView.text = "Text changed"
        
        //Setting the text from the strings.xml file.
        textView.text = resources.getString(R.string.app_name)

    }
}

Code Explanation:

  • MainActivity Kotlin class extends AppCompatActivity.
  • We’ve created the textView property by using findViewById. Though from Android API > 24 you can ignore specifying the type explicitly.
  • The text property is used as getter/setter on the TextView. It returns a CharSequence.
  • ${textView.text} implcitily converts the CharSequence to a String.
  • The text property in Kotlin is equivalent to getText() and setText(String) in Java.
  • To set the string from the strings.xml file, we call resources.getString(R.string.). The resources property is equivalent to getResources() from Java.

Handling Null Values in TextView Kotlin Code

Kotlin has a very safe way to deal with null values. Optional Types act as a wrapper over the current type. They need to be safely unwrapped to use non-null values, thus enabling null safety in our Kotlin code.

Let’s look at how the above app behaves when the textView is null.

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

        var textView = findViewById<textview>(R.id.textView)
        textView.text = null
        Log.d(TAG, "TextView text is ${textView.text}") // Logs TextView text is
        textView = null
        Log.d(TAG, "TextView text is ${textView.text}") //compilation error. Add safe call.
}

So when the text is null, the compiler ignores it.

When the textView is null, we need to add a safe call to unwrap the textView. This way Kotlin automatically gives us null safety.

What if the textView is null at runtime?

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //we've set a random id available from the autocomplete just to set textView to null at runtime.
        var textView = findViewById<textview>(R.id.ALT) 
        Log.d(TAG, "TextView text is ${textView.text}")
    }

It will throw error message as IllegalStateException. TextView cannot be null..

So let’s set the TextView properties as Optional in the declaration.

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

        val otherTextView: TextView? = findViewById(R.id.textViewOpacity)
        otherTextView?.text = null
        Log.d(TAG, "TextView displays ${otherTextView?.text ?: "NA"}")
    }

We’ve set otherTextView to the type TextView.

So calling anything over the TextView would require a safe call.

What if the text is null? What do we display instead?

We use the elvis operator ?: from Kotlin for null safety.

In the above code, NA gets displayed if otherTextView?.text is null.

The safe call can be replaced by a let lambda expression too.

Kotlin Android Extensions

Thanks to apply plugin: 'kotlin-android-extensions' in our build.gradle file, we can directly bind views from the layout in our Kotlin activity class.

Add the following import statement in your MainActivity.kt class.

import kotlinx.android.synthetic.main.activity_main.*

Now you can use the TextView properties directly without using findViewById.

Android TextView Kotlin onClick Listener

package net.androidly.androidtextviewkotlin

import android.graphics.Color
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.content.ContextCompat
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    val TAG = "MainActivity"

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

        //set textView to clickable
        textView.isClickable = true
        textView.setOnClickListener{ textView.text = resources.getString(R.string.app_name) }

        textViewClickMe.setOnClickListener { textViewClickMe.setTextColor(Color.WHITE) }

        textViewEllipsize.ellipsize = TextUtils.TruncateAt.MARQUEE
        textViewEllipsize.setHorizontallyScrolling(true)
        textViewEllipsize.marqueeRepeatLimit = -1
        textViewEllipsize.isSelected = true

        val mipMapDrawable = ContextCompat.getDrawable(this, R.mipmap.ic_launcher)
        textViewOpacity.setCompoundDrawablesWithIntrinsicBounds(mipMapDrawable,null,mipMapDrawable,null)

    }
}

In the above code, for the setOnClickListener we use lambda expressions from Kotlin. It makes the code shorter and easier to read than Java.

To make the textViewEllipsize slide, set it to MARQUEE. To make it loop continuously, we’ve set marqueeRepeatLimit to -1.

The mipMapDrawable is of the type Drawable and setCompoundDrawablesWithIntrinsicBounds() is the equivalent of android:drawablePadding.

The app output is shown in the following GIF.

android textview kotlin app output

Android TextView extension functions

We can create Kotlin extension functions on a TextView to add our custom functions and properties.

The below extension function creates a consistent property for currentTextColor property and setTextColor() function.

Add the following code outside the class.

var TextView.textColor: Int
get() = currentTextColor
set(v) = setTextColor(v)

We can then set the color on our TextView using the textColor property.

textViewOpacity.textColor = ContextCompat.getColor(this, R.color.colorPrimaryDark)

Android TextView “with” expression

Instead of using redundant lines where we set the attributes on the same TextView property like this:

textViewEllipsize.ellipsize = TextUtils.TruncateAt.MARQUEE
textViewEllipsize.setHorizontallyScrolling(true)
textViewEllipsize.marqueeRepeatLimit = -1
textViewEllipsize.isSelected = true
textViewEllipsize.setOnClickListener { println("So many calls to the same TextView") }

We can make it better using the with expression.

with(textViewEllipsize)
        {
            ellipsize = TextUtils.TruncateAt.MARQUEE
            setHorizontallyScrolling(true)
            marqueeRepeatLimit = -1
            isSelected = true
            setOnClickListener { println("WOW. AWESOME.") }
        }

Creating a TextView Programmatically in Kotlin

Below, we’ve created two TextViews programmatically. We’ve set a custom font from the assets folder and set underline on one of the TextViews. Also, we’ve set the string in the form of HTML.

The assets directory is created under src | main folder and is used to hold the TTF files for the custom fonts.

package net.androidly.androidtextviewkotlin

import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.os.Build
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.text.Html
import android.text.TextUtils
import android.view.Gravity
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    val TAG = "MainActivity"
    lateinit var programmaticTextView : TextView
    var optionalTextView : TextView? = null

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

        programmaticTextView = TextView(this)
        with(programmaticTextView)
        {
            text = "I'm Created Programmatically. Kotlin makes life simple"
            textSize = 20f
            textColor = Color.parseColor("#1F2135")
            typeface = Typeface.DEFAULT_BOLD
            isClickable = true
            setOnClickListener { println("I contain the string: $text") }
        }

        linearLayout.addView(programmaticTextView)

        optionalTextView = TextView(this)

        optionalTextView.let { with(optionalTextView!!)
        {
            text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                "${Html.fromHtml("

<h4>this is underlined text</h4>

Body goes here",Html.FROM_HTML_MODE_LEGACY)}"
            } else {
                @Suppress("DEPRECATION")
                "${Html.fromHtml("this is <u>underlined</u> text")}"
            }
            typeface = Typeface.createFromAsset(assets, "Pacifico.ttf")
            textSize = 20f
            gravity = Gravity.CENTER
            paintFlags = Paint.UNDERLINE_TEXT_FLAG


        } }

        linearLayout.addView(optionalTextView)
    }
}


var TextView.textColor: Int
    get() = currentTextColor
    set(v) = setTextColor(v)

Kotlin properties are required to be initialized there itself. If it’s not possible, we can set a lateinit modifier to the property.

By default, when the textView is created programmatically, its width is match_parent and height is wrap_content.

The paintFlags is used to add an underline to the string.

The output with the above TextViews added into the layout programmatically is shown in the following image.

android textview kotlin programming output

Using Spannable Strings

Spannable Strings are useful when we have to set different styles on different substrings of the TextView.

val string = "this is normal, this is underlined"
val firstWord = string.substringBefore(",")
val secondWord = string.substringAfterLast(",")
val redColor = ForegroundColorSpan(
        ContextCompat.getColor(this,android.R.color.holo_red_dark))

val ssb = SpannableStringBuilder(firstWord)

ssb.setSpan(
        redColor, // the span to add
        0, // the start of the span (inclusive)
        ssb.length, // the end of the span (exclusive)
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
ssb.append(" ")

val underlineSpan = UnderlineSpan()

ssb.append(secondWord)
ssb.setSpan(
        underlineSpan,
        ssb.length - secondWord.length,
        ssb.length,
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

optionalTextView = TextView(this)

optionalTextView.let { with(optionalTextView!!)
{
    text = ssb
    typeface = Typeface.createFromAsset(assets, "Pacifico.ttf")
    textSize = 20f
    gravity = Gravity.CENTER


} }

linearLayout.addView(optionalTextView)

Output:

android textview spannable string

This brings an end to the comprehensive tutorial on Android TextViews using Kotlin programming.

You can download the project from the following link: AndroidTextViewKotlin

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