Created
May 16, 2019 15:25
-
-
Save carranca/7e3414622ad7fc6ef375c8cd8dc840c9 to your computer and use it in GitHub Desktop.
Programmatically set Select Handler color of TextView/EditText
This file contains 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
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