Final Results
The new actions_edit
menu resource should contain:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/save"
android:icon="@drawable/ic_save"
android:title="@string/menu_save"
app:showAsAction="ifRoom|withText" />
</menu>
EditFragment
should resemble:
package com.commonsware.todo
import android.os.Bundle
import android.view.*
import android.view.inputmethod.InputMethodManager
import androidx.core.content.getSystemService
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.commonsware.todo.databinding.TodoEditBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
class EditFragment : Fragment() {
private var binding: TodoEditBinding? = null
private val args: EditFragmentArgs by navArgs()
private val motor: SingleModelMotor by viewModel { parametersOf(args.modelId) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
) = TodoEditBinding.inflate(inflater, container, false)
.apply { binding = this }
.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
motor.getModel()?.let {
binding?.apply {
isCompleted.isChecked = it.isCompleted
desc.setText(it.description)
notes.setText(it.notes)
}
}
}
override fun onDestroyView() {
binding = null
super.onDestroyView()
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.actions_edit, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.save -> {
save()
return true
}
}
return super.onOptionsItemSelected(item)
}
private fun save() {
binding?.apply {
val model = motor.getModel()
val edited = model?.copy(
description = desc.text.toString(),
isCompleted = isCompleted.isChecked,
notes = notes.text.toString()
) ?: ToDoModel(
description = desc.text.toString(),
isCompleted = isCompleted.isChecked,
notes = notes.text.toString()
)
edited.let { motor.save(it) }
}
navToDisplay()
}
private fun navToDisplay() {
hideKeyboard()
findNavController().popBackStack()
}
private fun hideKeyboard() {
view?.let {
val imm = context?.getSystemService<InputMethodManager>()
imm?.hideSoftInputFromWindow(
it.windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
}
}
RosterMotor
should look like:
package com.commonsware.todo
import androidx.lifecycle.ViewModel
class RosterMotor(private val repo: ToDoRepository) : ViewModel() {
fun getItems() = repo.items
fun save(model: ToDoModel) {
repo.save(model)
}
}
And RosterListFragment
should resemble:
package com.commonsware.todo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.commonsware.todo.databinding.TodoRosterBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
import androidx.navigation.fragment.findNavController
class RosterListFragment : Fragment() {
private val motor: RosterMotor by viewModel()
private var binding: TodoRosterBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = TodoRosterBinding.inflate(inflater, container, false)
.also { binding = it }
.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter = RosterAdapter(
layoutInflater,
onCheckboxToggle = { motor.save(it.copy(isCompleted = !it.isCompleted)) },
onRowClick = ::display)
binding?.items?.apply {
setAdapter(adapter)
layoutManager = LinearLayoutManager(context)
addItemDecoration(
DividerItemDecoration(
activity,
DividerItemDecoration.VERTICAL
)
)
}
adapter.submitList(motor.getItems())
binding?.empty?.visibility = View.GONE
}
override fun onDestroyView() {
binding = null
super.onDestroyView()
}
private fun display(model: ToDoModel) {
findNavController()
.navigate(RosterListFragmentDirections.displayModel(model.id))
}
}
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.