Skip to content

Instantly share code, notes, and snippets.

@carranca
Created May 16, 2019 15:25
Show Gist options
  • Save carranca/7e3414622ad7fc6ef375c8cd8dc840c9 to your computer and use it in GitHub Desktop.
Save carranca/7e3414622ad7fc6ef375c8cd8dc840c9 to your computer and use it in GitHub Desktop.
Programmatically set Select Handler color of TextView/EditText
package com.squareup.util.android
import android.graphics.PorterDuff
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import timber.log.Timber
/**
* This uses light-graylisted Android APIs.
* Verified that it works in devices running APIs 21 and 28
*/
fun TextView.setSelectHandleColor(@ColorInt color: Int) {
try {
// Retrieve a reference to this text field's android.widget.Editor
val editor = getEditor()
handles.forEach {
// Retrieve the field pointing to the drawable currently being used for the select handle
val resourceField = TextView::class.java.getDeclaredField(it.resourceFieldName)
resourceField.isAccessible = true
// Retrieve the drawable resource from that field
val drawableId = resourceField.getInt(this)
val drawable = ContextCompat.getDrawable(context, drawableId)
// Apply a filter on that drawable with the desired colour
drawable?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
// Override the drawable being used by the Editor with our coloured drawable
val selectHandleField = editor.javaClass.getDeclaredField(it.selectHandleFieldName)
selectHandleField.isAccessible = true
selectHandleField.set(editor, drawable)
}
} catch (e: Exception) {
// This would be expectable if, in the future, the fields accessed via reflection go from being
// light graylisted to dark graylisted or blacklisted.
// Nothing we can do about it, other than not crash :)
Timber.w(e)
}
}
private class HandleDescriptor(
val resourceFieldName: String,
val selectHandleFieldName: String
)
private val handles = arrayOf(
HandleDescriptor(
resourceFieldName = "mTextSelectHandleRes",
selectHandleFieldName = "mSelectHandleCenter"),
HandleDescriptor(
resourceFieldName = "mTextSelectHandleLeftRes",
selectHandleFieldName = "mSelectHandleLeft"),
HandleDescriptor(
resourceFieldName = "mTextSelectHandleRightRes",
selectHandleFieldName = "mSelectHandleRight")
)
private fun TextView.getEditor() : Any {
val editorField = TextView::class.java.getDeclaredField("mEditor")
editorField.isAccessible = true
return editorField.get(this)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment