Refine empty tip & all task item file

This commit is contained in:
Super12138 2024-08-14 15:18:56 +08:00
parent 9fd6d41aed
commit 331d098f80
12 changed files with 162 additions and 215 deletions

View file

@ -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
}

View file

@ -27,9 +27,10 @@ class AllTasksActivity : BaseActivity<ActivityAllTasksBinding>() {
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<ActivityAllTasksBinding>() {
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)
})
}

View file

@ -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<ToDo>,
private val fragmentManager: FragmentManager
) :
RecyclerView.Adapter<AllTasksAdapter.ViewHolder>() {
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<RecyclerView.ViewHolder>() {
// 默认待办项
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 onBindViewHolder(holder: ViewHolder, position: Int) {
val todo = todoList[position]
holder.todoContext.text = todo.content
holder.todoSubject.text = todo.subject
if (todo.state == 1) {
holder.itemBackground.background =
ContextCompat.getDrawable(ToDoApp.context, R.drawable.bg_item_complete)
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)
}
holder.itemView.setOnClickListener {
VibrationUtils.performHapticFeedback(it)
val infoBottomSheet = InfoBottomSheet.newInstance(
todo.content,
todo.subject,
todo.state,
todo.uuid
)
infoBottomSheet.show(fragmentManager, InfoBottomSheet.TAG)
}
/*if (!todo.isAnimated) {
holder.itemView.alpha = 0f
holder.itemView.animate().alpha(1f).duration = 200
todo.isAnimated = true
}*/
}
override fun getItemCount() = todoList.size
override fun getItemViewType(position: Int): Int {
return if (todoList.isEmpty()) EMPTY_VIEW_TYPE else DEFAULT_VIEW_TYPE
}
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
}
if (todo.state == 1) {
holder.itemBackground.background =
ContextCompat.getDrawable(ToDoApp.context, R.drawable.bg_item_complete)
}
holder.itemView.setOnClickListener {
VibrationUtils.performHapticFeedback(it)
val infoBottomSheet = InfoBottomSheet.newInstance(
todo.content,
todo.subject,
todo.state,
todo.uuid
)
infoBottomSheet.show(fragmentManager, InfoBottomSheet.TAG)
}
}
}
override fun getItemCount(): Int {
return if (todoList.isEmpty()) 1 else todoList.size
}
}

View file

@ -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<Int>(View.VISIBLE)
val todoListAll = ArrayList<ToDo>()
val refreshData = MutableLiveData<Int>(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
}
}
}

View file

@ -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()
}
}

View file

@ -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<ToDo>,
private val viewModelStoreOwner: ViewModelStoreOwner,
private val fragmentManager: FragmentManager
) :
RecyclerView.Adapter<ToDoAdapter.ViewHolder>() {
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// 默认待办项
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)
return ViewHolder(view)
// 判断列表是否为空,为空显示空项目提示
override fun getItemViewType(position: Int): Int {
return if (todoList.isEmpty()) EMPTY_VIEW_TYPE else DEFAULT_VIEW_TYPE
}
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
}*/
val progressViewModel =
ViewModelProvider(viewModelStoreOwner)[ProgressViewModel::class.java]
val todoViewModel =
ViewModelProvider(viewModelStoreOwner)[ToDoViewModel::class.java]
holder.checkToDoBtn.setOnClickListener {
VibrationUtils.performHapticFeedback(it)
if (position < 0 || position >= todoList.size) {
return@setOnClickListener
}
todoList.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, todoList.size)
todoViewModel.updateTaskState(todo.uuid)
// 设置空项目提示可见性
if (todoList.isEmpty()) {
todoViewModel.emptyTipVis.value = View.VISIBLE
} else {
todoViewModel.emptyTipVis.value = View.GONE
}
progressViewModel.updateProgress()
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)
}
}
holder.itemView.setOnClickListener {
if (GlobalValues.devMode) {
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]
holder.checkToDoBtn.setOnClickListener {
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
if (position >= todoList.size) {
return@setOnClickListener
}
todoList.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, todoList.size)
todoViewModel.updateTaskState(todo.uuid)
progressViewModel.updateProgress()
}
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
}
}
}
override fun getItemCount() = todoList.size
override fun getItemCount(): Int {
return if (todoList.isEmpty()) 1 else todoList.size
}
}

View file

@ -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)
})

View file

@ -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<Int>(View.GONE)
val addData = MutableLiveData<Int>(0)
val removeData = MutableLiveData<Int>(0)
val refreshData = MutableLiveData<Int>(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
}
}
}

View file

@ -32,18 +32,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/all_tasks_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<TextView
android:id="@+id/empty_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="@string/no_tasks"
android:textSize="14sp"
android:visibility="visible" />
android:layout_height="match_parent" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -8,20 +8,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/todo_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:id="@+id/empty_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="@string/no_tasks"
android:textSize="14sp"
android:visibility="visible" />
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/add_item"

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/empty_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/no_tasks"
android:textAlignment="center"
android:textSize="14sp" />
</LinearLayout>

View file

@ -12,6 +12,7 @@
android:focusable="true">
<LinearLayout
android:id="@+id/item_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
@ -44,15 +45,6 @@
android:textSize="11sp" />
</LinearLayout>
<!--<Button
android:id="@+id/delete_item_btn"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="15dp"
android:tooltipText="@string/delete_one"
app:icon="@drawable/ic_delete" />-->
<Button
android:id="@+id/check_item_btn"
style="?attr/materialIconButtonStyle"