Android Keep Track of Edit and View Mode With LiveData (Fragment, Kotlin)

April 20, 2020

For data entry UI, it is common to have an UI with support edit and view mode.

ViewModel

class BatchViewModel : ViewModel() {
    val editModeEvent = MutableLiveData<Event<Boolean>>(Event(false))
    internal var editMode: Boolean
        get() = editModeEvent.value!!.peek()
        set(value) {
            editModeEvent.value = Event(value)
        }
}

Fragment

class BatchFragment : Fragment() {
    private val viewModel: BatchViewModel by viewModels()
    // private val args: BatchFragmentArgs by navArgs()
    // private lateinit var adapter: LocalAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.batch, container, false)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.batch, menu)

        val editMenuItem = menu.findItem(R.id.action_edit)
        val saveMenuItem = menu.findItem(R.id.action_save)

        if (viewModel.editMode) {
            editMenuItem.isVisible = false
            saveMenuItem.isVisible = true
        }
        else {
            editMenuItem.isVisible = true
            saveMenuItem.isVisible = false
        }

        super.onCreateOptionsMenu(menu, inflater)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return (when(item.itemId) {
            R.id.action_save -> {
                viewModel.editMode = false
                true
            }
            R.id.action_edit -> {
                viewModel.editMode = true
                true
            }
            else ->
                super.onOptionsItemSelected(item)
        })
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        // viewModel.editMode = args.default.isNew
        viewModel.editMode = true

        initObserver()
    }

    private fun initObserver() {
        viewModel.editModeEvent.observe(viewLifecycleOwner, Observer { event ->
            event.getIfPending()?.also { isEdit ->
                activity?.invalidateOptionsMenu()
                // adapter.notifyDataSetChanged()

                // do something to update the UI
            }
        })
    }
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_edit"
        android:title="Edit"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_save"
        android:title="Save"
        app:showAsAction="ifRoom" />
</menu>
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.