iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 24
0
自我挑戰組

Kotlin Everyday:新手寫程式踩的坑系列 第 24

Day 24 ─用 Kotlin 做待辦清單 Todolist(7) 刪除 Sharepreference 資料 (下)

  • 分享至 

  • xImage
  •  

今天練習的主軸,就是要來完成右上角垃圾桶的設定,關於這個小小的 UI 元件,其實還滿多事情要來做的:

  • 垃圾桶預設不可被點擊(enable = false),呈現深灰色
  • 勾選 CheckBox 後讓垃圾桶可以被點擊(enable = true),呈現白色
  • 按下白色垃圾桶,會移除 CheckBox 被勾選的資料
  • 是從 Sharepreference 整筆移除,不是只有畫面移除

一、設定垃圾桶顏色

垃圾桶的顏色會隨著 enable 狀態改變,呈現白色時可以被點擊(enable = true),呈現灰色時不可被點擊觸發事件(enable = false),這種狀態變動的呈現,可以使用 selector 狀態選擇器 來做,細節參考這裡

  1. 首先在 res 增加一個 color 資料夾

  2. 使用文章提及的第一種方法「以 xml 方式寫 selector」,加入一個 xml 檔案

  3. 這次用到的狀態是 state_enabled,使用方式就是「改變項目+依據狀態」(color + enable)

android:state_enabled
设置触摸或点击事件是否可用状态,一般只在false时设置该属性,表示不可用状态

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#FFFFFF" android:state_enabled="true" />
<item android:color="#444444" android:state_enabled="false" />
</selector>

可以直接從紅色框框處看到設定的顏色

  1. 將這個 selector 指給垃圾筒的 icon,記住不是在 Menu Item 設定,而是直接去 res/drawable/icon.xml 對 ImageView 上色渲染,可參考利用 Tint 属性优化 Selector

二、勾選 CheckBox 會改變垃圾桶 enable 狀態

現在可以看到垃圾桶顏色變成灰色,因為預設就是 enable=false,現在要做的就是勾選資料 CheckBox 的同時,要讓垃圾桶變成白色,也就是 enable=true

  1. 怎麼拿到 Menu Item
    這邊有個小麻煩的點是,垃圾桶屬於 Menu Item,想一下,怎樣才能把它拿到外部使用,先宣告一個性質為 MenuItem 的 itemDelete,讓它後面才賦值
  lateinit var itemDelete: MenuItem
  1. 賦值 itemDelete
    在創建菜單的 onCreateOptionsMenu(menu: Menu?) 方法中,可以透過 findItem 來獲取具體的 Item,在這裡我們可以賦值 itemDelete,這樣從外面就可以取得
  itemDelete = menu!!.findItem(R.id.menu_delete)
  1. 設定函式 SelectEvent,改變垃圾桶 enable 狀態
    當資料的 CheckBox 被點擊時,垃圾桶狀態 itemDelete.isEnabled,因為沒有限定是哪一筆資料的 CheckBox 被點擊,所以使用陣列方法 list.find() 來檢查:
  itemDelete.isEnabled = things.find { it.isSelected }?.isSelected ?: false
  • it 指的是陣列裡的資料,即 ArrayList 裡面的 Thing
  • 只要有在陣列裡找到符合條件(isSelected=true)的資料,就回傳
  • 當這個資料狀態.isSelected 時,垃圾桶狀態就是.isEnabled
  • 這裡注意:之前在 Adapter 裡面我們已經將「畫面點選」和「資料狀態」連結起來
  chk_delete.isChecked = thing.isSelected   //(Adapter.kt)

如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式,注意仅当左侧为空时,才会对右侧表达式求值

三、刪除 Sharepreference 資料

要修改 SharedPreferences 裡面的資料,跟新增一樣需要取得 editor 物件,也只有讀取資料才用不到 Editor:

  1. 取得或建立一個 SharedPreferences
  2. .edit() 取得 Editor 物件
  3. 移除資料方法 remove(key值)
  4. 不要忘記 apply() 執行

onOptionsItemSelected(item: MenuItem) 裡面對垃圾桶做點擊事件:

  • 使用陣列方法 list.filter() 找出被點選的資料
  val deleteList = things.filter { it.isSelected }

filter() 和 find() 很像,但後者只會回傳第一次為 true 的值,而 filter() 會回傳一個陣列,即為 true 的值們,這裡回傳的東西是 List,filter() 這個方法很適合用在搜尋符合條件的資料們

  • 使用陣列方法 list.forEach() 執行刪除程序
deleteList.forEach { editor.remove(it.key) }

接下來,使用 Key 值來移除每一項資料,forEach() 不會額外回傳值,只單純執行每個陣列內的物件或值,用法類似 for 迴圈、只是更為簡單,做完之後記得讓 .apply() 執行,還要讓垃圾桶可點選按鈕重回預設值

→ 關於陣列處理的技巧,延伸參考 JavaScript 陣列處理方法

when(item.itemId){
    R.id.menu_delete ->{
        val editor = getSharedPreferences("save", Activity.MODE_PRIVATE).edit()
        val deleteList = things.filter { it.isSelected }
        deleteList.forEach { editor.remove(it.key) }
        editor.apply()
        itemDelete.isEnabled = false
        getEvent()
    }
}

這樣就做完刪除功能的設定囉~


上一篇
Day 23 ─用 Kotlin 做待辦清單 Todolist(6) 刪除 Sharepreference 資料 (上)
下一篇
Day 25 ─用 Kotlin 做待辦清單 Todolist(8) DatePickerDialog 及新增資料屬性(上)
系列文
Kotlin Everyday:新手寫程式踩的坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言