如何更改EditText选择句柄/锚点的颜色/外观?

30

我使用Holo Colors GeneratorAction Bar Style Generator更改了Holo主题的样式,使其符合我的颜色。但是当我选择编辑文本中的文本时,所选位置上的“标记”仍然是蓝色的。我该如何更改它呢?

LeftMiddleRight


相关 - https://dev59.com/ulgR5IYBdhLWcg3ww_s0 - Vadim Kotov
请参阅https://stackoverflow.com/questions/29795197/how-to-change-color-of-edittext-handles。 - undefined
7个回答

39
在这里最困难的部分是找到此项的“名称”以及其在主题中的称呼。因此,我查看了Android SDK文件夹中的每个可绘制对象,最终找到了名为“text_select_handle_middle”、“text_select_handle_left”和“text_select_handle_right”的可绘制对象。
因此,解决方案很简单:将这些具有自定义设计/颜色的可绘制对象添加到您的可绘制文件夹中,并将它们添加到您的主题样式定义中,例如:
<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>

虽然来晚了,但请看我的答案,介绍如何通过编程实现此功能。 @ant - Jared Rummler
即使仅应用于一个EditText或TextView,它也可以正常工作,而不仅仅是整个应用程序。 - Vadim Kotov
只是友好提醒。在应用此解决方案后,editView 在某些三星设备上可能会失去响应。我们刚刚发现了这个问题,请查看这里 - Freddie

13

如何通过代码完成:

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) {
}

2
是的,这是其中一种可能的方法。但是反射不是一个好主意。 - ant
1
如果我只想更改“mSelectHandleCenter”的颜色,而不是用新的可绘制对象替换它,该怎么办?我该如何实现?不幸的是,由于我通过我们的API获取新的“强调颜色”,所以我被迫使用反射。 - Niccolò Passolunghi
3
您可以通过在两个数组中删除左和右字段名称来更改该方法,以仅对中心手柄进行着色。 - Jared Rummler
1
@JaredRummler,你的文本选择句柄(text_select_handle_*)文件的drawable文件是什么样子的? - Pie
这个能在一个线程中完成吗?我可以在片段的onCreateView中实现,但是在一个线程中就不行了。有什么建议吗? - Madhavan Malolan
显示剩余3条评论

13

我知道这已经很晚了,但如果你只想改变手柄的颜色,你只需要在styles.xml文件中添加以下内容。

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

接着,在包含你想要改变的EditText的活动中设置主题即可。

或者,如果你想要全局应用这个主题,你可以按照以下步骤进行:

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

将该主题设置为整个应用程序的主题。

问题解决了!


4
我认为如果直接将colorControlActivated设置到EditText上,它不起作用。只有在Activity级别(通过清单文件)才能起作用。在搭载Android 6的Nexus 5和Android 4.4.4的Nexus 4上进行了测试。 - android developer
可能是对的。我没有说它只能在单个EditText上工作。我说你可以在整个Activity或应用程序上设置它。 - LukeWaggoner
因为如果只有一个EditText存在显示文本选择句柄的问题(由于其后面的背景),这并不意味着所有EditText都有此问题,因此更改所有EditText的样式是没有意义的。只需更改我感兴趣的那个EditText的样式即可。 - android developer
作为一个用户,我认为在EditText中使用不同的句柄颜色可能有点奇怪,但这可能只是我的想法。通常会使用强调颜色,并且它与主要颜色完全不同,以便更好地突出显示。 - LukeWaggoner
通常你为应用设置的强调色是用于手柄的颜色,我相信。通常强调色不会接近你为应用设置的主要颜色。出于某种原因,我认为你的背景将使用你的主要颜色。 - LukeWaggoner
显示剩余7条评论

11

要更改选择手柄的颜色,您需要在应用程序主题中覆盖激活的颜色:

<style name="MyCustomTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="android:colorControlActivated">@color/customActivatedColor</item>
</style>

2
有没有办法只让它在活动中特定的EditText上工作,而不是所有的EditText? - android developer
当然,您可以通过在布局中声明它们来使用您的自定义样式,仅针对特定的EditText。 - Mehmed Mert
3
在特定的EditText上它对我没有起作用,仅在activity级别(使用清单文件)有效。你能否尝试一下?请进行翻译。 - android developer

2
你可以在http://androiddrawables.com/Other.html中查看这些属性。
例如,更改你的values/styles.xml文件:
<style name="AppTheme.Cursor" parent="AppTheme">
    <item name="colorAccent">@color/cursor</item>
</style>

在values/color.xml中添加@color/cursor,然后将样式应用于活动:

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

访问如何更改EditText指针颜色(而不是光标)以获取其他解决方案。


这个不起作用。在安卓6上的Nexus 5和安卓5上的Nexus 4上进行了测试。 - android developer
@androiddeveloper,我现在不能确定。我在运行Android 5的三星Galaxy Tab A上测试了这段代码。现在我认为其他解决方案更可取,因为它们不会改变colorAccent(这可能会影响其他控件)。 - CoolMind

2
如果您只想隐藏一个EditText上的指针,您可以将主题仅设置为该EditText:
styles.xml
<style name="TransparentPointerEditText">
    <item name="colorControlActivated">@android:color/transparent</item>
</style>

使用方法

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:theme="@style/TransparentPointerEditText" />

2

对于那些试图从代码中处理此问题的人,您可以使用Jared Rummler提供的答案来处理API版本小于或等于28的情况,但是从Android Q(API 29)开始,他们添加了一个@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)注释,并且在Q+上似乎不起作用。相反,EditText添加了新的方法:

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

因此,为了使其正常工作,您可以这样做:
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) {
                }
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接