30

So I changed the style of the Holo Theme with the Holo Colors Generator and Action Bar Style Generator to my own color. But when I select text inside an edit text, the "markers" at the selected positions are still blue. How can I change it?

LeftMiddleRight

Jonik
  • 80,077
  • 70
  • 264
  • 372
jimpic
  • 5,360
  • 2
  • 28
  • 37
  • Related - https://stackoverflow.com/questions/40889455/how-to-change-color-of-the-bubble-under-cursor-on-editview-programmatically – Vadim Kotov Mar 14 '19 at 08:55

7 Answers7

39

The worst part here was to find the "name" for this item and how it is called inside the theme. So I looked through every drawable in the android SDK folder and finally found the drawables named "text_select_handle_middle", "text_select_handle_left" and "text_select_handle_right".

So the solution is simple: Add these drawables with customized design/color to your drawable folder and add them to your theme style definition like:

<style name="MyCustomTheme" parent="@style/MyNotSoCustomTheme">
        <item name="android:textSelectHandle">@drawable/text_select_handle_middle</item>
        <item name="android:textSelectHandleLeft">@drawable/text_select_handle_left</item>
        <item name="android:textSelectHandleRight">@drawable/text_select_handle_right</item>
</style>
jimpic
  • 5,360
  • 2
  • 28
  • 37
  • A little late to the party, but see my answer below on how to do this programmatically. @ant – Jared Rummler Dec 05 '14 at 00:55
  • It will work even if applied only for one EditText or TextView, not only app-wide. – Vadim Kotov Mar 13 '19 at 16:17
  • Just a friendly reminder. The editView could lose response on some Samsung device after applying this solution. We just located it, check [here](https://stackoverflow.com/a/59638335/7155725) – Freddie Jan 15 '20 at 02:40
13

How to do it from code:

try {
    final Field fEditor = TextView.class.getDeclaredField("mEditor");
    fEditor.setAccessible(true);
    final Object editor = fEditor.get(editText);

    final Field fSelectHandleLeft = editor.getClass().getDeclaredField("mSelectHandleLeft");
    final Field fSelectHandleRight =
        editor.getClass().getDeclaredField("mSelectHandleRight");
    final Field fSelectHandleCenter =
        editor.getClass().getDeclaredField("mSelectHandleCenter");

    fSelectHandleLeft.setAccessible(true);
    fSelectHandleRight.setAccessible(true);
    fSelectHandleCenter.setAccessible(true);

    final Resources res = context.getResources();

    fSelectHandleLeft.set(editor, res.getDrawable(R.drawable.text_select_handle_left));
    fSelectHandleRight.set(editor, res.getDrawable(R.drawable.text_select_handle_right));
    fSelectHandleCenter.set(editor, res.getDrawable(R.drawable.text_select_handle_middle));
} catch (final Exception ignored) {
}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
  • 2
    yes, this is one of the possible ways. but reflection is not good idea) – ant Dec 05 '14 at 13:29
  • 1
    What if I want to change only the color of the "mSelectHandleCenter" instead of replace it with a new drawable? How can I achieve that? Unfortunately I'm forced to use reflection because I get the new "accent color" via our API – Niccolò Passolunghi Sep 01 '16 at 15:28
  • 3
    @nicopasso, https://gist.github.com/jaredrummler/2317620559d10ac39b8218a1152ec9d4 You can change that method to only color the center handle by removing the left and right field names in the two arrays. – Jared Rummler Sep 01 '16 at 17:56
  • 1
    @JaredRummler what does your drawable file look like for the text_select_handle_* files? – Pie Nov 13 '16 at 00:02
  • Can this be done from a thread? I am able to get this to work from the onCreateView of the fragment, but not from a thread. Any leads? – Madhavan Malolan Feb 25 '17 at 03:47
  • wish the handles were tintable so we don't have to supply our own drawables :-) – kenyee Jun 12 '17 at 18:47
  • @JaredRummler Thanks..that works well..upvoted it :-) – kenyee Jun 13 '17 at 13:46
  • They've added @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) to fields, so I guess it's not working after API 28 – Danil.B Jul 27 '20 at 18:01
13

I recognize this is really late, but if all you want to do is change the color of the handle, you just need to add the following to your styles.xml file.

<style name="ColoredHandleTheme">
    <item name="colorControlActivated">@color/colorYouWant</item>
</style>

And then just set the theme on whatever activity is holding the EditText which you want to affect.

Or if you want to set it app-wide, you can do the following:

<style name="ColoredHandleThemeForWholeApp">
    <item name="colorAccent">@color/colorYouWant</item>
</style>

And set that theme for the whole app.

Problem solved!

LukeWaggoner
  • 8,869
  • 1
  • 29
  • 28
  • 4
    I don't think colorControlActivated works when setting it to the EditText directly. Only works in Activity-level (through the manifest). Tested on Nexus 5 with Android 6, and on Nexus 4 with Android 4.4.4. – android developer Aug 03 '17 at 08:14
  • Probably right. I didn't say that it would work on a single EditText. I said you could set it on an activity or app-wide. – LukeWaggoner Aug 04 '17 at 23:06
  • Oh ok. Sorry and thanks. Do you know of such a solution then? – android developer Aug 06 '17 at 11:25
  • I don't sorry. Why do you want different styling on different EditTexts in the same activity? – LukeWaggoner Aug 07 '17 at 22:41
  • Because if only one EditText has issue of showing its text-selection-handles (due to a background behind it), it doesn't mean all EditTexts have this issue, so it doesn't make sense to change the styles for all of them. Only for the one I'm interested in. – android developer Aug 08 '17 at 06:30
  • Speaking as a user I think it would be a bit odd to have different handle colors in an EditText, but that might just be me. Usually the accent color is used and it's a completely different color from the primary so as to stand out well. – LukeWaggoner Aug 08 '17 at 06:36
  • Well, the activity is comprised of multiple fragments, and in some state of the activity, the background behind a specific EditText is similar to the default text-selection-handles, but in most cases it's just white, so it's important to have the same default one across the app, yet only in this specific case, have a different color. What do you mean about the accent color? – android developer Aug 08 '17 at 06:51
  • Usually the accent color you set for your app is the color used for the handle, I believe. Usually the accent color isn't something close to the primary color you set for the app. For some reason I was figuring your background would be using your primary color. – LukeWaggoner Aug 09 '17 at 20:38
  • @androiddeveloper It will actually work if you change the theme of single EditText directly, see https://stackoverflow.com/a/35338189/1000551 – Vadim Kotov Mar 14 '19 at 09:26
  • @VadimKotov Wouldn't it change more than just the handles? – android developer Mar 14 '19 at 19:06
  • @androiddeveloper what do you mean? Please elaborate – Vadim Kotov Mar 19 '19 at 08:15
  • @VadimKotov I mean that I think it might change more UI elements, and not just the handles. Of course, I could be wrong. – android developer Mar 19 '19 at 08:57
11

In order to change the color of select handles, you have to override the activated color in your app theme:

<style name="MyCustomTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="android:colorControlActivated">@color/customActivatedColor</item>
</style>
Mehmed Mert
  • 935
  • 1
  • 7
  • 24
2

You can see these attributes in http://androiddrawables.com/Other.html.

Change your values/styles.xml, for instance:

<style name="AppTheme.Cursor" parent="AppTheme">
    <item name="colorAccent">@color/cursor</item>
</style>

where @color/cursor is added in values/color.xml. After that apply the style to the activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(R.style.AppTheme_Cursor);
    ...

Visit How to change EditText pointer color (not cursor) for other solutions.

Community
  • 1
  • 1
CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • This doesn't work. Tested on Nexus 5 with Android 6 and on Nexus 4 with Android 5. – android developer Aug 03 '17 at 08:28
  • @androiddeveloper, I can't say now. I tested this code on Samsung Galaxy Tab A running Android 5. Now I think other solutions are more preferable, because they don't change colorAccent (which may affect other controls). – CoolMind Aug 03 '17 at 20:54
2

For those who try to handle this from code, you can use answer provided by Jared Rummler for API version less or equal to 28, but from Android Q(API 29) they've added a @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) annotation and it doesn't seem to work on Q+. Instead a new methods where added to EditText:

setTextSelectHandle(R.drawable.test);
setTextSelectHandleLeft(R.drawable.test);
setTextSelectHandleRight(R.drawable.test);

So, to make it work you could do something like this:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                setTextSelectHandle(R.drawable.test);
                setTextSelectHandleLeft(R.drawable.test);
                setTextSelectHandleRight(R.drawable.test);
            } else {
                try {
                    final Field fEditor = TextView.class.getDeclaredField("mEditor");
                    fEditor.setAccessible(true);
                    final Object editor = fEditor.get(this);

                    final Field fSelectHandleLeft = editor.getClass().getDeclaredField("mSelectHandleLeft");
                    final Field fSelectHandleRight =
                            editor.getClass().getDeclaredField("mSelectHandleRight");
                    final Field fSelectHandleCenter =
                            editor.getClass().getDeclaredField("mSelectHandleCenter");

                    fSelectHandleLeft.setAccessible(true);
                    fSelectHandleRight.setAccessible(true);
                    fSelectHandleCenter.setAccessible(true);

                    final Resources res = getResources();

                    fSelectHandleLeft.set(editor, res.getDrawable(R.drawable.test, null));
                    fSelectHandleRight.set(editor, res.getDrawable(R.drawable.test, null));
                    fSelectHandleCenter.set(editor, res.getDrawable(R.drawable.test, null));
                } catch (final Exception ignored) {
                }
            }
Danil.B
  • 880
  • 1
  • 11
  • 23
2

If you want to hide the pointer only on one EditText you can set theme only to it:

styles.xml

<style name="TransparentPointerEditText">
    <item name="colorControlActivated">@android:color/transparent</item>
</style>

usage

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:theme="@style/TransparentPointerEditText" />
Alex Misiulia
  • 1,542
  • 17
  • 16