Despite a lot of searches and trials, I can't avoid my AlertDialog to close if my EditText is empty... I saw that it was a current issue on StackOverflow with a lot of responses but when I try it, it doesn't work...
Here is my Kotlin code, thanks for your help...
import androidx.appcompat.app.AlertDialog
import android.content.DialogInterface
private fun showMyEditextDialog() {
val alertDialog = AlertDialog.Builder(this)
val view = layoutInflater.inflate(R.layout.my_layout, null)
val myedittext = view.findViewById(R.id.myedittext) as EditText
alertDialog.setTitle(getString(R.string.title))
alertDialog.setView(view)
alertDialog.setCancelable(false)
alertDialog.setPositiveButton(R.string.ok, DialogInterface.OnClickListener { dialogInterface, i ->
var isValid = true
if ( isEmpty(myedittext.text.toString()) ) {
isValid = false
Toast.makeText(this, "empty", Toast.LENGHT_SHORT).show()
}
if ( isValid ) {
Toast.makeText(this, "yeah!", Toast.LENGHT_SHORT).show() }
if ( isValid ) {
dialogInterface.dismiss()
}
})
}
My xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/question" />
<EditText
android:id="#+id/myedittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal" />
</LinearLayout>
If I enter a value, I've got my "yeah" message.
If I don't enter a value, I've got my "empty" message but my dialog dismiss...
Thanks for your help,
MT
Use onShow to handle this like below:
val dialog = alertDialog.create()
dialog.setOnShowListener {
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
var isValid = true
if ( isEmpty(myedittext.text.toString()) ) {
isValid = false
Toast.makeText(this#MainActivity, "empty", Toast.LENGTH_SHORT).show()
}
if ( isValid ) {
Toast.makeText(this#MainActivity, "yeah!", Toast.LENGTH_SHORT).show()
dialog.dismiss()
}
}
}
dialog.show()
I'm unsure if there's a way to bypass an alertdialog's buttons' functions. If there is, I've never found it. However, you could go with a much simpler solution. Just create your own "alert" view with an editText and buttons. Set the view to view.setVisibility(View.INVISIBLE) or (View.GONE), and any of its children views will be invisible or gone as well. I generally, when this is necessary, do this with a semi-transparent black background behind the view as the parent; and set that view's visibility back and forth. Then, you can customize the functionality of the buttons and the rest of the view in any way you want.
You need to get the positive button to override the method onclick
you can use this code:
private fun showMyEditextDialog() {
val alertDialog = AlertDialog.Builder(this)
val view = layoutInflater.inflate(R.layout.my_layout, null)
val myedittext = view.findViewById(R.id.myedittext) as EditText
alertDialog.setTitle(getString(R.string.title))
alertDialog.setView(view)
alertDialog.setCancelable(false)
alertDialog.setPositiveButton(R.string.ok, null)
alertDialog.create()
var dialog = alertDialog.create()
dialog.show()
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
var isValid = true
if ( isEmpty(myedittext.text.toString()) ) {
isValid = false
Toast.makeText(this, "empty", Toast.LENGTH_SHORT).show()
}
if ( isValid ) {
Toast.makeText(this, "yeah!", Toast.LENGTH_SHORT).show() }
if ( isValid ) {
dialog.dismiss()
}
}
}
Related
I have a alertdialog that contains a hyperlink, however the hyperlink isn't clickable. It does show as a hyperlink
val termsDialog = AlertDialog.Builder(this#MainActivity)
val termsView = layoutInflater.inflate(R.layout.termsdialog, null)
val termsBox: CheckBox = termsView.findViewById(R.id.termsCheckbox)
val termsMsg = Html.fromHtml("By using this application you accept to our Terms and Conditions and Privacy Policy. \nMore information here")
termsDialog.setTitle("Terms and Conditions")
termsDialog.setView(termsView)
termsDialog.setMessage(termsMsg)
termsDialog.setPositiveButton("OK") { _, _ -> }
termsDialog.setCancelable(false)
termsBox.setOnCheckedChangeListener { compoundButton, _ ->
if (compoundButton.isChecked) {
storeDialogStatus(true)
} else {
storeDialogStatus(false)
}
}
// Automatic show terms dialog when dialog status is not checked
if (!this.getDialogStatus()) {
termsDialog.show()
}
Create a TextView for your message in termsdialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/dialog_textview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Then you must call setMovementMethod(LinkMovementMethod.getInstance()) on your TextView:
val termsDialog = AlertDialog.Builder(context)
val termsView = layoutInflater.inflate(R.layout.termsdialog, null)
val termsMessage: TextView = termsView.findViewById(R.id.dialog_textview)
val termsMsg = Html.fromHtml("By using this application you accept to our Terms and Conditions and Privacy Policy. \nMore information here")
termsDialog.setTitle("Terms and Conditions")
termsDialog.setView(termsView)
termsMessage.setText(termsMsg)
termsMessage.setMovementMethod(LinkMovementMethod.getInstance())
termsDialog.show()
I am trying to get the text of a textInputEditText, which is in a dialog (to be exact the onCreateDialog method in the set positive button section), but it doesn't work. I've read many questions which already are on StackOverflow, but none helped me.
The variable inputAddTunnel in which the text should be saved, is always just equal to "":
private fun getInput(): String {
val inputAddTunnel = this.layoutInflater.inflate(R.layout.dialog_add_vpn_tunnel,null).findViewById<TextInputEditText>(R.id.input_add_tunnel).getText().toString()
return inputAddTunnel
}
The Xml for the dialog is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/input_add_tunnel_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="#string/name_of_vpn">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/input_add_tunnel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"/>
</com.google.android.material.textfield.TextInputLayout>
Edit: Here is the onCreateDialog() method
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = androidx.appcompat.app.AlertDialog.Builder(it)
// Get the layout inflater
val inflater = requireActivity().layoutInflater
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_add_vpn_tunnel, null))
// Add action buttons
.setPositiveButton(R.string.add_vpn_tunnel,
DialogInterface.OnClickListener { dialog, id ->
// Add VPN tunnel
addVpn()
})
.setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
getDialog()?.cancel()
})
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
And this is the addVpn method, which is called in onCreateDialog():
private fun addVpn() {
// TODO test function addVpn(); count doesn't work properly
val count = activity?.getPreferences(AppCompatActivity.MODE_PRIVATE)?.getInt("countTunnels", -1)
val inputAddTunnel = getInput()
// If inputAddTunnel is not equal to "", put it in getPreferences
if(inputAddTunnel != "") { //TODO test if !== is needed, not !=
activity?.getPreferences(AppCompatActivity.MODE_PRIVATE)?.
edit()?.putString("tunnel$count", inputAddTunnel).apply { }
}
// Edit the count in getPreferences to the incremented count
count?.plus(1)
if (count != null) {
activity?.getPreferences(AppCompatActivity.MODE_PRIVATE)?.getInt("countTunnels", count)
}
}
You need to get editext object from dialog view and call getText() method
Edittext edittext= getDialog().getView().findViewbyId(R.id.editText);
edittext.getText(); // for getting textvalue from editetxt
You are re-inflating a brand new view, not querying from the one you already set for your dialog.
You should call findViewById on the root dialog view that you initially inflated. Please share your onCreateDialog method for more help.
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 implemented a "Don't show again" option to my Alert Dialog, but it's not working as intended:
All the other questions are 6-7 years old and in java, and since I am completely new to programming I only know the basics of kotlin as of right now..
fun showDialog() {
val dialogBuilder = AlertDialog.Builder(context)
val inflater = requireActivity().layoutInflater;
dialogBuilder.setView(inflater.inflate(R.layout.alert, null))
dialogBuilder.setMessage("Please always put the total on the bottom right corner. An example is shown below.")
dialogBuilder.setPositiveButton("Alright, got it!",
DialogInterface.OnClickListener { dialog, whichButton ->
pb.visibility = View.VISIBLE
checkPermission(Manifest.permission.CAMERA,CAMERA_PERMISSION_CODE)
startActivityForResult(receiptsViewModel.cameraIntent(requireActivity()),REQUEST_CODE_KAMERA)
})
val mainView: View = inflater.inflate(R.layout.alert, null)
checkBox = mainView.findViewById<View>(R.id.checkBox) as CheckBox
val b = dialogBuilder.create()
b.show()
checkBox.setOnCheckedChangeListener { compoundButton, b ->
if (compoundButton.isChecked) {
storeDialogStatus(true)
} else {
storeDialogStatus(false)
}
}
if (dialogStatus) {
b.hide()
} else {
b.show()
}
}
private fun storeDialogStatus(isChecked: Boolean) {
val mSharedPreferences = requireActivity().getSharedPreferences("CheckItem", AppCompatActivity.MODE_PRIVATE)
val mEditor = mSharedPreferences.edit()
mEditor.putBoolean("item", isChecked)
mEditor.apply()
}
private val dialogStatus: Boolean
private get() {
val mSharedPreferences = requireActivity().getSharedPreferences("CheckItem",
AppCompatActivity.MODE_PRIVATE
)
return mSharedPreferences.getBoolean("item", false)
}
The problem I see is that the checkbox that you're adding a listener to is for a layout that you're not using. You inflated a layout and set that as your dialog view. Then you inflate a second copy of the layout and set a listener on the checkbox in that unused second layout.
A few other tips, but these aren't things that are preventing it from working. They'll just make your code clearer:
You can chain Builder calls so you don't have to keep putting dialogBuilder. and you don't even have to store it in a variable.
findViewById<View> can be changed to findViewById<CheckBox> so you don't have to cast its result to CheckBox.
You can return early from the function if the dialog isn't needed rather than creating the dialog, showing it, and then immediately hiding it.
Instead of using if (someBoolean) doSomething(true) else doSomething(false) you can simplify to doSomething(someBoolean).
private fun startCamera() {
pb.visibility = View.VISIBLE
checkPermission(Manifest.permission.CAMERA,CAMERA_PERMISSION_CODE)
startActivityForResult(
receiptsViewModel.cameraIntent(requireActivity()),
REQUEST_CODE_KAMERA
)
}
fun showDialog() {
if (dialogStatus) {
startCamera()
return
}
val mainView = requireActivity().layoutInflater.inflate(R.layout.alert, null)
checkBox = mainView.findViewById<CheckBox>(R.id.checkBox)
checkBox.setOnCheckedChangeListener { compoundButton, b ->
storeDialogStatus(compoundButton.isChecked)
}
AlertDialog.Builder(context)
.setView(mainView)
.setMessage("Please always put the total on the bottom right corner. An example is shown below.")
.setPositiveButton("Alright, got it!") { _, _ -> startCamera() }
.create()
.show()
}
I also find it odd that you have a property for checkBox that couldn't possibly be useful outside this function. You should probably remove the property.
Also, you should look into using DialogFragment instead of a bare Dialog. There are issues with bare Dialogs, such as them disappearing after a screen rotation. The official documentation explains how to use DialogFragment. I will admit, though, that I think DialogFragment is kind of convoluted to use, especially for a new Android programmer.
Your logic seems to be faulty. This piece of code does not work as intended:
if (dialogStatus) {
b.hide()
} else {
b.show()
}
You should not create the dialog at all if the user has opted out. Please try this modified code:
fun showDialog() {
if (dialogStatus) {
return
}
val dialogBuilder = AlertDialog.Builder(context)
val inflater = requireActivity().layoutInflater
dialogBuilder.setView(inflater.inflate(R.layout.alert, null))
.setMessage("Please always put the total on the bottom right corner. An example is shown below.")
.setPositiveButton("Alright, got it!",
DialogInterface.OnClickListener { dialog, whichButton ->
pb.visibility = View.VISIBLE
checkPermission(Manifest.permission.CAMERA, CAMERA_PERMISSION_CODE)
startActivityForResult(
receiptsViewModel.cameraIntent(requireActivity()),
REQUEST_CODE_KAMERA
)
})
dialogBuilder.create().show()
val mainView: View = inflater.inflate(R.layout.alert, null)
checkBox = mainView.findViewById<CheckBox>(R.id.checkBox)
checkBox.setOnCheckedChangeListener { compoundButton, b ->
if (compoundButton.isChecked) {
storeDialogStatus(true)
} else {
storeDialogStatus(false)
}
}
}
I have this code:
var firstKitList = mutableListOf<String>("test", "potato", "another item")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kit_list)
val mainKitList = kitListView
val mainListViewAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, firstKitList)
mainKitList.adapter = mainListViewAdapter
newKitListBtn.setOnClickListener {
// Handler code here.
val intent = Intent(this, NewKitListActivity::class.java)
startActivity(intent);
}
}
For this layout.
How do I go around for when I click the button, to show up an alert dialog for me too add a name (as if I was creating an item to be added to that list) and then go to the next activity? (this part is already created as you can see on the code)
I created function which hold alert dialog with editText. When your click on save name will be stored in multableList and redirected to new activity.
Modified Code
var firstKitList = mutableListOf<String>("test", "potato", "another item")
// Mutable List for holding names
val nameList = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_kit_list)
val mainKitList = kitListView
val mainListViewAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, firstKitList)
mainKitList.adapter = mainListViewAdapter
newKitListBtn.setOnClickListener {
// Show Alert Dialog
showNewNameDialog()
}
}
Alert Dialog Function
fun showNewNameDialog() {
val dialogBuilder = AlertDialog.Builder(this)
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.custom_dialog, null)
dialogBuilder.setView(dialogView)
val editText = dialogView.findViewById<EditText>(R.id.editTextName)
dialogBuilder.setTitle("Custom dialog")
dialogBuilder.setMessage("Enter Name Below")
dialogBuilder.setPositiveButton("Save", { dialog, whichButton ->
//do something with edt.getText().toString();
// Add Name in list
nameList.add(editText.text.toString())
// Handler code here.
val intent = Intent(this, NewKitListActivity::class.java)
startActivity(intent);
})
dialogBuilder.setNegativeButton("Cancel", { dialog, whichButton ->
//pass
})
val b = dialogBuilder.create()
b.show()
}
Custom Dialog Layout: custom_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<EditText
android:id="#+id/editTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" />
</LinearLayout>
I changed the code from Rajesh Dalsaniya's answer to be a bit more concise using kotlin's features:
fun showNewNameDialog(activity: Activity) {
AlertDialog.Builder(activity).apply {
val dialogView = activity.layoutInflater.inflate(R.layout.custom_dialog, null)
val editText = dialogView.findViewById<EditText>(R.id.editTextName)
setView(dialogView)
setTitle("Custom dialog")
setMessage("Enter Name Below")
setPositiveButton("Save") { _, _ ->
//do something with edt.getText().toString();
// Add Name in list
activity.nameList.add(editText.text.toString())
// Handler code here.
val intent = Intent(activity, NewKitListActivity::class.java)
activity.startActivity(intent);
}
setNegativeButton("Cancel") { _, _ ->
//pass
}
}.create().show()
}
The xml stays:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<EditText
android:id="#+id/editTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" />
</LinearLayout>