Skip to content

Instantly share code, notes, and snippets.

@alorma
Created June 7, 2018 16:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alorma/b1c354b4fd0491edf643afc91f610de8 to your computer and use it in GitHub Desktop.
Save alorma/b1c354b4fd0491edf643afc91f610de8 to your computer and use it in GitHub Desktop.
import android.content.Context
import android.content.DialogInterface
import android.support.annotation.LayoutRes
import android.support.v7.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import com.alorma.R
@DslMarker
annotation class DialogDsl
@DialogDsl
sealed class ButtonBuilder(private val context: Context) {
lateinit var title: Any
internal lateinit var action: (DialogInterface) -> Unit
internal fun parseTitle(title: Any): String {
return when (title) {
is String -> title
is Int -> context.resources.getString(title)
else -> title.toString()
}
}
fun build(builder: AlertDialog.Builder) =
builder.createButton(parseTitle(title), DialogInterface.OnClickListener { dialog, _ ->
action(dialog)
})
abstract fun AlertDialog.Builder.createButton(parseTitle: String,
listener: DialogInterface.OnClickListener)
@DialogDsl
class Positive(context: Context) : ButtonBuilder(context) {
override fun AlertDialog.Builder.createButton(parseTitle: String,
listener: DialogInterface.OnClickListener) {
setPositiveButton(parseTitle(title), listener)
}
}
@DialogDsl
class Negative(context: Context) : ButtonBuilder(context) {
override fun AlertDialog.Builder.createButton(parseTitle: String,
listener: DialogInterface.OnClickListener) {
setNegativeButton(parseTitle(title), listener)
}
}
@DialogDsl
class Neutral(context: Context) : ButtonBuilder(context) {
override fun AlertDialog.Builder.createButton(parseTitle: String,
listener: DialogInterface.OnClickListener) {
setNeutralButton(parseTitle(title), listener)
}
}
}
@DialogDsl
sealed class DialogBuilder(internal val context: Context) {
private fun createDialog(): AlertDialog.Builder =
AlertDialog.Builder(context, R.style.Theme_AppCompat_Light_Dialog_Alert)
fun build(): AlertDialog = configureDialog(createDialog())
abstract fun configureDialog(builder: AlertDialog.Builder): AlertDialog
@DialogDsl
class NativeBasicDialog(context: Context) : DialogBuilder(context) {
internal var title: String? = null
internal var message: String = ""
private var actionYes: ButtonBuilder? = null
private var actionNo: ButtonBuilder? = null
private var actionNeutral: ButtonBuilder? = null
override fun configureDialog(builder: AlertDialog.Builder): AlertDialog = builder.apply {
setTitle(title)
setMessage(message)
actionYes?.build(this)
actionNo?.build(this)
actionNeutral?.build(this)
}.create()
fun confirm(title: Any, function: (DialogInterface) -> Unit) {
this.actionYes = ButtonBuilder.Positive(context).apply {
this.title = title
this.action = function
}
}
fun cancel(title: Any, function: (DialogInterface) -> Unit) {
this.actionNo = ButtonBuilder.Negative(context).apply {
this.title = title
this.action = function
}
}
fun neutral(title: Any, function: (DialogInterface) -> Unit) {
this.actionNeutral = ButtonBuilder.Neutral(context).apply {
this.title = title
this.action = function
}
}
}
@DialogDsl
class CustomBodyDialog(context: Context) : DialogBuilder(context) {
@LayoutRes
var layout: Int = 0
private lateinit var bind: View.(AlertDialog) -> Unit
override fun configureDialog(builder: AlertDialog.Builder): AlertDialog {
val view = LayoutInflater.from(context).inflate(layout, null, false)
return builder.apply {
setView(view)
}.create().apply {
view.bind(this)
}
}
fun onBind(function: View.(AlertDialog) -> Unit) {
this.bind = function
}
}
}
private fun <T : DialogBuilder> dialogDsl(dialogBuilder: T, block: T.() -> Unit): AlertDialog =
dialogBuilder.apply(block).build()
@DialogDsl
fun nativeBasicDialog(context: Context, block: DialogBuilder.NativeBasicDialog.() -> Unit): AlertDialog =
dialogDsl(DialogBuilder.NativeBasicDialog(context), block)
@DialogDsl
fun customDialogDsl(context: Context, block: DialogBuilder.CustomBodyDialog.() -> Unit): AlertDialog =
dialogDsl(DialogBuilder.CustomBodyDialog(context), block)
class DialogShowCase {
fun openBasicDialog(context: Context) {
nativeBasicDialog(context) {
title = "Basic dialog"
message = "Basic dialog message"
confirm("Aceptar") {
Toast.makeText(context, "Basic: YES", Toast.LENGTH_SHORT).show()
}
cancel("Cancelar") {
Toast.makeText(context, "Basic: NO", Toast.LENGTH_SHORT).show()
}
neutral("Neutral") {
Toast.makeText(context, "Basic: NEUTRAL", Toast.LENGTH_SHORT).show()
}
}.show()
}
fun openCustomDialog(context: Context) {
customDialogDsl(context) {
layout = R.layout.dialog_pin
onBind { dialog ->
positive_button.setOnClickListener {
Toast.makeText(context, pin_editText.text.toString(), Toast.LENGTH_SHORT).show()
}
negative_button.setOnClickListener {
dialog.dismiss()
}
}
}.show()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment