如何使用CheckBox(kotlin)

如何使用CheckBox(kotlin)

情境

如果要使用一個勾選方塊,可以使用 CheckBox 這個元件,它會出現一個選取方塊讓使用者來進行勾選,一般來說它會是多選的模式,如果你想要用單選的方式來進行選取,那麼建議是使用 RadioButton 會比較恰當。

程式碼說明

方法一

如果你要在程式內宣告可以直接這樣寫。

  • Java 程式內宣告表示
class MainActivity : AppCompatActivity() {  
  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
        val checkBox = CheckBox(this)  
        checkBox.text = "是否為程式設計師?"  
  container.addView(checkBox)  
    }  
}

如下圖所示


但是會有缺點就是管理不便而且維護困難,所以一般都會宣告在 xml 上面。

方法二

  • XML內宣告表示
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.givemepass.checkboxdemo.MainActivity">

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為程式設計師?" />
</RelativeLayout>

如下圖所示。


方法一跟方法二效果會是一樣,而文字設定完了會顯示在右邊。

設定事件

CheckBox要怎麼指定它的事件呢?

事件方法一

如果你想要設定事件,你可以在 xml 上面設定事件。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.givemepass.checkboxdemo.MainActivity">

    <CheckBox
        android:id="@+id/checkbox"
        android:onClick="clickEvent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為程式設計師?" />
</RelativeLayout>

接著在 MainActivity.java 內指定好這個事件。

  class MainActivity : AppCompatActivity() {  
  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
    }  
  
    fun clickEvent(view: View) {  
        val checkBox = view as CheckBox  
 Toast.makeText(this@MainActivity, checkBox.isChecked.toString() + "", Toast.LENGTH_SHORT).show()  
    }  
}

這邊有三個重點要注意, 如果你想在xml設定好事件,那麼就一定要遵守以下這些規範。

  • 方法回傳值一定 void
  • 串入的參數一定要是 View
  • 方法一定要是 public

這樣就可以完成一個事件的設定了。
如下圖所示。


但是這樣其實不好追蹤,比較好的做法會是先從 xml 宣告好一個元件,再從程式內取出元件的物件,接著定義事件,讓它跟元件進行連結。

事件方法二

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.givemepass.checkboxdemo.MainActivity">

    <CheckBox
        android:id="@+id/check_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為程式設計師?" />
</RelativeLayout>

接著透過程式內對元件進行事件的連結。

class MainActivity : AppCompatActivity() {  
 override fun onCreate(savedInstanceState: Bundle?) {  
     super.onCreate(savedInstanceState)  
     setContentView(R.layout.activity_main)  
     check_box.setOnCheckedChangeListener { _, isChecked ->  
   Toast.makeText(this@MainActivity, isChecked.toString() + "", Toast.LENGTH_SHORT).show()  
  }  
 }  
}

基本上跟在 xml 設定效果是一樣的,如下圖所示。


事件方法三

假設現在 CheckBox 元件有多個,每一個元件都要綁定一個事件,那麼程式碼重複的地方就會變很多,因此,你可以透過同一個事件內進行 ID 的判斷的方法來處理。
首先宣告兩個 CheckBox 在 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:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.givemepass.checkboxdemo.MainActivity">

    <CheckBox
        android:id="@+id/check_box1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為程式設計師?" />
    <CheckBox
        android:id="@+id/check_box2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為男性?" />
</LinearLayout>

接著在 MainActivity.java 內綁定事件,透過宣告出來的 CompoundButton.OnCheckedChangeListener 事件介面實作,將它跟所有的 CheckBox 元件進行綁定,由傳入的第一個參數 CompoundButton 來取得 ID 進行辨認使用者按下哪個 CheckBox,就可以做出所對應的事件了。

class MainActivity : AppCompatActivity(){  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
        check_box1.setOnCheckedChangeListener(mOnCheckedChangeListener)  
        check_box2.setOnCheckedChangeListener(mOnCheckedChangeListener)  
    }  
    private val mOnCheckedChangeListener = CompoundButton.OnCheckedChangeListener{  
   buttonView, isChecked->  
    when(buttonView.id){  
           R.id.check_box1 -> {  
               if (isChecked) {  
                   Toast.makeText(this@MainActivity, "你是程式設計師", Toast.LENGTH_SHORT).show()  
               } else {  
                   Toast.makeText(this@MainActivity, "你不是程式設計師", Toast.LENGTH_SHORT).show()  
               }  
           }  
           R.id.check_box2 -> {  
               if (isChecked) {  
                   Toast.makeText(this@MainActivity, "你是男性", Toast.LENGTH_SHORT).show()  
               } else {  
                   Toast.makeText(this@MainActivity, "你是女性", Toast.LENGTH_SHORT).show()  
               }  
           }  
        }  
    }   
}

如下圖所示。


Style 替換

有時候你會想要把 CheckBox 換成自己想要的樣式,所以你就會這樣寫。

<?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:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.givemepass.checkboxdemo.MainActivity">

    <CheckBox
        android:background="@android:drawable/checkbox_off_background"
        android:id="@+id/check_box1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為程式設計師?" />
</LinearLayout>

在 AndroidSDK\platforms\android-24\data\res\drawable-hdpi 資料夾之下,會有許多預設圖示提供你使用。


透過 Background 來替換,這邊我們利用預設的 Icon 來進行更換,如下圖所示。


執行一下怎麼怪怪的?


原來在設定 CheckBox 的時候,是不能使用 android:background 這個屬性的,要改用 android:button 這個屬性。


看起來正常多了,可是你會發現怎麼無法勾選了?
原來我們把原本的 Button 換掉,Android 內建綁定一個 selector 就被蓋掉
導致原本勾選的效果就這樣消失了,那怎麼辦呢?
沒關係自己的 selector 自己寫,首先, 前面已經有了非勾選的 Icon,再把勾選的 Icon 找出來。


然後開啟res/drawable/點選右鍵選擇新增Drawable resource file,如下圖。


接著產生一個check_box_style.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="false" android:drawable="@android:drawable/checkbox_off_background" />
    <item android:state_checked="true" android:drawable="@android:drawable/checkbox_on_background" />
</selector>

裡面指定了 checked 跟 uncheck 所要顯示的 icon,接著在將它指定給 CheckBox。

<?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:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.givemepass.checkboxdemo.MainActivity">

    <CheckBox
        android:button="@android:drawable/check_box_style"
        android:id="@+id/check_box1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="是否為程式設計師?" />
</LinearLayout>

執行 build 就可以看到我們自定的 CheckBox 可以被勾選了。


這樣就是一個簡單的 CheckBox 操作了。