From f15348128f5e6848d9f98f32bf10d5215d0de4c1 Mon Sep 17 00:00:00 2001 From: nominalista Date: Wed, 31 Jul 2019 20:41:40 +0200 Subject: [PATCH] Fix keyboard appearance on expense and tag creation --- .../presentation/AddEditExpenseFragment.kt | 10 ++++- .../tagselection/NewTagDialogFragment.kt | 44 +++++++++++-------- .../tagselection/TagSelectionFragmentModel.kt | 17 ++++--- .../expenses/util/extensions/Activity.kt | 17 +++++-- .../expenses/util/extensions/Fragment.kt | 8 +++- app/src/main/res/layout/item_add_tag.xml | 4 +- app/src/main/res/layout/item_tag.xml | 18 ++++---- 7 files changed, 74 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/AddEditExpenseFragment.kt b/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/AddEditExpenseFragment.kt index a60e422..b9302c1 100644 --- a/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/AddEditExpenseFragment.kt +++ b/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/AddEditExpenseFragment.kt @@ -42,6 +42,7 @@ class AddEditExpenseFragment : Fragment() { addListeners() initializeModels() bindModels() + showKeyboard() } private fun setupActionBar() { @@ -53,7 +54,6 @@ class AddEditExpenseFragment : Fragment() { } private fun watchEditTexts() { - showKeyboard(edit_text_amount, 200) edit_text_amount.afterTextChanged { model.updateAmount(it.toString().toFloatOrNull() ?: 0f) } @@ -165,6 +165,10 @@ class AddEditExpenseFragment : Fragment() { requireActivity().onBackPressed() } + private fun showKeyboard() { + showKeyboard(edit_text_amount, KEYBOARD_APPEARANCE_DELAY) + } + // Lifecycle end override fun onDestroyView() { @@ -201,4 +205,8 @@ class AddEditExpenseFragment : Fragment() { model.saveExpense() return true } + + companion object { + private const val KEYBOARD_APPEARANCE_DELAY = 300L + } } diff --git a/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/NewTagDialogFragment.kt b/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/NewTagDialogFragment.kt index a2f334f..f64423f 100644 --- a/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/NewTagDialogFragment.kt +++ b/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/NewTagDialogFragment.kt @@ -2,6 +2,7 @@ package com.nominalista.expenses.addeditexpense.presentation.tagselection import android.annotation.SuppressLint import android.app.Dialog +import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -11,16 +12,12 @@ import androidx.fragment.app.DialogFragment import com.nominalista.expenses.R import com.nominalista.expenses.data.Tag import com.nominalista.expenses.util.extensions.afterTextChanged -import com.nominalista.expenses.util.extensions.hideKeyboard import com.nominalista.expenses.util.extensions.showKeyboard +import com.nominalista.expenses.util.extensions.toggleKeyboard class NewTagDialogFragment : DialogFragment() { - companion object { - fun newInstance() = NewTagDialogFragment() - } - var tagCreated: ((Tag) -> Unit)? = null private lateinit var editText: EditText @@ -28,32 +25,43 @@ class NewTagDialogFragment : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return AlertDialog.Builder(requireActivity()) - .setView(createView()) - .setPositiveButton(R.string.add) { _, _ -> tagCreated?.invoke(Tag(0, text)) } - .setNegativeButton(R.string.cancel) { _, _ -> } - .setOnDismissListener { hideKeyboard() } - .create() + .setView(createView()) + .setPositiveButton(R.string.add) { _, _ -> tagCreated?.invoke(Tag(0, text)) } + .setNegativeButton(R.string.cancel) { _, _ -> } + .create() + .apply { setOnShowListener { enableOrDisableEditText() } } } @SuppressLint("InflateParams") private fun createView(): View { val inflater = LayoutInflater.from(requireContext()) val view = inflater.inflate(R.layout.dialog_new_tag, null) - bindViews(view) + bindEditText(view) watchEditText() + showKeyboard(editText) return view } - private fun bindViews(view: View) { + private fun bindEditText(view: View) { editText = view.findViewById(R.id.edit_text) } private fun watchEditText() { - showKeyboard(editText) - editText.afterTextChanged { - val dialog = dialog as AlertDialog - val addButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE) - addButton.isEnabled = text.isNotEmpty() - } + editText.afterTextChanged { enableOrDisableEditText() } + } + + private fun enableOrDisableEditText() { + val dialog = dialog as AlertDialog + val addButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE) + addButton.isEnabled = text.isNotEmpty() + } + + override fun onDismiss(dialog: DialogInterface?) { + super.onDismiss(dialog) + toggleKeyboard() + } + + companion object { + fun newInstance() = NewTagDialogFragment() } } \ No newline at end of file diff --git a/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/TagSelectionFragmentModel.kt b/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/TagSelectionFragmentModel.kt index 3527d43..2671da1 100644 --- a/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/TagSelectionFragmentModel.kt +++ b/app/src/main/java/com/nominalista/expenses/addeditexpense/presentation/tagselection/TagSelectionFragmentModel.kt @@ -15,8 +15,7 @@ import io.reactivex.disposables.CompositeDisposable class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSource) : ViewModel() { - val itemModels = - Variable(emptyList()) + val itemModels = Variable(emptyList()) val showNewTagDialog = Event() val delegateSelectedTags = DataEvent>() val finish = Event() @@ -25,8 +24,6 @@ class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSour private val disposables = CompositeDisposable() - private val addTagSelection = listOf(createAddTagItemModel()) - // Lifecycle start init { @@ -47,7 +44,13 @@ class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSour private fun updateItemModels(tags: List) { itemModels.value = tags .sortedBy { it.name } - .let { addTagSelection + createTagSection(it) } + .let { createAddTagSection() + createTagSection(it) } + } + + private fun createAddTagSection() = listOf(createAddTagItemModel()) + + private fun createAddTagItemModel(): AddTagItemModel { + return AddTagItemModel().apply { click = { showNewTagDialog.next() } } } private fun createTagSection(tags: List) = tags.map { createTagItemModel(it) } @@ -83,10 +86,6 @@ class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSour }) } - private fun createAddTagItemModel() = AddTagItemModel().apply { - click = { showNewTagDialog.next() } - } - // Lifecycle end override fun onCleared() { diff --git a/app/src/main/java/com/nominalista/expenses/util/extensions/Activity.kt b/app/src/main/java/com/nominalista/expenses/util/extensions/Activity.kt index 78aef50..8b46e3b 100644 --- a/app/src/main/java/com/nominalista/expenses/util/extensions/Activity.kt +++ b/app/src/main/java/com/nominalista/expenses/util/extensions/Activity.kt @@ -13,8 +13,19 @@ fun Activity.showKeyboard(view: View, delay: Long = 0) { }, delay) } -fun Activity.hideKeyboard() { - val view = currentFocus ?: View(this) +fun Activity.hideKeyboard(view: View? = null) { + val windowToken = view?.windowToken ?: getCurrentFocusOrPlaceholder().windowToken val manager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager - manager.hideSoftInputFromWindow(view.windowToken, 0) + manager.hideSoftInputFromWindow(windowToken, 0) +} + +private fun Activity.getCurrentFocusOrPlaceholder() = currentFocus ?: View(this) + +/** + * Shows or hides keyboard. It is especially useful for DialogFragments where hideKeyboard() seems + * to be not working correctly. + */ +fun Activity.toggleKeyboard() { + val imm = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager + imm.toggleSoftInput(0, 0) } \ No newline at end of file diff --git a/app/src/main/java/com/nominalista/expenses/util/extensions/Fragment.kt b/app/src/main/java/com/nominalista/expenses/util/extensions/Fragment.kt index 698d880..adca19f 100644 --- a/app/src/main/java/com/nominalista/expenses/util/extensions/Fragment.kt +++ b/app/src/main/java/com/nominalista/expenses/util/extensions/Fragment.kt @@ -7,6 +7,10 @@ fun Fragment.showKeyboard(view: View, delay: Long = 0) { requireActivity().showKeyboard(view, delay) } -fun Fragment.hideKeyboard() { - requireActivity().hideKeyboard() +fun Fragment.hideKeyboard(view: View? = null) { + requireActivity().hideKeyboard(view) +} + +fun Fragment.toggleKeyboard() { + requireActivity().toggleKeyboard() } \ No newline at end of file diff --git a/app/src/main/res/layout/item_add_tag.xml b/app/src/main/res/layout/item_add_tag.xml index 7ba9474..dc5cf7b 100644 --- a/app/src/main/res/layout/item_add_tag.xml +++ b/app/src/main/res/layout/item_add_tag.xml @@ -22,7 +22,7 @@ \ No newline at end of file diff --git a/app/src/main/res/layout/item_tag.xml b/app/src/main/res/layout/item_tag.xml index ad890b3..d149c28 100644 --- a/app/src/main/res/layout/item_tag.xml +++ b/app/src/main/res/layout/item_tag.xml @@ -6,6 +6,15 @@ android:layout_height="56dp" android:background="?selectableItemBackground"> + + - - \ No newline at end of file