使用Kotlin的Android TextView –全面教程

时间:2020-02-23 14:29:21  来源:igfitidea点击:

Kotlin是用于Android应用程序开发的官方编程语言。
在本教程中,我们将讨论使用Kotlin编程的Android应用程序中的TextView。
我们将在Kotlin编程中创建和更改TextViews代码。

Android TextView概述

Android TextView是View类的子类。
View类通常占据我们的窗口。
TextView用于在屏幕上显示文本。
我们可以使用TextView做很多花哨的事情。

让我们从Android Studio中的一个新项目开始。

创建一个新项目,并确保已在设置向导中启用Kotlin。

在XML布局中创建TextView

TextView以以下方式在xml布局中创建。

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

上面定义的四个属性是TextView小部件的核心属性。

  • id属性用于设置唯一标识符。
    它设置为@ + id /,后跟您分配的名称。
    相同的名称将用于检索Kotlin Activity类中的TextView属性。

  • text属性用于设置要在TextView中显示的字符串文本。

  • 从名称本身可以明显看出,layout_width和layout_height用于设置TextView的边界。
    wrap_content表示将宽度,高度包装为文本的长度。
    match_parent表示TextView与封闭的父视图的宽度/高度匹配。
    我们还可以设置dp(与设备无关的像素)中的硬编码值。

干净的代码提示:不用在字符串上进行硬编码,而是在strings.xml中定义它,并按如下所示在布局中设置文本。

android:text="@string/app_name"

让我们在XML的TextView上应用一些属性。

TextView XML属性

让我们快速浏览一下TextView小部件的一些流行属性。

  • android:textSize:设置TextView的大小。
    建议使用sp而不是dp。
    sp代表与比例无关的像素并缩放字体。
    示例:16sp。

  • android:textColor用于设置文本的颜色。
    通常,其格式为#rgb,#rrggbb,#aarrggbb。

  • android:background属性用于设置TextView的背景颜色。

  • android:textStyle用于设置粗体,斜体和普通样式。
    如果要设置粗体和斜体,请使用android:textStyle =" bold | italic"。

  • android:textAppearance属性用于在TextView上设置样式,该样式包括其自己的颜色,字体和大小。
    我们可以在" styles.xml"文件中创建自定义样式。

  • android:visibility用于设置文本的可视性,可能的值包括visible,invisible和goone。
    "消失"使文本视图不可见,并将其从布局中的当前位置删除。

  • android:ellipsize用于处理文本长度超过限制的情况。

  • 当文本达到TextView的限制宽度时," end"会添加点。
    "开始"在开始处添加点。
    "选取框"用于使文本连续左右滑动以显示全文。

  • android:onClick是Kotlin活动类中的方法名称,将在TextView点击时调用。
    我们需要确保将此属性的android:clickable设置为true。

  • android:typeface用于设置文本的字体。

  • android:drawableLeft用来设置TextView之外的drawable/mipmap图像或者矢量资源。

  • android:gravity用于设置文本相对于其尺寸的位置。

  • android:layout_margin用于设置TextView与布局中其他视图的间距。
    layout_marginLeft,layout_marginRight,layout_marginTop,layout_marginBottom用于在各个面上设置边距。

  • android:padding用于在TextView的四个侧面之间添加间距。
    可能的值为paddingLeft,paddingRight,paddingTop和paddingBottom。

让我们在布局中的TextView上使用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"
  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>

注意:为了方便起见,我们将ConstraintLayout替换为LinearLayout。

注意最后一个TextView中的不透明度

有关Android TextView的XML属性的详细信息,请访问此页末尾随附的Google文档或者theitroad Android TextView教程。

在以下部分中,我们将使用Kotlin以编程方式创建TextView,并设置Kotlin函数,属性,并在TextView上使用lambda函数。

使用Kotlin创建Android TextView

我们可以使用findViewById在MainActivity.kt Kotlin类中获取TextView。

" findViewById"用于使用指定的ID从Activity类中的XML获取视图。
它就像字典一样-键/值对。

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)

  }
}

代码说明:

  • MainActivity Kotlin类扩展了AppCompatActivity。

  • 我们已经使用findViewById创建了textView属性。
    虽然从Android API> 24开始,您可以忽略显式指定类型。

  • text属性用作TextView上的getter/setter方法。
    它返回一个CharSequence。

  • ${textView.text}不正确地将CharSequence转换为字符串。

  • Kotlin中的text属性等效于Java中的getText()setText(String)

  • 要从strings.xml文件设置字符串,我们调用resources.getString(R.string )
    resources属性等效于Java中的getResources()

在TextView Kotlin代码中处理空值

Kotlin有一个非常安全的方法来处理空值。
可选类型充当当前类型的包装。
需要安全地解开它们才能使用非null值,从而在我们的Kotlin代码中启用null安全性。

让我们看一下当textView为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.
}

因此,当文本为null时,编译器将忽略它。

当textView为null时,我们需要添加一个安全调用以解开textView。
这样Kotlin会自动为我们提供零安全。

如果textView在运行时为null怎么办?

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}")
  }

它将引发错误消息为ʻIllegalStateException。
TextView不能为null。

因此,让我们在声明中将TextView属性设置为Optional。

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"}")
  }

我们已经将otherTextView设置为TextView类型。

因此,通过TextView调用任何内容都需要安全的调用。

如果文本为空怎么办?我们显示什么呢?

我们使用Kotlin的Elvis运算符?:来确保安全。

在上面的代码中,如果otherTextView?.text为null,则显示NA。

安全调用也可以由letlambda表达式代替。

Kotlin Android扩展

多亏了我们build.gradle文件中的apply plugin:'kotlin-android-extensions',我们可以在Kotlin活动类中直接从布局中绑定视图。

在MainActivity.kt类中添加以下导入语句。

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

现在,您可以直接使用TextView属性,而无需使用findViewById。

Android TextView Kotlin onClick侦听器

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)

  }
}

在上面的代码中,对于setOnClickListener,我们使用Kotlin的lambda表达式。
与Java相比,它使代码更短,更易于阅读。

要使" textViewEllipsize"幻灯片滑动,请将其设置为" MARQUEE"。
为了使其连续循环,我们将marqueeRepeatLimit设置为-1。

" mipMapDrawable"的类型为Drawable,而" setCompoundDrawablesWithIntrinsicBounds()"的类型相当于" android:drawablePadding"。

应用程序的输出显示在以下GIF中。

Android TextView扩展功能

我们可以在TextView上创建Kotlin扩展功能,以添加自定义功能和属性。

下面的扩展功能为currentTextColor属性和setTextColor()函数创建了一个一致的属性。

在类外添加以下代码。

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

然后,我们可以使用textColor属性在TextView上设置颜色。

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

Android TextView" with"表达式

代替使用多余的行,我们在同一个TextView属性上像下面这样设置属性:

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

我们可以使用with表达式使它更好。

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

在Kotlin中以编程方式创建TextView

下面,我们以编程方式创建了两个TextView。
我们从资产文件夹中设置了自定义字体,并其中一个TextView上设置了下划线。
另外,我们将字符串设置为HTML形式。

资产目录在src下创建。
main文件夹,用于保存自定义字体的TTF文件。

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属性需要在此处本身进行初始化。
如果不可能的话,我们可以为属性设置一个" lateinit"修饰符。

默认情况下,以编程方式创建textView时,其宽度为match_parent,高度为wrap_content。

paintFlags用于在字符串上添加下划线。

下图显示了将上述TextViews以编程方式添加到布局中的输出。

使用跨度字符串

当我们必须在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)