Hiding SoftKeyboard when button inside dialog is clicked - android

I have custom dialog where inside its xml has a Submit button that whenever clicked, it should dismiss the softKeyboard.
I have the following code:
MainActivity.kt (Inherits from BaseActivity)
val updateDialog = Dialog(this, R.style.CustomDialog)
updateDialog.setContentView(R.layout.dialog_update)
val tvSubmitToFirestore = updateDialog.findViewById<HelveticaBoldTextView>(R.id.tv_update_item)
tvSubmitToFirestore.setOnClickListener {
hideKeyboard(currentFocus ?: View(this))
}
BaseActivity:
open class BaseActivity : AppCompatActivity() {
//hide keyboard when instance of an event
fun Context.hideKeyboard(view: View) {
val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
}
But the keyboard remains on its position after clicking the said button.
Update:
//update item
val tvUpdate = showItemDialog.findViewById<HelveticaNormalTextView>(R.id.tv_update)
tvUpdate.setOnClickListener {
//close search dialog
showItemDialog.dismiss()
val updateDialog = Dialog(this, R.style.CustomDialog)
updateDialog.setContentView(R.layout.dialog_update)
updateDialog.setCancelable(false)
//spinner settings
val spinner = updateDialog.findViewById<Spinner>(R.id.sp_update)
populateSpinner(spinner, dialogProductCategory.text.toString())
//set default values of update dialog fields == the current product's properties(name, category, price)
val etProductName = updateDialog.findViewById<TextInputEditText>(R.id.et_update_product_name)
val etProductPrice = updateDialog.findViewById<TextInputEditText>(R.id.et_update_product_price)
etProductName.setText(dialogProdName.text.toString())
etProductPrice.setText(dialogProductPrice.text.toString())
//update item
val tvSubmitToFirestore = updateDialog.findViewById<HelveticaBoldTextView>(R.id.tv_update_item)
//TODO allow user to update an item with the same name provided that it should only exist once
// and must be unique
tvSubmitToFirestore.setOnClickListener {
// hideKeyboard(currentFocus ?: tvSubmitToFirestore)
hideKeyboard1(it, this#MainActivity)
val newProductName = etProductName.text.toString().trim()
val newProductCategory = spinner.selectedItem.toString().uppercase()
val newProductPrice = etProductPrice.text.toString().toDouble()
GlobalScope.launch {
validateProduct(newProductName, newProductCategory, newProductPrice)
}
//TODO : allow user to reuse the product name when updating
}

You can use the new WindowInsetsController library to hide and show keyboard. Use this function:
fun hideKeyboard(view: View, activity: Activity) {
WindowInsetsControllerCompat(activity.window, view).hide(WindowInsetsCompat.Type.ime())
}
In your case, you call use it like this:
tvSubmitToFirestore.setOnClickListener { view ->
hideKeyboard(view, this) // 'this' refers to MainActivity
}

Related

How do I display a snackbar over/on top of the soft keyboard. Upon clicking the button, success() and error() displays behind the keyboard

Here is my code for clicking the submitButton
submitButton.setOnClickListener {
//when submit is clicked go through verification
//verification would include
//displaying a toast error message
//if pin input is shorter than requiredLength
// validate()
//same idea as above but this time using a snackbar in place of toast
verify()
}
This is my verify method with a closeKeyboard method that I dislike using. I would rather have the snackbar display over the keyboard - see https://www.youtube.com/watch?v=eifc44nH1xE. However, I would like to close the keyboard when clicking out of the view for ex... after you typed in digits and click on blank screen(the parent)
private fun verify() {
val requiredLength = 4
val editTextView: EditText = findViewById(R.id.pinInput)
val textLength = editTextView.text.length
if (textLength != requiredLength) {
error()
} else {
success()
}
closeKeyboard()
}
This is my snackbar success method. I have another one for error(looks identical)
private fun success() {
val view = findViewById<View>(R.id.root_layout)
val snackTime = Snackbar.LENGTH_INDEFINITE
val snacking = getString(R.string.success_message)
val snackbarsuccess = Snackbar.make(view, snacking, snackTime)
snackbarsuccess.show()
snackbarsuccess.setAction("Close", View.OnClickListener { snackbarsuccess.dismiss() })
snackbarsuccess.setActionTextColor(ContextCompat.getColor(this, R.color.teal_200))
val text =
snackbarsuccess.view.findViewById((com.google.android.material.R.id.snackbar_text)) as TextView
text.setTextColor(ContextCompat.getColor(this, R.color.white))
}
I found this code and pasted it. The problem with this code is that it closes the keyboard and you would then have to click back into the edit text view to display the keyboard. I don't like this. I hope that makes sense. When I am clicking out to the side, it switches the keyboard to a different style. I don't like this.
private fun closeKeyboard() {
val view: View = this.currentFocus!!
if (view != null) {
val imm: InputMethodManager =
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}

How to use SetOnClickListener on a programmatic ScrollView Android Kotlin

I created a scrollView programmaticaly that contains 20 views each with an image and a text.
I have two questions :
1 - is the id assignment correct and is my setOnClickListener correct?
2 - By which method onClick can I know which view of the scrollView the user has clicked?
See my code below
private var integerList: MutableList<Int>? = mutableListOf()
private var cellNo: MutableList<String>? = mutableListOf()
private var sv_mvmtChoosed = ""
private fun showSpinner() {
/* SCROllL VIEW */
var linearLayout: LinearLayout? = null
linearLayout = findViewById(R.id.linear1)
val layoutInflater = LayoutInflater.from(this)
var randIndex = 0
for (posIndex in 0..19) {
val rand = Random()
randIndex = rand.nextInt(20)
while (integerList!!.contains(randIndex)) {
randIndex = rand.nextInt(20)
}
integerList!!.add(randIndex)
// Create the view...
val view: View = layoutInflater.inflate(R.layout.scroll_bckgrnd, linearLayout, false)
// give it an id
view.id = generateViewId()
view.setOnClickListener(this)
cellNo!!.add(view.id.toString())
println(cellNo)
//... then populate it with image and text
val iv = view.findViewById<ImageView>(R.id.iv)
iv.setImageResource(sv_photoImage[randIndex])
val tv = view.findViewById<TextView>(R.id.tv)
tv.text = sv_photoName[randIndex]
linearLayout?.addView(view)
}
// which view the user did select?
fun onClick(view: View?) {
when (view!!.id) {
??? -> doSomething
}
}
}
Any idea to get me back on track will be welcome.
Its probably better to make a new OnClickListener for every view.
view.setOnClickListener(this)
needs to be this
view.setOnClickListener {
// do something
}
or
view.setOnClickListener(createOnClickListner())
fun createOnClickListner():View.OnClickListener{
return object :View.OnClickListener{
override fun onClick(view : View) {
//do something with the view that was clicked
}
}
}
Thanks a lot avalerio.
I finally found a solution as follow :
I replaced :
// give it an id
view.id = generateViewId()
view.setOnClickListener(this)
cellNo!!.add(view.id.toString())
println(cellNo)
with :
// give it an id
view.id = posIndex
view.setOnClickListener(this)
then I did this :
// the onClickListener for my 20 images/text
override fun onClick(view: View?) {
when (view!!.id) {
// Now de position clicked on the ScrollView
in 0..19 -> didHeSucceeded(view!!.id)
}
}
And use the result:
private fun didHeSucceeded(scrllPos: Int) {
// TODO: close de scrollView, how ? :-)
spinnerChoice = nameOfTechScrollVw[scrllPos]
succes = (!allreadyChoosedArray.contains(spinnerChoice)) && (currentArray.contains(spinnerChoice
))
if (succes) {
...
...
}
It works perfectly

Issue with custom dialog after removing Kotlin extension from the Android project

I have a custom dialog in my android project and it was working fine. After I removed kotlin extension from the project, I have modified my code as follows but there is some issue with the Views in the custom dialog. Codes etTitle.visibility = View.GONE and val newRequest = etDetail.text.toString() didn't work as I expected. It didn't hide the view etTitle and the value in the EditText etDetail is not picked also, it always returns emplty even when there is some value.
private lateinit var bindingDialogLayout: CustomDialogBinding
fun specialRequestDialog(currentRequest: String?) {
bindingDialogLayout = CustomDialogBinding.inflate(layoutInflater)
val dialogLayout = layoutInflater.inflate(R.layout.custom_dialog, null)
val etTitle = bindingDialogLayout.etTitle
val etDetail = bindingDialogLayout.etDetails
etTitle.visibility = View.GONE
etDetail.setText(currentRequest)
MaterialAlertDialogBuilder(this)
.setTitle("What is your special request?")
.setCancelable(false)
.setPositiveButton("Save") { dialog, which ->
val newRequest = etDetail.text.toString()
if (newRequest.isEmpty()) {
showErrorSnackBar("Type in if you have any special request, else hit cancel", true)
} else {
addButton.visibility = View.GONE
deleteButton.visibility = View.VISIBLE
}
}
.setNegativeButton("Cancel") { dialog, which ->
dialog?.dismiss()
}
.setView(dialogLayout)
.show()
}
You set the wrong view to the dialog.
Use this instead:
.setView(bindingDialogLayout.root)

android - how to update mutablieLiveData from another class

I've a mutableLiveData of list of items in my fragment and I have a custom dialog that I pass a single item from this list to it . this is my code:
adapter.itemPosPriceListener.observe(this, Observer { pos ->
activity?.let { act ->
val dialog = DialogRoomPrices(act)
dialog.item.value = it.get(pos)
}
})
this is my dialog :
class DialogRoomPrices(act: Activity) {
private var dialog: Dialog
private var act: Activity
val item = MutableLiveData<RoomItem>()
init {
dialog = Dialog(act, R.style.DialogAnimation)
dialog.setContentView(R.layout.dialog_room_prices)
this.act = act
makeDialog()
val lp = WindowManager.LayoutParams()
lp.copyFrom(dialog.window?.attributes)
lp.width = WindowManager.LayoutParams.MATCH_PARENT
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
dialog.getWindow()?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
dialog.show()
dialog.window?.attributes = lp
}
private fun makeDialog() {
item?.value?.let { row ->
dialog.et_roomp_price_paye.setText(row.price_paye)
dialog.et_roomp_price_akhathafte.setText(row.price_akhathafte)
////and 10 more rows of these
}
dialog.bt_next.setOnClickListener {
/////need to update the item and observe it in my fragment
dialog.dismiss()
}
}
as you can see ,dialog has a form and after filling the data and clicking on submit button , I need to update my item in fragment class .
the question is , how can I update the this item and notify my fragment's item about it ?
I don't see the whole code, but such communication can be done simply with a callback.
Solution will look like
class DialogRoomPrices(act: Activity) {
interface Listener() {
fun onNext(data: SomeData)
}
private var listener: Listener?
private var dialog: Dialog
private var act: Activity
val item = MutableLiveData<RoomItem>()
...
dialog.bt_next.setOnClickListener {
val dataToBeSetToHostingFragment = getData()
listener?.onNext(dataToBeSetToHostingFragment)
dialog.dismiss()
}
In the Fragment
class HostingFragment(): Listener {
adapter.itemPosPriceListener.observe(this, Observer { pos ->
activity?.let { act ->
val dialog = DialogRoomPrices(act)
dialog.item.value = it.get(pos)
dialog.listener = object : DialogRoomPrices.Listener {
override onNext(data: SomeData) {
// Assign data to your liveData, force update recycler view or do any other action you want to
}
}
}
})

Dismissing Anko Dialog in onClickListener

I would like to dismiss Anko Dialog when pressing the button defined in my customLayout
val dialog = alert {
val view = layoutInflater.inflate(R.layout.match_stats, null)
val closeButton = view.findViewById<ImageButton>(R.id.closeButton)
closeButton.setOnClickListener { _ -> dialog.dismiss()}
customView = view
}
dialog.show()
I tried above code, unfortunately, I can’t get a reference to dialog in my onClickListener. Do you have any idea how to solve it?
You could declare variable before and assign null:
var dialog: DialogInterface? = null
dialog = alert {
val view = layoutInflater.inflate(R.layout.match_stats, null)
val closeButton = view.findViewById<ImageButton>(R.id.closeButton)
closeButton.setOnClickListener { _ -> dialog?.dismiss()}
customView = view
}.show()
Of course now your dialog variable is muttable and optional.

Categories

Resources