代码中动态和布局文件中静态改变Edittext光标样式方法

时间:2021-06-13 08:58:57

这两种修改光标样式的方法各有优缺点,我会在后面说明。建议使用第一种
1、布局文件中修改Edittext光标样式(常用)
drawable下,创建光标样式文件:edittext_cursor_style

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"

android:shape="rectangle">


<size android:width="1dp" />

<solid android:color="#f5c2c5" />

</shape>

在Edittext中引用即可

<EditText
android:id="@+id/edittext"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_marginLeft="30dp"
android:layout_marginTop="50dp"
android:background="#dedede"
android:paddingLeft="3dp"
android:singleLine="true"
android:textCursorDrawable="@drawable/edittext_cursor_style"
/>

2、在代码中动态修改光标样式:如,一开始光标是A颜色,在点击Edittext的时候,光标颜色就要变化
效果图
选中前:
代码中动态和布局文件中静态改变Edittext光标样式方法
选中后:
代码中动态和布局文件中静态改变Edittext光标样式方法


代码:使用反射原理(最后有注意事项,需要留意)
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#EEEED1"
android:orientation="vertical"
>


<EditText
android:id="@+id/edittext"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_marginLeft="30dp"
android:layout_marginTop="50dp"
android:background="#dedede"
android:paddingLeft="3dp"
android:singleLine="true"
android:textCursorDrawable="@drawable/edittext_cursor_style"
/>


</LinearLayout>

Activity:

package com.chen.customviewdemo;

import android.app.Activity;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.lang.reflect.Field;

/**
* 动态变换Edittext的光标颜色
*/

public class MainActivity_11 extends Activity {

private EditText et;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_11);

et = (EditText) findViewById(R.id.edittext);

//默认打开数字键盘(InputType的类型还有很多,不一一展示了)
//et.setInputType(InputType.TYPE_CLASS_NUMBER);

et.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
fCursorDrawableRes.setAccessible(true);
int mCursorDrawableRes = fCursorDrawableRes.getInt(et);
Field fEditor = TextView.class.getDeclaredField("mEditor");
fEditor.setAccessible(true);
Object editor = fEditor.get(et);
Class<?> clazz = editor.getClass();
Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable");
fCursorDrawable.setAccessible(true);
Drawable[] drawables = new Drawable[1];
drawables[0] = et.getContext().getResources().getDrawable(mCursorDrawableRes);
drawables[0].setColorFilter(0xff00ff00, PorterDuff.Mode.SRC_IN);
fCursorDrawable.set(editor, drawables);
} catch (Exception ignored) {
Toast.makeText(MainActivity_11.this, "出异常了", Toast.LENGTH_SHORT).show();
}
}
});
}
}

注:
1、使用第一种方法(布局中修改),可以*改变光标的宽度,但是带代码中改变,很遗憾,我没有找到方法。
2、在使用反射方法时,会在控制台上看到警告日志:
提示:

drawables[0] = et.getContext().getResources().getDrawable(mCursorDrawableRes);

这句话有java.lang.RuntimeException,但是不影响使用
详细日志:

08-19 11:45:43.513 693-693/com.chen.customviewdemo W/Resources: Drawable android:drawable/text_cursor_material has unresolved theme attributes! Consider using Resources.getDrawable(int, Theme) or Context.getDrawable(int).
java.lang.RuntimeException
at android.content.res.Resources.getDrawable(Resources.java:786)
at android.widget.Editor$InsertionHandleView.getHotspotX(Editor.java:3921)
at android.widget.Editor$HandleView.updateDrawable(Editor.java:3535)
at android.widget.Editor$HandleView.<init>(Editor.java:3526)
at android.widget.Editor$InsertionHandleView.<init>(Editor.java:3877)
at android.widget.Editor$InsertionPointCursorController.getHandle(Editor.java:4185)
at android.widget.Editor$InsertionPointCursorController.access$300(Editor.java:4149)
at android.widget.Editor.onTouchUpEvent(Editor.java:1814)
at android.widget.TextView.onTouchEvent(TextView.java:8373)
at android.view.View.dispatchTouchEvent(View.java:9306)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
at android.app.Activity.dispatchTouchEvent(Activity.java:2820)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
at android.view.View.dispatchPointerEvent(View.java:9526)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4255)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4121)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3662)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3715)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3681)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3807)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3689)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3864)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3662)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3715)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3681)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3689)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3662)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5947)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5921)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5882)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6050)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5432)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:735)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
08-19 11:45:43.516 693-693/com.chen.customviewdemo W/Resources: Drawable android:drawable/text_cursor_material has unresolved theme attributes! Consider using Resources.getDrawable(int, Theme) or Context.getDrawable(int).
java.lang.RuntimeException
at android.content.res.Resources.getDrawable(Resources.java:786)
at com.chen.customviewdemo.MainActivity_11$1.onClick(MainActivity_11.java:46)
at android.view.View.performClick(View.java:5207)
at android.view.View$PerformClick.run(View.java:21177)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5432)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:735)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)