Kotlin extension functions for Views

A collection of Kotlin extension methods that simplify many common tasks related to Android Views.

fun View.show() : View {
    this.visibility = View.VISIBLE
    return this
}

fun View.hide() : View {
    this.visibility = View.GONE
    return this
}

fun View.enable() : View {
    this.isEnabled = true
    return this
}

fun View.disable() : View {
    this.isEnabled = false
    return this
}

fun ViewGroup.inflate(resourceId: Int) =
    LayoutInflater.from(this.context).inflate(resourceId, this, false)

fun TextView.setHtmlResourceId(resId: Int) {
    var tagHandler: Html.TagHandler? = null
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        tagHandler = Html.TagHandler { opening, tag, output, xmlReader ->
            if (tag == "ul" && !opening) output.append("\n")
            if (tag == "li" && opening) output.append("\n\t• ")
        }
    }
    val html = resources.openRawResource(resId).bufferedReader().use(BufferedReader::readText)
    this.text = HtmlCompat.fromHtml(html, 0, null, tagHandler)
}

fun EditText.asString() = this.text.toString()

To open a website

/**
 * Opens a link in a Chrome Custom Tab. Basically,
 * a customizable default browser window.
 */
fun Context.openLink(link: String?): Boolean {
    try {
        val builder = CustomTabsIntent.Builder()
        builder.setToolbarColor(ColorBuilder.getColor(ColorType.OVERLAY))
        val customTabsIntent = builder.build()
        customTabsIntent.launchUrl(this, Uri.parse(link))
        return true
    } catch (e: Exception) {
        Log.e("", "Failed to open link in Custom Tab", e)
        try {
            ContextCompat.startActivity(this, Intent(Intent.ACTION_VIEW, Uri.parse(link)), null)
            return true
        } catch (e1: Exception) {
            Log.e("", "Failed to link using Intent.ACTION_VIEW", e)
        }
    }
    return false
}

Snackbar & Toasts

fun AppCompatActivity.toast(msg: String) =
	Toast.makeText(this, msg, Toast.LENGTH_LONG).show()

fun AppCompatActivity.toast(@StringRes msg: Int) =
	Toast.makeText(this, msg, Toast.LENGTH_LONG).show()

fun AppCompatActivity.snackbar(view: View, msg: String) =
	Snackbar.make(view, msg, Snackbar.LENGTH_LONG).show()

fun AppCompatActivity.snackbar(msg: String) =
	Snackbar.make(window.decorView, msg, Snackbar.LENGTH_LONG).show()

Keyboard

fun View.showKeyboard() {
    this.requestFocus()
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
}

fun View.hideKeyboard() {
    val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.hideSoftInputFromWindow(windowToken, 0)
}

fun EditText.onDone(callback: (Editable?) -> Unit) : EditText {
    setOnEditorActionListener { _, actionId, _ ->
        if (actionId == EditorInfo.IME_ACTION_DONE
                || actionId == EditorInfo.IME_ACTION_GO
                || actionId == EditorInfo.IME_ACTION_SEND
                || actionId == EditorInfo.IME_ACTION_SEARCH
                || actionId == EditorInfo.IME_ACTION_NEXT
                ) {
            callback.invoke(this.text)
            true
        } else {
            false
        }
    }
    return this
}

Text input

fun EditText.onTextChanged(callback: (Editable?) -> Unit) : EditText {
    this.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            callback.invoke(s)
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

        }

    })
    return this
}

fun EditText.onLeave(callback: (Editable?) -> Unit): EditText {
    setOnFocusChangeListener { _, hasFocus ->
        if (!hasFocus) {
            callback.invoke(this.text)
        }
    }
    return this
}