From 331d098f804368f3ca601f503548f2e2ad3bb672 Mon Sep 17 00:00:00 2001 From: Super12138 <70494801+Super12138@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:18:56 +0800 Subject: [PATCH] Refine empty tip & all task item file --- .../cn/super12138/todo/constant/Constants.kt | 3 + .../todo/views/all/AllTasksActivity.kt | 23 +--- .../todo/views/all/AllTasksAdapter.kt | 86 ++++++++----- .../todo/views/all/AllTasksViewModel.kt | 11 +- .../todo/views/bottomsheet/ToDoBottomSheet.kt | 10 -- .../super12138/todo/views/todo/ToDoAdapter.kt | 116 ++++++++++-------- .../todo/views/todo/ToDoFragment.kt | 41 +------ .../todo/views/todo/ToDoViewModel.kt | 11 +- .../main/res/layout/activity_all_tasks.xml | 13 +- app/src/main/res/layout/fragment_todo.xml | 15 +-- app/src/main/res/layout/item_empty.xml | 16 +++ app/src/main/res/layout/item_todo.xml | 10 +- 12 files changed, 151 insertions(+), 204 deletions(-) create mode 100644 app/src/main/res/layout/item_empty.xml diff --git a/app/src/main/kotlin/cn/super12138/todo/constant/Constants.kt b/app/src/main/kotlin/cn/super12138/todo/constant/Constants.kt index 0eb42be..80969cc 100644 --- a/app/src/main/kotlin/cn/super12138/todo/constant/Constants.kt +++ b/app/src/main/kotlin/cn/super12138/todo/constant/Constants.kt @@ -28,4 +28,7 @@ object Constants { const val BUNDLE_TODO_SUBJECT = "todoSubject" const val BUNDLE_TODO_STATE = "todoState" const val BUNDLE_TODO_UUID = "todoUUID" + + const val EMPTY_VIEW_TYPE = 0 + const val DEFAULT_VIEW_TYPE = 1 } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksActivity.kt b/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksActivity.kt index 2366f63..9d68e10 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksActivity.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksActivity.kt @@ -27,9 +27,10 @@ class AllTasksActivity : BaseActivity() { false -> window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) } + val todoListAll = viewModel.todoListAll val layoutManager = LinearLayoutManager(ToDoApp.context) binding.allTasksList.layoutManager = layoutManager - val adapter = AllTasksAdapter(viewModel.todoListAll, supportFragmentManager) + val adapter = AllTasksAdapter(todoListAll, supportFragmentManager) binding.allTasksList.adapter = adapter FastScrollerBuilder(binding.allTasksList).apply { @@ -43,24 +44,8 @@ class AllTasksActivity : BaseActivity() { finish() } - viewModel.emptyTipVis.observe(this, Observer { visibility -> - if (visibility == View.VISIBLE) { - binding.allTasksList.alpha = 1f - binding.allTasksList.animate().alpha(0f).duration = 200 - binding.allTasksList.visibility = View.GONE - - binding.emptyTip.alpha = 0f - binding.emptyTip.visibility = View.VISIBLE - binding.emptyTip.animate().alpha(1f).duration = 200 - } else { - binding.allTasksList.alpha = 0f - binding.allTasksList.visibility = View.VISIBLE - binding.allTasksList.animate().alpha(1f).duration = 200 - - binding.emptyTip.alpha = 1f - binding.emptyTip.animate().alpha(0f).duration = 200 - binding.emptyTip.visibility = View.GONE - } + viewModel.refreshData.observe(this, Observer { + binding.allTasksList.adapter?.notifyItemRangeChanged(0, todoListAll.size + 1) }) } diff --git a/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksAdapter.kt b/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksAdapter.kt index 6487518..9081246 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksAdapter.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksAdapter.kt @@ -3,6 +3,7 @@ package cn.super12138.todo.views.all import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Button import android.widget.LinearLayout import android.widget.TextView import androidx.core.content.ContextCompat @@ -10,56 +11,73 @@ import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.RecyclerView import cn.super12138.todo.R import cn.super12138.todo.ToDoApp +import cn.super12138.todo.constant.Constants.DEFAULT_VIEW_TYPE +import cn.super12138.todo.constant.Constants.EMPTY_VIEW_TYPE import cn.super12138.todo.logic.model.ToDo import cn.super12138.todo.utils.VibrationUtils +import cn.super12138.todo.views.todo.ToDoAdapter.DefaultViewHolder class AllTasksAdapter( private val todoList: MutableList, private val fragmentManager: FragmentManager -) : - RecyclerView.Adapter() { - - inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { - val todoContext: TextView = view.findViewById(R.id.todo_content_all) - val todoSubject: TextView = view.findViewById(R.id.todo_subject_all) +) : RecyclerView.Adapter() { + // 默认待办项 + inner class DefaultViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val todoContext: TextView = view.findViewById(R.id.todo_content) + val todoSubject: TextView = view.findViewById(R.id.todo_subject) val itemBackground: LinearLayout = view.findViewById(R.id.item_background) + val checkBtn: Button = view.findViewById(R.id.check_item_btn) } + // 空项目提示 + inner class EmptyViewHolder(view: View) : RecyclerView.ViewHolder(view) - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_all_tasks, parent, false) - return ViewHolder(view) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return if (viewType == EMPTY_VIEW_TYPE) { // 如果列表是空的 + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_empty, parent, false) + EmptyViewHolder(view) + } else { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_todo, parent, false) + DefaultViewHolder(view) + } } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val todo = todoList[position] - holder.todoContext.text = todo.content - holder.todoSubject.text = todo.subject + override fun getItemViewType(position: Int): Int { + return if (todoList.isEmpty()) EMPTY_VIEW_TYPE else DEFAULT_VIEW_TYPE + } - if (todo.state == 1) { - holder.itemBackground.background = - ContextCompat.getDrawable(ToDoApp.context, R.drawable.bg_item_complete) - } + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + // 判断当前的holder是不是待办项目的holder + if (holder is DefaultViewHolder) { + val todo = todoList[position] + holder.apply { + checkBtn.visibility = View.GONE + todoContext.text = todo.content + todoSubject.text = todo.subject + } - holder.itemView.setOnClickListener { - VibrationUtils.performHapticFeedback(it) + if (todo.state == 1) { + holder.itemBackground.background = + ContextCompat.getDrawable(ToDoApp.context, R.drawable.bg_item_complete) + } - val infoBottomSheet = InfoBottomSheet.newInstance( - todo.content, - todo.subject, - todo.state, - todo.uuid - ) - infoBottomSheet.show(fragmentManager, InfoBottomSheet.TAG) - } + holder.itemView.setOnClickListener { + VibrationUtils.performHapticFeedback(it) - /*if (!todo.isAnimated) { - holder.itemView.alpha = 0f - holder.itemView.animate().alpha(1f).duration = 200 - todo.isAnimated = true - }*/ + val infoBottomSheet = InfoBottomSheet.newInstance( + todo.content, + todo.subject, + todo.state, + todo.uuid + ) + infoBottomSheet.show(fragmentManager, InfoBottomSheet.TAG) + } + } } - override fun getItemCount() = todoList.size + override fun getItemCount(): Int { + return if (todoList.isEmpty()) 1 else todoList.size + } } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksViewModel.kt b/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksViewModel.kt index 1f380d0..0a9ab3d 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksViewModel.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/all/AllTasksViewModel.kt @@ -1,6 +1,5 @@ package cn.super12138.todo.views.all -import android.view.View import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -9,8 +8,8 @@ import cn.super12138.todo.logic.model.ToDo import kotlinx.coroutines.launch class AllTasksViewModel : ViewModel() { - val emptyTipVis = MutableLiveData(View.VISIBLE) val todoListAll = ArrayList() + val refreshData = MutableLiveData(0) init { loadToDos() @@ -19,15 +18,11 @@ class AllTasksViewModel : ViewModel() { private fun loadToDos() { viewModelScope.launch { val todos = Repository.getAll() - var count = 0 for (todo in todos) { todoListAll.add(ToDo(todo.uuid, todo.state, todo.content, todo.subject)) - count++ } - if (count == 0) { - emptyTipVis.value = View.VISIBLE - } else { - emptyTipVis.value = View.GONE + if (todoListAll.size > 0) { + refreshData.value = 1 } } } diff --git a/app/src/main/kotlin/cn/super12138/todo/views/bottomsheet/ToDoBottomSheet.kt b/app/src/main/kotlin/cn/super12138/todo/views/bottomsheet/ToDoBottomSheet.kt index 2e2bc78..6946ecc 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/bottomsheet/ToDoBottomSheet.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/bottomsheet/ToDoBottomSheet.kt @@ -152,9 +152,6 @@ class ToDoBottomSheet : BottomSheetDialogFragment() { todoViewModel.refreshData.value = 1 } else { // 添加到 RecyclerView - if (todoList.size + 1 > 0) { - todoViewModel.emptyTipVis.value = View.GONE - } todoList.add( ToDo(randomUUID, 0, todoContent, todoSubject) ) @@ -189,13 +186,6 @@ class ToDoBottomSheet : BottomSheetDialogFragment() { progressViewModel.updateProgress() todoViewModel.removeData.value = 1 - // 空项目提示显示判断 - if (todoList.isEmpty()) { - todoViewModel.emptyTipVis.value = View.VISIBLE - } else { - todoViewModel.emptyTipVis.value = View.GONE - } - dismiss() } } diff --git a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt index 61ef5b0..c9a3193 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt @@ -10,6 +10,8 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelStoreOwner import androidx.recyclerview.widget.RecyclerView import cn.super12138.todo.R +import cn.super12138.todo.constant.Constants.DEFAULT_VIEW_TYPE +import cn.super12138.todo.constant.Constants.EMPTY_VIEW_TYPE import cn.super12138.todo.constant.GlobalValues import cn.super12138.todo.logic.model.ToDo import cn.super12138.todo.utils.VibrationUtils @@ -21,79 +23,85 @@ class ToDoAdapter( private val todoList: MutableList, private val viewModelStoreOwner: ViewModelStoreOwner, private val fragmentManager: FragmentManager -) : - RecyclerView.Adapter() { - - inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { +) : RecyclerView.Adapter() { + // 默认待办项 + inner class DefaultViewHolder(view: View) : RecyclerView.ViewHolder(view) { val todoContext: TextView = view.findViewById(R.id.todo_content) val todoSubject: TextView = view.findViewById(R.id.todo_subject) val checkToDoBtn: Button = view.findViewById(R.id.check_item_btn) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_todo, parent, false) + // 空项目提示 + inner class EmptyViewHolder(view: View) : RecyclerView.ViewHolder(view) + + // 判断列表是否为空,为空显示空项目提示 + override fun getItemViewType(position: Int): Int { + return if (todoList.isEmpty()) EMPTY_VIEW_TYPE else DEFAULT_VIEW_TYPE + } - return ViewHolder(view) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return if (viewType == EMPTY_VIEW_TYPE) { // 如果列表是空的 + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_empty, parent, false) + EmptyViewHolder(view) + } else { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_todo, parent, false) + DefaultViewHolder(view) + } } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val todo = todoList[position] - holder.todoContext.text = todo.content - holder.todoSubject.text = todo.subject - /*if (!todo.isAnimated) { - holder.itemView.alpha = 0f - holder.itemView.animate().alpha(1f).duration = 200 - todo.isAnimated = true - }*/ + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + // 判断当前的holder是不是待办项目的holder + if (holder is DefaultViewHolder) { + val todo = todoList[position] + holder.todoContext.text = todo.content + holder.todoSubject.text = todo.subject - val progressViewModel = - ViewModelProvider(viewModelStoreOwner)[ProgressViewModel::class.java] - val todoViewModel = - ViewModelProvider(viewModelStoreOwner)[ToDoViewModel::class.java] + val progressViewModel = + ViewModelProvider(viewModelStoreOwner)[ProgressViewModel::class.java] + val todoViewModel = + ViewModelProvider(viewModelStoreOwner)[ToDoViewModel::class.java] - holder.checkToDoBtn.setOnClickListener { - VibrationUtils.performHapticFeedback(it) + holder.checkToDoBtn.setOnClickListener { + VibrationUtils.performHapticFeedback(it) - if (position < 0 || position >= todoList.size) { - return@setOnClickListener - } + if (position >= todoList.size) { + return@setOnClickListener + } - todoList.removeAt(position) - notifyItemRemoved(position) - notifyItemRangeChanged(position, todoList.size) + todoList.removeAt(position) + notifyItemRemoved(position) + notifyItemRangeChanged(position, todoList.size) - todoViewModel.updateTaskState(todo.uuid) + todoViewModel.updateTaskState(todo.uuid) - // 设置空项目提示可见性 - if (todoList.isEmpty()) { - todoViewModel.emptyTipVis.value = View.VISIBLE - } else { - todoViewModel.emptyTipVis.value = View.GONE + progressViewModel.updateProgress() } - progressViewModel.updateProgress() - } - holder.itemView.setOnClickListener { - if (GlobalValues.devMode) { - VibrationUtils.performHapticFeedback(it) - "Current position: $position".showToast() + holder.itemView.setOnClickListener { + if (GlobalValues.devMode) { + VibrationUtils.performHapticFeedback(it) + "Current position: $position".showToast() + } } - } - holder.itemView.setOnLongClickListener { - val toDoBottomSheet = ToDoBottomSheet.newInstance( - true, - position, - todo.uuid, - todo.state, - todo.subject, - todo.content - ) - toDoBottomSheet.show(fragmentManager, ToDoBottomSheet.TAG) - true + holder.itemView.setOnLongClickListener { + val toDoBottomSheet = ToDoBottomSheet.newInstance( + true, + position, + todo.uuid, + todo.state, + todo.subject, + todo.content + ) + toDoBottomSheet.show(fragmentManager, ToDoBottomSheet.TAG) + true + } } } - override fun getItemCount() = todoList.size + override fun getItemCount(): Int { + return if (todoList.isEmpty()) 1 else todoList.size + } } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt index 8902f8a..3971210 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt @@ -18,6 +18,7 @@ import cn.super12138.todo.ToDoApp import cn.super12138.todo.databinding.FragmentTodoBinding import cn.super12138.todo.logic.Repository import cn.super12138.todo.utils.VibrationUtils +import cn.super12138.todo.utils.showToast import cn.super12138.todo.views.bottomsheet.ToDoBottomSheet import cn.super12138.todo.views.progress.ProgressViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -50,21 +51,17 @@ class ToDoFragment : Fragment() { } WindowInsetsCompat.CONSUMED } - val todoList = todoViewModel.todoList - - val layoutManager = LinearLayoutManager(ToDoApp.context) - binding.todoList.layoutManager = layoutManager - val adapter = ToDoAdapter(todoList, requireActivity(), parentFragmentManager) - binding.todoList.adapter = adapter FastScrollerBuilder(binding.todoList).apply { useMd2Style() build() } - if (todoList.isEmpty()) { - todoViewModel.emptyTipVis.value = View.VISIBLE - } + val layoutManager = LinearLayoutManager(ToDoApp.context) + binding.todoList.layoutManager = layoutManager + val todoList = todoViewModel.todoList + val adapter = ToDoAdapter(todoList, requireActivity(), parentFragmentManager) + binding.todoList.adapter = adapter binding.addItem.setOnClickListener { VibrationUtils.performHapticFeedback(it) @@ -90,9 +87,6 @@ class ToDoFragment : Fragment() { } // 通知数据更改 binding.todoList.adapter?.notifyItemRangeRemoved(0, todoList.size + 1) - - // 显示空项目提示 - todoViewModel.emptyTipVis.value = View.VISIBLE } .setNegativeButton(R.string.cancel, null) .show() @@ -114,29 +108,6 @@ class ToDoFragment : Fragment() { } }) - todoViewModel.emptyTipVis.observe(viewLifecycleOwner, Observer { visibility -> - if (visibility == View.VISIBLE) { - binding.todoList.alpha = 1f - binding.todoList.animate().alpha(0f).duration = 200 - binding.todoList.visibility = View.GONE - - binding.emptyTip.alpha = 0f - binding.emptyTip.visibility = View.VISIBLE - binding.emptyTip.animate().alpha(1f).duration = 200 - } else { - binding.todoList.alpha = 0f - binding.todoList.visibility = View.VISIBLE - binding.todoList.animate().alpha(1f).duration = 200 - - binding.emptyTip.alpha = 1f - binding.emptyTip.animate().alpha(0f).duration = 200 - binding.emptyTip.visibility = View.GONE - } - if (todoList.size == 0 && !binding.addItem.isShown) { - binding.addItem.show() - } - }) - todoViewModel.addData.observe(viewLifecycleOwner, Observer { binding.todoList.adapter?.notifyItemInserted(todoList.size + 1) }) diff --git a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoViewModel.kt b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoViewModel.kt index 055e79d..6f224a2 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoViewModel.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoViewModel.kt @@ -1,6 +1,5 @@ package cn.super12138.todo.views.todo -import android.view.View import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -10,8 +9,6 @@ import cn.super12138.todo.logic.model.ToDo import kotlinx.coroutines.launch class ToDoViewModel : ViewModel() { - val emptyTipVis = MutableLiveData(View.GONE) - val addData = MutableLiveData(0) val removeData = MutableLiveData(0) val refreshData = MutableLiveData(0) @@ -25,15 +22,11 @@ class ToDoViewModel : ViewModel() { private fun loadTasks() { viewModelScope.launch { val todos = Repository.getAllIncomplete() - var count = 0 for (todo in todos) { todoList.add(ToDo(todo.uuid, todo.state, todo.content, todo.subject)) - count++ } - if (count == 0) { - emptyTipVis.value = View.VISIBLE - } else { - emptyTipVis.value = View.GONE + if (todoList.size > 0) { + refreshData.value = 1 } } } diff --git a/app/src/main/res/layout/activity_all_tasks.xml b/app/src/main/res/layout/activity_all_tasks.xml index 8183cbd..aef8d2b 100644 --- a/app/src/main/res/layout/activity_all_tasks.xml +++ b/app/src/main/res/layout/activity_all_tasks.xml @@ -32,18 +32,7 @@ - - + android:layout_height="match_parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_todo.xml b/app/src/main/res/layout/fragment_todo.xml index ffd32d4..3aab641 100644 --- a/app/src/main/res/layout/fragment_todo.xml +++ b/app/src/main/res/layout/fragment_todo.xml @@ -8,20 +8,7 @@ - - - - + android:layout_height="match_parent" /> + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_todo.xml b/app/src/main/res/layout/item_todo.xml index 4c9779c..573395c 100644 --- a/app/src/main/res/layout/item_todo.xml +++ b/app/src/main/res/layout/item_todo.xml @@ -12,6 +12,7 @@ android:focusable="true"> - -