情境
如果要使用一個勾選方塊,可以使用 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 操作了。