5

I am having a hard time customizing the EditText select handle. I am following this thread:

How to change color / appearance of EditText select handle / anchor?

It looks like pretty straight forward. Yet, I can't get it to work on landscape. Can anyone spot what I am doing wrong? I pretty much pasted the same code on a test activity but the anchor handles' are always the same. I tried using styles as suggested and programmatically. Still I always get the same default blue anchors :(

I am on Nougat not sure if makes any difference.

Test activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(R.style.MyCustomTheme);
    setContentView(R.layout.activity_main);
    final EditText editText = (EditText) findViewById(R.id.edit1);
    // tried programatically too and no success
    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);
        fSelectHandleLeft.set(editor, ContextCompat.getDrawable(this, R.drawable.small_rect));
        fSelectHandleRight.set(editor, ContextCompat.getDrawable(this, R.drawable.small_rect));
        fSelectHandleCenter.set(editor, ContextCompat.getDrawable(this, R.drawable.small_rect));
    } catch (final Exception e) {
        Log.d("CUSTOM_ANCHORS", e.toString());
    }
}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/edit1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Hello World"
        android:textSize="20sp" />

</LinearLayout>

My styles:

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>


<style name="MyCustomTheme" parent="@style/AppTheme">
    <item name="android:textSelectHandle">@drawable/small_rect</item>
    <item name="android:textSelectHandleLeft">@drawable/small_rect</item>
    <item name="android:textSelectHandleRight">@drawable/small_rect</item>
</style>

the drawable (small_rect.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:width="20dp"
        android:height="20dp" />
    <gradient
        android:angle="90"
        android:centerColor="#D6D6D6"
        android:endColor="#4B6CD6"
        android:startColor="#6586F0" />
    <corners android:radius="0dp" />
</shape>

the result:

enter image description here

gmmo
  • 2,577
  • 3
  • 30
  • 56

6 Answers6

3
 <EditText
    android:imeOptions="flagNoFullscreen"
 />

You can use android:imeOptions to tell the system not to display editing UI in fullscreen. enter image description here

Tin Tran
  • 2,265
  • 1
  • 14
  • 17
  • It worked on Nougat but not on Lollipop for me. In all cases this was the cleanest answer. – gmmo Jun 12 '17 at 17:33
  • This works brilliantly on at least some pre-N devices too. For example, I can now see the custom handles in landscape mode on my KitKat phone. On my ICS (API 15) phone, I don't see the custom handles, but I do see the background drawable when editing in landscape mode. This solution is the best I've seen so far, and deserves the bounty! But be aware that its effectiveness may vary from device to device. – Rapunzel Van Winkle Jun 13 '17 at 00:53
2

I think that your custom EditText handle can be implemented with just xml.

  1. Define the handle's style in your styles.xml:

    <style name="CustomSelectHandle">
        <item name="android:textSelectHandle">@drawable/small_rect</item>
        <item name="android:textSelectHandleLeft">@drawable/small_rect</item>
        <item name="android:textSelectHandleRight">@drawable/small_rect</item>
    </style>
    
  2. Add the style attribute to your EditText:

    <EditText
        android:id="@+id/edit1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Hello World"
        style="@style/CustomSelectHandle"
        android:textSize="20sp" />
    

I just ran a quick test of this on a KitKat device, and the custom handles were there.

Update: I duplicated the problem with landscape mode on the KitKat phone. However, the bug doesn't affect all devices. In particular, when I ran the code in landscape mode on a tablet, the custom handles worked fine.

Additional Observation: The EditText that I tested this on also had a background drawable. This drawable appears as expected in both portrait and landscape mode, on both phones and tablets. However, if I actually edit the field in landscape mode on a phone, the custom background disappears, and the field has a plain white background until I leave edit mode.

Conjecture: It looks like Android runs through a different code path (that ignores custom formatting) when editing fields in landscape mode on small devices. When a soft keyboard is displayed in landscape mode, that doesn't leave much room to display the field being edited on a phone. So maybe the developers made a compromise at some point (that it's better to display a very plain text field for the user to edit, than to risk having the entire field obscured). Without delving into the source code, that's my best guess for what's going on here...

Rapunzel Van Winkle
  • 5,380
  • 6
  • 31
  • 48
  • This only works in portrait. See my answer this looks like and OS bug. – gmmo Jun 06 '17 at 18:42
  • Updated my answer. You're probably right that it's an OS bug, but only in landscape mode on phones (not tablets). – Rapunzel Van Winkle Jun 06 '17 at 22:39
  • thanks for the extra testing, but I need it working on a phone. Looks like you just confirmed what I suspected, this cannot be done in portrait on a phone. – gmmo Jun 06 '17 at 23:39
2

The below code works perfectly on Nougat

<EditText
      android:layout_width="match_parent"
      style="@style/MyCustomTheme"
      android:text="@string/app_name"
      android:layout_height="wrap_content" />

<style name="MyCustomTheme" parent="@style/AppTheme">
    <item name="android:textSelectHandle">@android:drawable/arrow_down_float</item>
    <item name="android:textSelectHandleLeft">@android:drawable/arrow_down_float</item>
    <item name="android:textSelectHandleRight">@android:drawable/arrow_down_float</item>
  </style>
Arun Shankar
  • 2,295
  • 16
  • 20
2

You guys code work only in Portrait (so does mine). My application is landscape only and I looked around and it looks like this an OS bug. I notified google about it. Yet, if there is workaround still using the EditText the 50 points is still up for grabs.

gmmo
  • 2,577
  • 3
  • 30
  • 56
2

add a XML attribute to your EditText

android:textColorHighlight="@color/accent_translucent"
Saubhagya
  • 155
  • 12
2

Try adding

<item name="colorControlActivated">@drawable/small_rect</item>

to your styles

krishan
  • 1,141
  • 1
  • 12
  • 24