天天看點

Kotlin學習日志(六)控件使用

前言

學習最重要的就是堅持了,笨鳥多飛,業精于勤荒于嬉,學如逆水行舟,不進則退。前面學了那麼多關于函數、文法、類這些知識,确實是比較枯燥,但卻是有必要的,因為這些都是在進行業務實作需要的,舉個例子,正常功能,登入。你有想過需要哪些業務邏輯處理嗎?你不會以為輸入賬号密碼就沒事了嗎?當然不是,登入首先是頁面的布局處理,通常的是輸入框和按鈕的搭配,當然有的會有圖形驗證碼,手勢驗證碼,或者滑動驗證等驗證手段,最簡單的就是隻有賬号和密碼的登入,但是賬号和密碼也是要做限制的,登入的時候首先做非空判斷,輸入類型限制,比如賬号指定是純數字、還是數字加字母,一般來說是純數字的,純數字要限制多少位數,如果是手機号的話需要用正規表達式來驗證是否為正規的手機号,總不能你輸入個13888888888,我都能讓你登入上去吧,那這個程式員也要開除,其次就是登入的時候與背景的資料庫進行查詢對比,假如沒有這個手機号是不是還要先注冊呢?然後密碼當然不能明文顯示,也不能明文傳輸啊,也不能是純數字或者純字母,特殊符号什麼的,這裡又涉及到了密碼的安全登入,常見的是三級,純數字是不行的,這一步你在注冊的時候就過不去,然後是最短和最長的密碼位數限制,一般來說最短8位最長18位,然後就是傳輸過程加密,背景對比資料庫的值是否一緻,一緻再允許登入,進一步的出來就是登入過程中的網絡處理了,網絡請求多長時間,網絡異常,等一些問題的處理,但是在使用者眼裡就是一個簡單的登入而已,是以任何功能的設定都沒有你實際看上去的那麼簡單,如果你想的過于簡單的話,都不用到客戶,測試就能玩死你,你信不信?好了,廢話說的有點多了,接下來進入正題,Kotlin中控件的的使用。

快捷檢視

  • ​​前言​​
  • ​​一、簡單控件使用​​
  • ​​1.1 按鈕Button​​
  • ​​1. 匿名函數方式​​
  • ​​2. 内部類方式​​
  • ​​3. 接口實作方式​​
  • ​​1.2 複選框CheckBox​​
  • ​​1.3 單選按鈕RadioButton​​
  • ​​1.4 開關按鈕Switch​​
  • ​​1.5 文本視圖TextView​​
  • ​​1.6 圖像視圖ImageView​​
  • ​​1.7 文本編輯框EditText​​

一、簡單控件使用

我們之後寫示例的時候用到最多的控件就是按鈕Button了。

1.1 按鈕Button

Button是Android常用的控件之一,我在前面的文章就提到過Button

​​​Kotlin學習日志(一)TextView、Button、Toast的使用​​ 我們看一下使用的代碼。

btn_test.setOnClickListener { btn_test.text = "您點了一下下" }      

有沒有很熟悉的感覺呢?而長按事件處理和點選事件差不太多,隻要在長按代碼末尾加上true的傳回,就可以了,代碼如下:

btn_test.setOnLongClickListener { btn_test.text="您長按了一小下下";true }      

上面的兩種按鈕事件代碼其實是簡化最徹底的表達形式,因為點選事件和長按時間本身存在輸入參數,它們的入參是發生了點選和長按動作的視圖對象,是以完整的事件處理代碼應當保留視圖對象這個輸入參數。隻不過由于多數情況用不到視圖對象,是以在Kotlin中把備援的視圖入參給省略了,但是為了弄清楚按鈕事件的來龍去脈,還是有必要觀察一下它的本來面貌,接下來依次介紹按鈕事件的三種Kotlin編碼方式:匿名函數、内部類、接口實作。

1. 匿名函數方式

//點選事件第一種:匿名函數方式
        btn_test.setOnClickListener { v ->
            //Kotlin對變量進行類型轉換的關鍵字as
            toast("您點選了控件:${(v as Button).text}")
        }      

從上面的代碼可以得出,點選事件的函數代碼被符号“ ->” 分成兩部分:前一部分的“v” 表示發生了點選動作的視圖入參,其類型為View,後一部分則為處理點選事件的具體函數體代碼。此時的函數體代碼中還有兩個值得注意的地方:

(1)因為視圖View是基本的視圖類型,并不存在文本屬性,是以需要把這個視圖對象的變量類型轉換為按鈕Button,然後才能得到按鈕對象的文本,Kotlin中的類型轉換通過關鍵字as實作的,具體的轉換格式形如“待轉換的變量名稱 as 轉換後的類型名稱”。

(2)由于待顯示的字元串需要拼接按鈕文本,是以需要通過字元串模闆表達式"${***} "将按鈕文本置于該字元串。

2. 内部類方式

對于包含較多行代碼的事件處理,往往給它定義一個内部類,這樣該事件的處理代碼被完全封裝在内部類之中,能夠有效增強代碼的可讀性。下面給按鈕的點選和長按事件分别定義内部類,代碼如下:

package com.llw.kotlinstart

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.longToast
import org.jetbrains.anko.toast

class MainActivity : AppCompatActivity() {

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

        //點選事件第二種:内部類方式
        btn_test.setOnClickListener(MyClickListener())//點選
        btn_test.setOnLongClickListener(MyLongClickListener())//長按
    }
    
    //點選事件第二種:内部類方式,還記得inner嗎,内部類就是在class前面加上inner
    private inner class MyClickListener:View.OnClickListener{
        override fun onClick(v: View?) {
            toast("您點選了控件:${(v as Button).text}")
        }
    }
    
    private inner class MyLongClickListener:View.OnLongClickListener{
        override fun onLongClick(v: View): Boolean {
            longToast("您長按了控件:${(v as Button).text}")
            return true
        }
    }
    

}      

3. 接口實作方式

内部類方式固然使事件代碼更加靈活,可如果每個事件都定義新的内部類,要是某個頁面上有多個控件都需要監聽對應的事件處理,那頁面上的代碼就會很多,為了解決這個問題,第三種方式➖接口實作方式邊應運而生,該方式讓頁面的Activity類實作事件監聽器的接口,并重寫監聽器的接口方式,使得那些接口方法就像是Activity類的成員方法一樣,并且可以毫無障礙地通路該Activity類的所有成員屬性和成員方法。下面是示例代碼:

package com.llw.kotlinstart

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.longToast
import org.jetbrains.anko.toast

class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //點選事件第三種:Activity實作接口
        btn_test.setOnClickListener(this)
        btn_test.setOnLongClickListener(this)

    }

    //點選事件第三種:Activity實作接口
    override fun onClick(v: View) {
        if (v.id == R.id.btn_test) {
            toast("您點選了控件:${(v as Button).text}")
        }
    }

    override fun onLongClick(v: View): Boolean {
        if (v.id == R.id.btn_test) {
            longToast("您長按了控件:${(v as Button).text}")
        }
        return true
    }


}      

1.2 複選框CheckBox

複選框用于檢查有沒有選中的控件,隻有兩種情況,選中和未選中。也就是true和false,在學習複選框的用法之前,先了解一下複合按鈕CompoundButton的概念,在Android體系中,CompoundButton是抽象的複合按鈕,因為是抽象類,是以不能直接使用,而我們實際開發中用的是它的幾個派生類,如複選框CheckBox、單選按鈕RadioButton單選按鈕、Switch開關按鈕,這些派生類均可使用CompoundButton的屬性和方法。

在Java中,複合按鈕CompoundButton的勾選狀态有兩個,setChecked和isChecked,前者用于設定是否勾選,後者用于判斷是否勾選,但在Kotlin中這兩個方法被統一成了isChecked屬性,修改isChecked的屬性即為設定是否勾選,而擷取isChecked的屬性值即為判斷是否勾選,這種合二為一的情況還有一些,如下表:

按鈕控件的屬性說明 Kotlin的狀态屬性 Java的狀态擷取與設定方式
是否勾選 isChecked isChecked/setChecked
是否允許點選 isClickable isClickable/setClickable
是否可用 isEnabled isEnabled/setEnabled
是否獲得焦點 isFocusable isFocusable/setFocusable
是否按下 isPressed isPressed/setPressed
是否允許長按 isLongClickable isLongClickable/setLongClickable
是否選擇 isSelected isSelected/setSelected

下面來使用一下這個CheckBox:

布局代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:padding="20dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    
    <CheckBox
        android:id="@+id/ck_select"
        android:text="這是一個複選框"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_marginTop="20dp"
        android:textColor="#000"
        android:id="@+id/tv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
</LinearLayout>      

代碼

package com.llw.kotlinstart

import androidx.appcompat.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)

        ck_select.isChecked = false //預設未選中
        ck_select.setOnCheckedChangeListener { buttonView, isChecked ->
            tv_result.text = "您${if (isChecked) "勾選" else "取消勾選"}了複選框"
        }

    }

}      

運作效果圖:

Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用

有一說一,Android預設的控件顔色是真的辣眼睛。

1.3 單選按鈕RadioButton

單選按鈕要在一組按鈕中選擇其中一項,并且不能多選,這要求有個容器确定這組按鈕的範圍,這個容器便是單選組RadioGroup,單選組RadioGroup實質上是一個布局,同一組的RadioButton都要放在同一個RadioGroup節點之下,RadioGroup擁有orientation屬性,可指定下級控件的排列方向,該屬性為horizontal時,單選按鈕就在水準方向上排列,該屬性為vertical時,單選按鈕就在垂直方向上排列,并且RadioGroup下面除了RadioButton外,也可以挂載其他子控件,如TextView、ImageView等,這樣看來,它就是一個特殊的線性布局,隻不過多了一個管理單選按鈕的功能。

單選按鈕RadioButton預設是未選中狀态,點選它則顯示選中狀态,但是再次點選并不會取消選擇,隻有點選同組的其他單選按鈕,原來選中的單選按鈕才會被取消選中。另外,單選按鈕的選中時間一般不由RadioButton相應,而是由RadioGroup來響應。單選按鈕的選中事件在實作的時候,首先寫一個選中監聽器實作接口RadioGroup.OnCheckedChangeListener,然後調用RadioGroup對象的setOnCheckedChangeListener方法來注冊該監聽器。下面是使用示例:

布局代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:padding="20dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <TextView
        android:textColor="#000"
        android:text="請選擇您的性别"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <RadioGroup
        android:id="@+id/rg_sex"
        android:layout_marginTop="20dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <RadioButton
            android:id="@+id/rb_male"
            android:text="男"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>

        <RadioButton
            android:id="@+id/rb_female"
            android:text="女"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </RadioGroup>

    <TextView
        android:id="@+id/tv_sex"
        android:layout_marginTop="20dp"
        android:textColor="#000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>      

Activity中:

package com.llw.kotlinstart

import androidx.appcompat.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)

        rg_sex.setOnCheckedChangeListener { group, checkedId ->
            tv_sex.text = when (checkedId) {
                R.id.rb_male -> "靓仔啊"
                R.id.rb_female -> "靓女啊"
                else -> ""
            }
        }
    }

}      

運作效果圖:

Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用

1.4 開關按鈕Switch

這個Switch其實和就是true和false的控制,就不過多的啰嗦了,布局代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:padding="20dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <TextView
        android:textColor="#000"
        android:text="請選擇開關"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <Switch
        android:id="@+id/switch_open"
        android:layout_marginTop="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    

    <TextView
        android:id="@+id/tv_switch"
        android:layout_marginTop="20dp"
        android:textColor="#000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>      

Activity代碼中:

package com.llw.kotlinstart

import androidx.appcompat.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)

        switch_open.setOnCheckedChangeListener { buttonView, isChecked ->
            tv_switch.text = if (isChecked) "打開 開關" else "關閉 開關"
        }
    }

}      

運作效果圖:

Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用

1.5 文本視圖TextView

有沒有人覺得TextView很簡單呢?但實際并不簡單,比如常見的文字跑馬燈效果,一行文本的内容太多,導緻無法完全顯示,但也不想分行顯示,于是就有這個跑馬燈效果了。

下面用代碼來展示一下吧:

布局代碼:

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

    <TextView
        android:textSize="14sp"
        android:padding="10dp"
        android:text="跑馬燈效果,點選暫停,再點選恢複"
        android:layout_width="match_parent"
        android:gravity="center_horizontal"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_marginTop="20dp"
        android:id="@+id/tv_marquee"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:textSize="18sp"
        android:textColor="#000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>      

Activity代碼:

package com.llw.kotlinstart

import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.above
import org.jetbrains.anko.alignParentLeft
import org.jetbrains.anko.dip

class MainActivity : AppCompatActivity() {

    private var bPause = false

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

        tv_marquee.text = "富強   民主   文明   和諧   自由   平等   公正   法治" +
                "   愛國   敬業   誠信   友善"
        tv_marquee.gravity = Gravity.LEFT or Gravity.CENTER
        tv_marquee.ellipsize = TextUtils.TruncateAt.MARQUEE//從右往左滾動的跑馬燈
        tv_marquee.setSingleLine(true)//單行顯示
        tv_marquee.setOnClickListener {
            bPause = !bPause
            tv_marquee.isFocusable = if(bPause) false else true
            tv_marquee.isFocusableInTouchMode = if(bPause) false else true
        }

    }





}      

運作效果圖:

Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用

剛才注意到這樣一行代碼:

tv_marquee.gravity = Gravity.LEFT or Gravity.CENTER      

在Java中是

tv_marquee.gravity = Gravity.LEFT | Gravity.CENTER      

這是位運算符的差別

1.6 圖像視圖ImageView

圖像視圖是另一種常用的基本控件。圖像視圖ImageView在代碼中調用的方法說明如下:

  • setImageDrawable : 設定圖形的Drawable對象。
  • setImageResource : 設定圖形的資源ID。
  • setImageBitmap : 設定圖形的位圖對象。
  • setScaleType : 設定圖形的拉伸類型,在Kotlin中可直接給屬性scaleType指派,如下表所示:
scaleType類的拉伸類型 說明
ScaleType.FIT_XY 拉伸圖檔使之正好填滿視圖(圖檔可能被拉伸變形)
ScaleType.FIT_START 拉伸圖檔使之位于視圖上部
ScaleType.FIT_CENTER 拉伸圖檔使之位于視圖中間
ScaleType.FIT_END 拉伸圖檔使之位于視圖下部
ScaleType.CENTER 保持圖檔原尺寸,并使之位于視圖中間
ScaleType.CENTER_CROP 拉伸圖檔使之充滿視圖,并位于視圖中間
ScaleType.CENTER_INSIDE 使圖檔位于視圖中間(隻壓不拉),當圖檔尺寸大于視圖時,centerInside等同于fitCenter:當圖檔尺寸小于視圖時,centerInside等同于center

然後代碼來示範一遍

布局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv_img"
        android:layout_width="300dp"
        android:layout_height="300dp"/>

    <TextView
        android:layout_marginTop="20dp"
        android:id="@+id/tv_info"
        android:text="原圖"
        android:textColor="#000"
        android:textSize="18sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <LinearLayout
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_center"
            android:text="Center"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_fit_center"
            android:text="Fit Center"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_center_crop"
            android:text="Center Crop"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_center_inside"
            android:text="Center Inside"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <LinearLayout

        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_fit_xy"
            android:text="Fit XY"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_fit_start"
            android:text="Fit Start"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_fit_end"
            android:text="Fit End"
            android:textAllCaps="false"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>      

Activity代碼

package com.llw.kotlindemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        iv_img.setImageResource(R.mipmap.logo)//代碼中設定圖檔

        //按鈕控制圖檔展示方式
        btn_center.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.CENTER;tv_info.text = "CENTER" }

        btn_fit_center.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.FIT_CENTER;tv_info.text = "FIT_CENTER" }

        btn_center_crop.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.CENTER_CROP;tv_info.text = "CENTER_CROP" }

        btn_center_inside.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.CENTER_INSIDE;tv_info.text = "CENTER_INSIDE" }

        btn_fit_xy.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.FIT_XY;tv_info.text = "FIT_XY" }

        btn_fit_start.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.FIT_START;tv_info.text = "FIT_START" }

        btn_fit_end.setOnClickListener { iv_img.scaleType = ImageView.ScaleType.FIT_END;tv_info.text = "FIT_END" }
    }
}      

運作效果:

這裡我選了幾張又代表性的

Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用
Kotlin學習日志(六)控件使用

當然這些效果你也可以直接在布局檔案中寫好

Kotlin學習日志(六)控件使用

這裡設定也是一樣的效果。

1.7 文本編輯框EditText

檔案編輯框通俗的說就是輸入框,在實際的開發中應用廣泛,基本每一個APP都會有,常見的在一些登入、注冊、個人資訊編輯的地方使用,EditText是可以限制使用者的輸入方式的,比如手機号,就限制你隻能輸入數字,并且點選之後彈出數字鍵盤,而不是預設的文字鍵盤。通過setInputType方法,可以過濾合法的輸入字元,隻有符合輸入類型的字元,才允許接收并顯示出來,而Kotlin可以直接給inputType屬性設定輸入類型,進而取代setInputType的方法調用,這裡用一個表來進行說明:

InputType類的輸入類型 說明
InputType.TYPE_CLASS_TEXT 所有文本
InputType.TYPE_CLASS_NUMBER 隻能是數字
InputType.TYPE_CLASS_DATETIME 隻能是日期時間
InputType.TYPE_CLASS_VARIATION_NORMAL 正常顯示
InputType.TYPE_CLASS_VARIATION_PASSWORD 密文顯示
InputType.TYPE_CLASS_VARIATION_VISIBLE_PASSWORD 明文顯示

實際的業務邏輯操作中,很多是在輸入的過程中對輸入值進行判斷,對于輸入時的控制通過文本觀察器TextWatcher,它可以實時監控使用者的輸入字元,并且支援在輸入每個字元時由開發者進行手工幹預,進而實作随時校驗,随時加工的功能。下面用代碼來示範一下:

布局檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/et_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>


    <TextView
        android:layout_marginTop="20dp"
        android:id="@+id/tv_phone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>      

使用代碼

package com.llw.kotlindemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.widget.ImageView
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        //EditText的控件指派不能像TextView那樣,通過text來進行指派
        //否則會報錯Editable與String類型不比對,隻能調用setText方法對EditText控件設定文本
        et_phone.setText("")
        //顯示明文數字
        et_phone.inputType = InputType.TYPE_CLASS_NUMBER
        //顯示明文密碼
        //et_phone.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
        //隐藏密碼
        //et_phone.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD

        //給輸入框添加文本變化監聽器
        et_phone.addTextChangedListener(EditWatcher())
    }

    private inner class EditWatcher: TextWatcher{
        //輸入之前
        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, before: Int) {}
        //輸入中
        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
        //輸入之後
        override fun afterTextChanged(s: Editable) {
            var str = s.toString()//擷取輸入之後的文本
            if(str.indexOf("\r") >= 0 || str.indexOf("\n") >= 0){
                //去掉回車符和換行符  将回車符和換行符都替換成 "" 空字元串
                str = str.replace("\r","").replace("\n","")
            }
            if (str.length >= 11){
                tv_phone.text = "您輸入的手機号碼是:$str"
            }
        }


    }
}      

運作效果圖:

輸入未到11位

Kotlin學習日志(六)控件使用

到11位或者大于11位