New feature: use Bottom Sheet to manage tasks

This commit is contained in:
Super12138 2024-06-09 12:17:55 +08:00
parent 11b8320774
commit 238856f403
14 changed files with 489 additions and 253 deletions

View file

@ -17,7 +17,10 @@ object Constants {
const val STRING_DEV_MODE = "/DEV_MODE" const val STRING_DEV_MODE = "/DEV_MODE"
const val TAG_INFO_BOTTOM_SHEET = "InfoBottomSheet" const val TAG_INFO_BOTTOM_SHEET = "InfoBottomSheet"
const val TAG_TODO_BOTTOM_SHEET = "ToDoBottomSheet"
const val BUNDLE_EDIT_MODE = "editMode"
const val BUNDLE_POSITION = "todoPosition"
const val BUNDLE_TODO_CONTENT = "todoContent" const val BUNDLE_TODO_CONTENT = "todoContent"
const val BUNDLE_TODO_SUBJECT = "todoSubject" const val BUNDLE_TODO_SUBJECT = "todoSubject"
const val BUNDLE_TODO_STATE = "todoState" const val BUNDLE_TODO_STATE = "todoState"

View file

@ -78,4 +78,10 @@ object Repository {
todoDao.updateStateByUUID(uuid) todoDao.updateStateByUUID(uuid)
} }
} }
suspend fun update(toDoRoom: ToDoRoom) {
withContext(Dispatchers.IO) {
todoDao.update(toDoRoom)
}
}
} }

View file

@ -3,6 +3,7 @@ package cn.super12138.todo.logic.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update
@Dao @Dao
interface ToDoRoomDao { interface ToDoRoomDao {
@ -26,4 +27,7 @@ interface ToDoRoomDao {
@Query("UPDATE todo SET state = 1 WHERE uuid = :uuid") @Query("UPDATE todo SET state = 1 WHERE uuid = :uuid")
suspend fun updateStateByUUID(uuid: String) suspend fun updateStateByUUID(uuid: String)
@Update
suspend fun update(toDoRoom: ToDoRoom)
} }

View file

@ -0,0 +1,47 @@
package cn.super12138.todo.utils
import android.text.Editable
import cn.super12138.todo.R
import cn.super12138.todo.ToDoApp
object TextUtils {
private val subjectMap = mapOf(
globalGetString(R.string.subject_chinese) to R.id.subject_chinese,
globalGetString(R.string.subject_math) to R.id.subject_math,
globalGetString(R.string.subject_english) to R.id.subject_english,
globalGetString(R.string.subject_biology) to R.id.subject_biology,
globalGetString(R.string.subject_geography) to R.id.subject_geography,
globalGetString(R.string.subject_history) to R.id.subject_history,
globalGetString(R.string.subject_physics) to R.id.subject_physics,
globalGetString(R.string.subject_law) to R.id.subject_law,
globalGetString(R.string.subject_other) to R.id.subject_other
)
fun getSubjectName(id: Int): String {
return when (id) {
R.id.subject_chinese -> globalGetString(R.string.subject_chinese)
R.id.subject_math -> globalGetString(R.string.subject_math)
R.id.subject_english -> globalGetString(R.string.subject_english)
R.id.subject_biology -> globalGetString(R.string.subject_biology)
R.id.subject_geography -> globalGetString(R.string.subject_geography)
R.id.subject_history -> globalGetString(R.string.subject_history)
R.id.subject_physics -> globalGetString(R.string.subject_physics)
R.id.subject_law -> globalGetString(R.string.subject_law)
R.id.subject_other -> globalGetString(R.string.subject_other)
else -> globalGetString(R.string.subject_unknown)
}
}
fun getSubjectID(name: String): Int? {
return subjectMap[name]
}
}
fun globalGetString(resID: Int): String {
return ToDoApp.context.resources.getString(resID)
}
fun String.toEditable(): Editable? {
return Editable.Factory.getInstance().newEditable(this)
}

View file

@ -0,0 +1,184 @@
package cn.super12138.todo.views.bottomsheet
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import cn.super12138.todo.R
import cn.super12138.todo.constant.Constants
import cn.super12138.todo.constant.GlobalValues
import cn.super12138.todo.databinding.BottomSheetTodoBinding
import cn.super12138.todo.logic.dao.ToDoRoom
import cn.super12138.todo.logic.model.ToDo
import cn.super12138.todo.utils.TextUtils
import cn.super12138.todo.utils.showToast
import cn.super12138.todo.utils.toEditable
import cn.super12138.todo.views.progress.ProgressFragmentViewModel
import cn.super12138.todo.views.todo.ToDoFragmentViewModel
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import java.util.UUID
class ToDoBottomSheet : BottomSheetDialogFragment() {
private lateinit var binding: BottomSheetTodoBinding
private val progressViewModel: ProgressFragmentViewModel by viewModels({ requireActivity() })
private val todoViewModel: ToDoFragmentViewModel by viewModels({ requireActivity() })
private var editMode: Boolean = false
private var todoState: Int = 0
private var todoPosition: Int = 0
private lateinit var todoUUID: String
private lateinit var todoOrigSubject: String
private lateinit var todoOrigContent: String
companion object {
const val TAG = Constants.TAG_TODO_BOTTOM_SHEET
fun newInstance(
editMode: Boolean,
todoPosition: Int,
todoUUID: String,
todoState: Int,
todoSubject: String,
todoContent: String,
) = ToDoBottomSheet().apply {
arguments = Bundle().apply {
putBoolean(Constants.BUNDLE_EDIT_MODE, editMode)
putInt(Constants.BUNDLE_POSITION, todoPosition)
putString(Constants.BUNDLE_TODO_UUID, todoUUID)
putInt(Constants.BUNDLE_TODO_STATE, todoState)
putString(Constants.BUNDLE_TODO_SUBJECT, todoSubject)
putString(Constants.BUNDLE_TODO_CONTENT, todoContent)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
editMode = it.getBoolean(Constants.BUNDLE_EDIT_MODE, false)
todoPosition = it.getInt(Constants.BUNDLE_POSITION, 0)
todoOrigContent = it.getString(Constants.BUNDLE_TODO_CONTENT, "")
todoOrigSubject = it.getString(Constants.BUNDLE_TODO_SUBJECT, "")
todoState = it.getInt(Constants.BUNDLE_TODO_STATE, 0)
todoUUID = it.getString(Constants.BUNDLE_TODO_UUID, "")
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = BottomSheetTodoBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// BottomSheet 基本参数设置
val bottomSheetDialog = dialog as BottomSheetDialog
bottomSheetDialog.behavior.apply {
state = BottomSheetBehavior.STATE_EXPANDED
saveFlags = BottomSheetBehavior.SAVE_ALL
}
bottomSheetDialog.dismissWithAnimation = true
val todoList = todoViewModel.todoList
// 编辑模式
if (editMode) {
binding.btnCancel.visibility = View.GONE
binding.btnDelete.visibility = View.VISIBLE
binding.todoSheetTitle.text = getString(R.string.update_task)
binding.todoContent.editText?.text = todoOrigContent.toEditable()
binding.btnSave.text = getString(R.string.update)
TextUtils.getSubjectID(todoOrigSubject)?.let { binding.todoSubject.check(it) }
}
binding.btnSave.setOnClickListener {
val todoContent = binding.todoContent.editText?.text.toString()
// 内容判空
if (todoContent.isEmpty()) {
binding.todoContent.error =
getString(R.string.content_cannot_be_empty)
return@setOnClickListener
} else {
// 开发者模式
if (todoContent == Constants.STRING_DEV_MODE) {
if (GlobalValues.devMode) {
GlobalValues.devMode = false
} else {
GlobalValues.devMode = true
"Dev Mode".showToast()
}
} else {
// 随机 UUID
val randomUUID = UUID.randomUUID().toString()
// 待办学科
val todoSubject = TextUtils.getSubjectName(binding.todoSubject.checkedChipId)
// 更新待办
if (editMode) {
todoViewModel.updateTask(
todoPosition,
ToDoRoom(
todoUUID,
todoState,
todoSubject,
todoContent
)
)
todoViewModel.refreshData.value = 1
} else {
// 添加到 RecyclerView
if (todoList.size + 1 > 0) {
todoViewModel.emptyTipVis.value = View.GONE
}
todoList.add(
ToDo(randomUUID, 0, todoContent, todoSubject)
)
// 插入数据库
todoViewModel.insertTask(
ToDoRoom(
randomUUID,
0,
todoSubject,
todoContent
)
)
progressViewModel.updateProgress()
todoViewModel.addData.value = 1
}
}
}
dismiss()
}
binding.btnCancel.setOnClickListener {
dismiss()
}
binding.btnDelete.setOnClickListener {
todoViewModel.deleteTask(todoPosition, todoUUID)
progressViewModel.updateProgress()
todoViewModel.removeData.value = 1
// 空项目提示显示判断
if (todoList.isEmpty()) {
todoViewModel.emptyTipVis.value = View.VISIBLE
} else {
todoViewModel.emptyTipVis.value = View.GONE
}
dismiss()
}
}
}

View file

@ -6,18 +6,21 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.ViewModelStoreOwner
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import cn.super12138.todo.R import cn.super12138.todo.R
import cn.super12138.todo.logic.dao.ToDoRoom import cn.super12138.todo.constant.GlobalValues
import cn.super12138.todo.logic.model.ToDo import cn.super12138.todo.logic.model.ToDo
import cn.super12138.todo.utils.showToast
import cn.super12138.todo.views.bottomsheet.ToDoBottomSheet
import cn.super12138.todo.views.progress.ProgressFragmentViewModel import cn.super12138.todo.views.progress.ProgressFragmentViewModel
import com.google.android.material.snackbar.Snackbar
class ToDoAdapter( class ToDoAdapter(
private val todoList: MutableList<ToDo>, private val todoList: MutableList<ToDo>,
private val viewModelStoreOwner: ViewModelStoreOwner private val viewModelStoreOwner: ViewModelStoreOwner,
private val fragmentManager: FragmentManager
) : ) :
RecyclerView.Adapter<ToDoAdapter.ViewHolder>() { RecyclerView.Adapter<ToDoAdapter.ViewHolder>() {
@ -25,7 +28,7 @@ class ToDoAdapter(
val todoContext: TextView = view.findViewById(R.id.todo_content) val todoContext: TextView = view.findViewById(R.id.todo_content)
val todoSubject: TextView = view.findViewById(R.id.todo_subject) val todoSubject: TextView = view.findViewById(R.id.todo_subject)
val checkToDoBtn: Button = view.findViewById(R.id.check_item_btn) val checkToDoBtn: Button = view.findViewById(R.id.check_item_btn)
val delToDoBtn: Button = view.findViewById(R.id.delete_item_btn) // val delToDoBtn: Button = view.findViewById(R.id.delete_item_btn)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -60,7 +63,7 @@ class ToDoAdapter(
notifyItemRemoved(position) notifyItemRemoved(position)
notifyItemRangeChanged(position, todoList.size) notifyItemRangeChanged(position, todoList.size)
todoViewModel.updateTask(todo.uuid) todoViewModel.updateTaskState(todo.uuid)
// 设置空项目提示可见性 // 设置空项目提示可见性
if (todoList.isEmpty()) { if (todoList.isEmpty()) {
@ -71,47 +74,23 @@ class ToDoAdapter(
progressViewModel.updateProgress() progressViewModel.updateProgress()
} }
holder.delToDoBtn.setOnClickListener { holder.itemView.setOnClickListener {
it.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) if (GlobalValues.devMode) {
if (position < 0 || position >= todoList.size) { "Current position: $position".showToast()
return@setOnClickListener
} }
}
todoList.removeAt(position) holder.itemView.setOnLongClickListener {
notifyItemRemoved(position) val toDoBottomSheet = ToDoBottomSheet.newInstance(
notifyItemRangeChanged(position, todoList.size) true,
position,
todoViewModel.deleteTask(todo.uuid) todo.uuid,
todo.state,
// 设置空项目提示可见性 todo.subject,
if (todoList.isEmpty()) { todo.content
todoViewModel.emptyTipVis.value = View.VISIBLE )
} else { toDoBottomSheet.show(fragmentManager, ToDoBottomSheet.TAG)
todoViewModel.emptyTipVis.value = View.GONE true
}
progressViewModel.updateProgress()
Snackbar.make(it, R.string.task_deleted, Snackbar.LENGTH_LONG)
.setAction(R.string.delete_undo) {
if (todoList.size + 1 > 0) {
todoViewModel.emptyTipVis.value = View.GONE
}
todoList.add(ToDo(todo.uuid, 0, todo.content, todo.subject))
todoViewModel.insertTask(
ToDoRoom(
todo.uuid,
0,
todo.subject,
todo.content
)
)
todoViewModel.refreshData.value = 1
progressViewModel.updateProgress()
}
.show()
} }
} }

View file

@ -5,7 +5,6 @@ import android.view.HapticFeedbackConstants
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
@ -14,25 +13,18 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import cn.super12138.todo.R import cn.super12138.todo.R
import cn.super12138.todo.ToDoApp import cn.super12138.todo.ToDoApp
import cn.super12138.todo.constant.Constants
import cn.super12138.todo.constant.GlobalValues
import cn.super12138.todo.databinding.DialogAddTodoBinding
import cn.super12138.todo.databinding.FragmentTodoBinding import cn.super12138.todo.databinding.FragmentTodoBinding
import cn.super12138.todo.logic.Repository import cn.super12138.todo.logic.Repository
import cn.super12138.todo.logic.dao.ToDoRoom import cn.super12138.todo.views.bottomsheet.ToDoBottomSheet
import cn.super12138.todo.logic.model.ToDo
import cn.super12138.todo.utils.showToast
import cn.super12138.todo.views.progress.ProgressFragmentViewModel import cn.super12138.todo.views.progress.ProgressFragmentViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.zhanghai.android.fastscroll.FastScrollerBuilder import me.zhanghai.android.fastscroll.FastScrollerBuilder
import java.util.UUID
class ToDoFragment : Fragment() { class ToDoFragment : Fragment() {
private val progressViewModel: ProgressFragmentViewModel by viewModels({ requireActivity() }) private val progressViewModel: ProgressFragmentViewModel by viewModels({ requireActivity() })
private val todoViewModel: ToDoFragmentViewModel by viewModels({ requireActivity() }) private val todoViewModel: ToDoFragmentViewModel by viewModels({ requireActivity() })
private lateinit var binding: FragmentTodoBinding private lateinit var binding: FragmentTodoBinding
private lateinit var toDoDialogBinding: DialogAddTodoBinding
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -60,7 +52,7 @@ class ToDoFragment : Fragment() {
val layoutManager = LinearLayoutManager(ToDoApp.context) val layoutManager = LinearLayoutManager(ToDoApp.context)
binding.todoList.layoutManager = layoutManager binding.todoList.layoutManager = layoutManager
val adapter = ToDoAdapter(todoList, requireActivity()) val adapter = ToDoAdapter(todoList, requireActivity(), parentFragmentManager)
binding.todoList.adapter = adapter binding.todoList.adapter = adapter
FastScrollerBuilder(binding.todoList).apply { FastScrollerBuilder(binding.todoList).apply {
@ -74,76 +66,8 @@ class ToDoFragment : Fragment() {
binding.addItem.setOnClickListener { binding.addItem.setOnClickListener {
it.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) it.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
toDoDialogBinding = DialogAddTodoBinding.inflate(layoutInflater) val toDoBottomSheet = ToDoBottomSheet()
toDoBottomSheet.show(parentFragmentManager, ToDoBottomSheet.TAG)
activity?.let { it1 ->
val dialog = MaterialAlertDialogBuilder(it1)
.setTitle(R.string.add_task)
.setView(toDoDialogBinding.root)
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setCancelable(false)
.show()
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val todoContent = toDoDialogBinding.todoContent.editText?.text.toString()
if (todoContent.isEmpty()) {
toDoDialogBinding.todoContent.error =
getString(R.string.content_cannot_be_empty)
} else {
if (todoContent == Constants.STRING_DEV_MODE) {
if (GlobalValues.devMode) {
GlobalValues.devMode = false
} else {
GlobalValues.devMode = true
"Dev Mode".showToast()
}
dialog.dismiss()
} else {
// 随机UUID
val randomUUID = UUID.randomUUID().toString()
// 待办学科
val todoSubject = when (toDoDialogBinding.todoSubject.checkedChipId) {
R.id.subject_chinese -> getString(R.string.subject_chinese)
R.id.subject_math -> getString(R.string.subject_math)
R.id.subject_english -> getString(R.string.subject_english)
R.id.subject_biology -> getString(R.string.subject_biology)
R.id.subject_geography -> getString(R.string.subject_geography)
R.id.subject_history -> getString(R.string.subject_history)
R.id.subject_physics -> getString(R.string.subject_physics)
R.id.subject_law -> getString(R.string.subject_law)
R.id.subject_other -> getString(R.string.subject_other)
else -> getString(R.string.subject_unknown)
}
// 显示RecyclerView
if (todoList.size + 1 > 0) {
todoViewModel.emptyTipVis.value = View.GONE
}
// 添加到RecyclerView
todoList.add(
ToDo(randomUUID, 0, todoContent, todoSubject)
)
// 插入数据库
lifecycleScope.launch {
Repository.insert(
ToDoRoom(
randomUUID,
0,
todoSubject,
todoContent
)
)
progressViewModel.updateProgress()
}
binding.todoList.adapter?.notifyItemInserted(todoList.size + 1)
dialog.dismiss()
}
}
}
}
} }
binding.addItem.setOnLongClickListener { binding.addItem.setOnLongClickListener {
@ -208,8 +132,16 @@ class ToDoFragment : Fragment() {
} }
}) })
todoViewModel.refreshData.observe(viewLifecycleOwner, Observer { todoViewModel.addData.observe(viewLifecycleOwner, Observer {
binding.todoList.adapter?.notifyItemInserted(todoList.size + 1) binding.todoList.adapter?.notifyItemInserted(todoList.size + 1)
}) })
todoViewModel.removeData.observe(viewLifecycleOwner, Observer {
binding.todoList.adapter?.notifyItemRemoved(todoList.size + 1)
})
todoViewModel.refreshData.observe(viewLifecycleOwner, Observer {
binding.todoList.adapter?.notifyItemRangeChanged(0, todoList.size + 1)
})
} }
} }

View file

@ -11,7 +11,11 @@ import kotlinx.coroutines.launch
class ToDoFragmentViewModel : ViewModel() { class ToDoFragmentViewModel : ViewModel() {
val emptyTipVis = MutableLiveData<Int>(View.GONE) val emptyTipVis = MutableLiveData<Int>(View.GONE)
val addData = MutableLiveData<Int>(0)
val removeData = MutableLiveData<Int>(0)
val refreshData = MutableLiveData<Int>(0) val refreshData = MutableLiveData<Int>(0)
val todoList = ArrayList<ToDo>() val todoList = ArrayList<ToDo>()
init { init {
@ -34,7 +38,8 @@ class ToDoFragmentViewModel : ViewModel() {
} }
} }
fun deleteTask(uuid: String) { fun deleteTask(position: Int, uuid: String) {
todoList.removeAt(position)
viewModelScope.launch { viewModelScope.launch {
Repository.deleteByUUID(uuid) Repository.deleteByUUID(uuid)
} }
@ -46,9 +51,24 @@ class ToDoFragmentViewModel : ViewModel() {
} }
} }
fun updateTask(uuid: String) { fun updateTaskState(uuid: String) {
viewModelScope.launch { viewModelScope.launch {
Repository.updateStateByUUID(uuid) Repository.updateStateByUUID(uuid)
} }
} }
fun updateTask(position: Int, todo: ToDoRoom) {
todoList.removeAt(position)
todoList.add(
position, ToDo(
todo.uuid,
todo.state,
todo.content,
todo.subject
)
)
viewModelScope.launch {
Repository.update(todo)
}
}
} }

View file

@ -25,7 +25,6 @@
android:id="@+id/todo_content_info" android:id="@+id/todo_content_info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="测试"
android:textAlignment="center" android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="25sp" /> android:textSize="25sp" />

View file

@ -0,0 +1,172 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/todo_sheet_title"
android:text="@string/add_task"
android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary"
android:textSize="25sp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/todo_content"
style="?attr/textInputFilledExposedDropdownMenuStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="20dp"
android:layout_marginTop="25dp"
android:layout_marginRight="20dp"
android:gravity="center_horizontal"
android:hint="@string/tasks_textfield_hint"
app:errorEnabled="true"
app:helperText=" "
app:helperTextEnabled="true">
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@string/tasks_textfield_hint"
app:simpleItems="@array/todo_predicts" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.chip.ChipGroup
android:id="@+id/todo_subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
android:layout_marginRight="20dp"
app:chipSpacing="5dp"
app:selectionRequired="true"
app:singleSelection="true">
<com.google.android.material.chip.Chip
android:id="@+id/unknown_subject"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/subject_unknown" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_chinese"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_chinese" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_math"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_math" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_english"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_english" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_biology"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_biology" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_physics"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_physics" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_history"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_history" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_geography"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_geography" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_law"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_law" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_other"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_other" />
</com.google.android.material.chip.ChipGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginBottom="50dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cancel"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel" />
<Button
android:id="@+id/btn_delete"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/delete_one"
android:textColor="?android:attr/textColorPrimary"
android:visibility="gone"
app:backgroundTint="?attr/colorErrorContainer" />
<Button
android:id="@+id/btn_save"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="@string/save" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -1,118 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/todo_content"
style="?attr/textInputFilledExposedDropdownMenuStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:layout_marginRight="20dp"
android:gravity="center_horizontal"
android:hint="@string/tasks_textfield_hint"
app:errorEnabled="true"
app:helperText=" "
app:helperTextEnabled="true">
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@string/tasks_textfield_hint"
app:simpleItems="@array/todo_predicts" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.chip.ChipGroup
android:id="@+id/todo_subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
android:layout_marginRight="20dp"
app:chipSpacing="5dp"
app:selectionRequired="true"
app:singleSelection="true">
<com.google.android.material.chip.Chip
android:id="@+id/unknown_subject"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/subject_unknown" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_chinese"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_chinese" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_math"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_math" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_english"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_english" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_biology"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_biology" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_physics"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_physics" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_history"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_history" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_geography"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_geography" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_law"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_law" />
<com.google.android.material.chip.Chip
android:id="@+id/subject_other"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subject_other" />
</com.google.android.material.chip.ChipGroup>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -7,7 +7,9 @@
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:layout_marginBottom="5dp"> android:layout_marginBottom="5dp"
android:clickable="true"
android:focusable="true">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -42,14 +44,14 @@
android:textSize="11sp" /> android:textSize="11sp" />
</LinearLayout> </LinearLayout>
<Button <!--<Button
android:id="@+id/delete_item_btn" android:id="@+id/delete_item_btn"
style="?attr/materialIconButtonStyle" style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="15dp" android:layout_marginEnd="15dp"
android:tooltipText="@string/delete_one" android:tooltipText="@string/delete_one"
app:icon="@drawable/ic_delete" /> app:icon="@drawable/ic_delete" />-->
<Button <Button
android:id="@+id/check_item_btn" android:id="@+id/check_item_btn"

View file

@ -32,8 +32,8 @@
<string name="delete_all">删除全部代办</string> <string name="delete_all">删除全部代办</string>
<string name="check_one">标记为已完成</string> <string name="check_one">标记为已完成</string>
<string name="no_tasks">无待办事项</string> <string name="no_tasks">无待办事项</string>
<string name="delete_undo">撤销</string> <!--<string name="delete_undo">撤销</string>-->
<string name="task_deleted">该待办已删除</string> <!--<string name="task_deleted">该待办已删除</string>-->
<string name="content_cannot_be_empty">待办内容不能为空</string> <string name="content_cannot_be_empty">待办内容不能为空</string>
<string name="settings_label">设置</string> <string name="settings_label">设置</string>
<string name="appearance">外观</string> <string name="appearance">外观</string>
@ -69,4 +69,7 @@
<string name="info_state_incomplete">状态:未完成</string> <string name="info_state_incomplete">状态:未完成</string>
<string name="info_uuid">UUID%s</string> <string name="info_uuid">UUID%s</string>
<string name="remain_text">剩余 %s 项任务</string> <string name="remain_text">剩余 %s 项任务</string>
<string name="save">保存</string>
<string name="update_task">更新待办</string>
<string name="update">更新</string>
</resources> </resources>

View file

@ -32,8 +32,8 @@
<string name="delete_all">Delete all tasks</string> <string name="delete_all">Delete all tasks</string>
<string name="check_one">Checked this task</string> <string name="check_one">Checked this task</string>
<string name="no_tasks">No tasks</string> <string name="no_tasks">No tasks</string>
<string name="delete_undo">Undo</string> <!--<string name="delete_undo">Undo</string>-->
<string name="task_deleted">This task has been deleted</string> <!--<string name="task_deleted">This task has been deleted</string>-->
<string name="content_cannot_be_empty">Task content cannot be empty</string> <string name="content_cannot_be_empty">Task content cannot be empty</string>
<!--Settings--> <!--Settings-->
<string name="settings_label">Settings</string> <string name="settings_label">Settings</string>
@ -69,4 +69,7 @@
<string name="info_state_incomplete">State: incomplete</string> <string name="info_state_incomplete">State: incomplete</string>
<string name="info_uuid">UUID: %s</string> <string name="info_uuid">UUID: %s</string>
<string name="remain_text">%s tasks remaining</string> <string name="remain_text">%s tasks remaining</string>
<string name="save">Save</string>
<string name="update_task">Update task</string>
<string name="update">Update</string>
</resources> </resources>