Skip to content

Commit

Permalink
Fix keyboard appearance on expense and tag creation
Browse files Browse the repository at this point in the history
  • Loading branch information
nominalista committed Jul 31, 2019
1 parent bed0c5c commit f153481
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class AddEditExpenseFragment : Fragment() {
addListeners()
initializeModels()
bindModels()
showKeyboard()
}

private fun setupActionBar() {
Expand All @@ -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)
}
Expand Down Expand Up @@ -165,6 +165,10 @@ class AddEditExpenseFragment : Fragment() {
requireActivity().onBackPressed()
}

private fun showKeyboard() {
showKeyboard(edit_text_amount, KEYBOARD_APPEARANCE_DELAY)
}

// Lifecycle end

override fun onDestroyView() {
Expand Down Expand Up @@ -201,4 +205,8 @@ class AddEditExpenseFragment : Fragment() {
model.saveExpense()
return true
}

companion object {
private const val KEYBOARD_APPEARANCE_DELAY = 300L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -11,49 +12,56 @@ 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
private val text get() = editText.text.toString()

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()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import io.reactivex.disposables.CompositeDisposable

class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSource) : ViewModel() {

val itemModels =
Variable(emptyList<TagSelectionItemModel>())
val itemModels = Variable(emptyList<TagSelectionItemModel>())
val showNewTagDialog = Event()
val delegateSelectedTags = DataEvent<List<Tag>>()
val finish = Event()
Expand All @@ -25,8 +24,6 @@ class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSour

private val disposables = CompositeDisposable()

private val addTagSelection = listOf(createAddTagItemModel())

// Lifecycle start

init {
Expand All @@ -47,7 +44,13 @@ class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSour
private fun updateItemModels(tags: List<Tag>) {
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<Tag>) = tags.map { createTagItemModel(it) }
Expand Down Expand Up @@ -83,10 +86,6 @@ class TagSelectionFragmentModel(private val databaseDataSource: DatabaseDataSour
})
}

private fun createAddTagItemModel() = AddTagItemModel().apply {
click = { showNewTagDialog.next() }
}

// Lifecycle end

override fun onCleared() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
4 changes: 2 additions & 2 deletions app/src/main/res/layout/item_add_tag.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginStart="72dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
Expand All @@ -32,7 +32,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/button_add"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
18 changes: 9 additions & 9 deletions app/src/main/res/layout/item_tag.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
android:layout_height="56dp"
android:background="?selectableItemBackground">

<View
android:layout_width="0dp"
android:layout_height="@dimen/divider"
android:layout_marginStart="72dp"
android:background="@color/divider_dark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<CheckBox
android:id="@+id/check_box"
android:layout_width="wrap_content"
Expand Down Expand Up @@ -45,13 +54,4 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<View
android:layout_width="0dp"
android:layout_height="@dimen/divider"
android:layout_marginStart="72dp"
android:background="@color/divider_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

0 comments on commit f153481

Please sign in to comment.