ImageView in first alert dialog opens second dialog to change an imageResource of the ImageView in the first dialog. However I don't know how to make connection between two alert dialogs
Both have different xml layouts, so I assume that in second dialog I should make a reference to the layout of the first dialog
private fun editItemDialog() {
val dialogBuilder1 = AlertDialog.Builder(this)
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.edit_dialog, null)
dialogBuilder1.setView(dialogView)
var editIconButton = dialogView.findViewById<View>(R.id.editIcon) as ImageView
editIconButton.setOnClickListener{
showIconDialog()
}
dialogBuilder1.setTitle("Edit mode")
dialogBuilder1.setPositiveButton("Save") { _, _ ->
//sth
}
dialogBuilder1.setNegativeButton("Cancel") { _, _ ->
//sth
}
val b = dialogBuilder1.create()
b.show()
}
private fun showIconDialog() {
val dialogBuilder = AlertDialog.Builder(this)
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.icons, null)
dialogBuilder.setView(dialogView)
//examplary two icons to select
var travelRB = dialogView.findViewById<View>(R.id.travel) as RadioButton
var travRB = dialogView.findViewById<View>(R.id.travel) as RadioButton
dialogBuilder.setTitle("Icon dialog")
dialogBuilder.setMessage("Select an icon")
dialogBuilder.setPositiveButton("Save") { _, _ ->
//here I would like to change an icon of the ImageView, for example:
editIconButton.setImageResource(R.id.travel)
dialogBuilder.setNegativeButton("Cancel") { _, _ ->
//sth
}
val b = dialogBuilder.create()
b.show()
}
You can add a callback to the second dialog
fun showIconDialog(callback : (Drawable) -> Unit) {
//code
callback.invoke(someDrawable)
}
And on the first one you just do this:
showIconDialog() { someDrawable ->
//code to change the layout src icon
}
Related
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)
I tried to follow solid principles and want to make my code better. So I want to separate the function that may not be used in some problems.
this is the code that I already to separate but still redundant
private lateinit var dialogView : View
private lateinit var b : AlertDialog
override fun modalDialog(
view:Int,
listener: bodyModalDialog, submitButtonModalDialog: submitButtonModalDialog,
btnSubmit:Int,
btnCancel:Int) {
val dialogBuilder = AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert)
val inflater = this.layoutInflater
dialogView = inflater.inflate(view, null)
dialogBuilder.setView(dialogView)
dialogBuilder.setCancelable(false)
var uiSubmitButton = dialogView.findViewById<View>(btnSubmit)
var uiCancelButton = dialogView.findViewById<View>(btnCancel)
listener.bodyDialog(dialogView)
uiSubmitButton.setOnClickListener {
submitButtonModalDialog.submitButton(dialogView)
b.cancel()
}
uiCancelButton.setOnClickListener {
b.cancel()
}
b = dialogBuilder.create()
b.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
b.show()
}
override fun modalDialogNoBody(
view:Int,
listener: submitButtonModalDialog,
btnSubmit:Int,
btnCancel:Int) {
val dialogBuilder = AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert)
val inflater = this.layoutInflater
dialogView = inflater.inflate(view, null)
dialogBuilder.setView(dialogView)
dialogBuilder.setCancelable(false)
var uiSubmitButton = dialogView.findViewById<View>(btnSubmit)
var uiCancelButton = dialogView.findViewById<View>(btnCancel)
uiSubmitButton.setOnClickListener {
listener.submitButton(dialogView)
b.cancel()
}
uiCancelButton.setOnClickListener {
b.cancel()
}
b = dialogBuilder.create()
b.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
b.show()
}
from that code I tried to separate when the problem need the body and some of them not. So if i let them can access the body it will be just empty so I separate like that. But, the code are redundant becouse it write the same code with one of them there is no body. So i tried to make one of them just take the other code and add body procedure, but I have no idea how to do that. I tried to make an object so when it called true then means there is no body and if false there is body like this code
object Modal{
fun isNoBody(view:Int,
listener: submitButtonModalDialog,
btnSubmit:Int,
btnCancel:Int):Boolean{
val dialogBuilder = AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert)
val inflater = this.layoutInflater
dialogView = inflater.inflate(view, null)
dialogBuilder.setView(dialogView)
dialogBuilder.setCancelable(false)
var uiSubmitButton = dialogView.findViewById<View>(btnSubmit)
var uiCancelButton = dialogView.findViewById<View>(btnCancel)
uiSubmitButton.setOnClickListener {
listener.submitButton(dialogView)
b.cancel()
}
uiCancelButton.setOnClickListener {
b.cancel()
}
b = dialogBuilder.create()
b.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
b.show()
return true
}
}
but it won't work because AlertDialog and View can't be called there. even if I change them to be public. please help
I got my answer. So what I do is I make button and body with two different interfaces. and because if want to use body you need button automatically so I just make it call when it needed only like this
override fun modalDialog(view:Int,
listener: SubmitButtonModalDialog,
btnSubmit:Int,
btnCancel:Int) {
val dialogBuilder = AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert)
val inflater = this.layoutInflater
dialogView = inflater.inflate(view, null)
dialogBuilder.setView(dialogView)
dialogBuilder.setCancelable(false)
var uiSubmitButton = dialogView.findViewById<View>(btnSubmit)
var uiCancelButton = dialogView.findViewById<View>(btnCancel)
uiSubmitButton.setOnClickListener {
listener.submitButton(dialogView)
b.cancel()
}
uiCancelButton.setOnClickListener {
b.cancel()
}
b = dialogBuilder.create()
b.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
b.show()
}
override fun modalDialogBody(listener: BodyModalDialog) {
listener.bodyDialog(dialogView)
}
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
}
}
}
})
I'm trying to make a mobile application with a button that should create an Alert dialog with a search bar in it, However for some reason i can't get the MultiAutoCompleteTextView to work with it as it keeps giving me KotlinNullPointerExceptions. and adding nullpointer safety will just skip the setting the adapter.
addItem.setOnClickListener {
val builder = AlertDialog.Builder(this).create()
val alertview = View.inflate(this, R.layout.content_searchproduct, null)
val itemsList = listOf("Item1","items2","Btem3","btem4")
builder.setView(alertview)
val textfield =builder.findViewById<MultiAutoCompleteTextView>(R.id.textidplaceholder)
val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, itemsList)
textfield!!.setAdapter(adapter)
textfield.threshold = 1
builder.textidplaceholder.setTokenizer(MultiAutoCompleteTextView.CommaTokenizer())
builder.setButton(AlertDialog.BUTTON_POSITIVE,"Add") { _: DialogInterface?, _: Int -> searchProducts(textfield.text.toString()) }
builder.setButton(AlertDialog.BUTTON_NEGATIVE,"Cancel") { _: DialogInterface?, _: Int -> }
builder.show()
}
Do this :
val textfield =alertview.findViewById<MultiAutoCompleteTextView>(R.id.textidplaceholder)
instead of :
val textfield =builder.findViewById<MultiAutoCompleteTextView>(R.id.textidplaceholder)
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.