Last active
July 15, 2021 10:47
-
-
Save truedem/536aebef8d36edcd4ad902c7b1ff5fd6 to your computer and use it in GitHub Desktop.
Universal Android Confirmation Dialog
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object AppCfg { | |
const val CONFIRMATION_PARAM = "resultKey" | |
const val CONFIRMATION_TITLE = "title" | |
const val CONFIRMATION_TEXT = "content" | |
const val CONFIRMATION_POSITIVE = "positiveLabel" | |
const val CONFIRMATION_NEGATIVE = "negativeLabel" | |
const val CONFIRMATION_POSITIVE_ICON = "positiveIcon" | |
const val IS_DELETED = "IS_DELETED" | |
const val IS_EXPORTED = "IS_EXPORTED" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ConfirmationDialog : BaseDialogFragment(), View.OnClickListener { | |
private val TAG = ConfirmationDialog::class.java.canonicalName | |
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { | |
val view = requireActivity().layoutInflater.inflate(R.layout.dialog_confirmation, null) | |
val builder = MaterialAlertDialogBuilder(requireContext()) | |
builder.setView(view) | |
bindText() | |
val dialog: Dialog = builder.create() | |
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) | |
// dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) | |
return dialog | |
} | |
private fun bindText() { | |
with(dialog!!) { | |
findViewById<TextView>(R.id.titleConfirmation).text = arguments?.getString(AppCfg.CONFIRMATION_TITLE) | |
findViewById<TextView>(R.id.textConfirmation).let { | |
it.isVisible = arguments?.getString(AppCfg.CONFIRMATION_TEXT) != null | |
it.text = arguments?.getString(AppCfg.CONFIRMATION_TEXT) | |
} | |
findViewById<MaterialButton>(R.id.buttonConfirmation).let { | |
it.text = arguments?.getString(AppCfg.CONFIRMATION_POSITIVE) ?: getString(R.string.btn_delete) | |
it.setOnClickListener(this@ConfirmationDialog) | |
} | |
findViewById<MaterialButton>(R.id.buttonCancelConfirmation).let { btn -> | |
btn.text = arguments?.getString(AppCfg.CONFIRMATION_NEGATIVE) ?: getString(R.string.btn_cancel) | |
arguments?.getInt(AppCfg.CONFIRMATION_POSITIVE_ICON)?.let { | |
if (it > 0) btn.setIconResource(it) | |
} | |
btn.setOnClickListener(this@ConfirmationDialog) | |
} | |
} | |
} | |
override fun onClick(v: View?) { | |
if (BuildConfig.DEBUG) Log.e(TAG, "Sending results back: " + arguments?.getString(AppCfg.CONFIRMATION_PARAM)) | |
sendResult(key = arguments?.getString(AppCfg.CONFIRMATION_PARAM) ?: "", v?.id == R.id.buttonConfirmation) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<androidx.appcompat.widget.LinearLayoutCompat | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/confirmationLayout" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="vertical"> | |
<TextView | |
android:id="@+id/titleConfirmation" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_margin="16dp" | |
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" | |
android:text="Are you sure?" /> | |
<TextView | |
android:id="@+id/textConfirmation" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_margin="16dp" | |
android:textSize="18sp" | |
android:text="Are you sure you want to do it?" /> | |
<androidx.appcompat.widget.LinearLayoutCompat | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_margin="16dp" | |
android:orientation="horizontal"> | |
<Button | |
android:id="@+id/buttonCancelConfirmation" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_weight="1" | |
android:elevation="0dp" | |
android:layout_marginEnd="16dp" | |
app:icon="@drawable/ic_close_circle_outline" | |
android:text="cancel" | |
style="@style/Widget.MaterialComponents.Button.OutlinedButton.Icon" /> | |
<com.google.android.material.button.MaterialButton | |
android:id="@+id/buttonConfirmation" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
app:iconGravity="end" | |
app:icon="@drawable/ic_trash_can_outline" | |
android:text="confirm" /> | |
</androidx.appcompat.widget.LinearLayoutCompat> | |
</androidx.appcompat.widget.LinearLayoutCompat> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
super.onViewCreated(view, savedInstanceState) | |
getResult<Boolean>(AppCfg.IS_DELETED) { deleteItem(it) } | |
getResult<Boolean>(AppCfg.IS_EXPORTED) { exportItem(it) } | |
} | |
fun onDeleteButtonClick() { | |
navigate(R.id.action_global_confirmationDialog, Bundle().also { | |
it.putString(AppCfg.CONFIRMATION_PARAM, AppCfg.IS_DELETED) | |
it.putString(AppCfg.CONFIRMATION_TITLE, "Delete this contanct?") | |
it.putString(AppCfg.CONFIRMATION_TEXT, "Deleting the contact will also remove their images, history.") | |
it.putString(AppCfg.CONFIRMATION_POSITIVE, "ok") | |
it.putString(AppCfg.CONFIRMATION_NEGATIVE, "nah") | |
it.putInt(AppCfg.CONFIRMATION_POSITIVE_ICON, R.drawable.ic_alert_outlined) | |
}) | |
} | |
fun deleteItem(how: Boolean) { | |
if (how) Log.e("ConfirmedActionDialog", "Confirmed, may proceed") | |
else Log.e("ConfirmedActionDialog", "Cancelled, forget it") | |
} | |
fun exportItem(how: Boolean) { | |
// see above | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun <T> Fragment.sendResult(key: String, value: T) { | |
with(findNavController()) { | |
previousBackStackEntry?.savedStateHandle?.set(key, value) | |
// to handle screen rotation, otherwise getResult with ID works | |
currentBackStackEntry?.savedStateHandle?.set(key, value) | |
navigateUp() | |
} | |
} | |
// cannot handle screen rotation with opened dialog | |
fun <T> Fragment.getResult(key: String, observer: Observer<T>) { | |
val savedStateHandle = findNavController().currentBackStackEntry?.savedStateHandle ?: return | |
savedStateHandle.getLiveData<T>(key).observe(viewLifecycleOwner, observer) | |
} | |
fun <T> DialogFragment.getResult(key: String, observer: Observer<T>) { | |
val savedStateHandle = findNavController().currentBackStackEntry?.savedStateHandle ?: return | |
savedStateHandle.getLiveData<T>(key).observe(this, observer) | |
} | |
// entry = R.id.myScreen from nav xml map | |
fun <T> Fragment.getResult(entry: Int, key: String, observer: Observer<T>) { | |
val savedStateHandle = findNavController().getBackStackEntry(entry).savedStateHandle ?: return | |
savedStateHandle.getLiveData<T>(key).observe(viewLifecycleOwner, observer) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Notice the click listeners in the dialog - there is a potential for memory leaks. Dispose them on dismiss maybe.