一, App 通过 View 修改鼠标样式
App view 上修改鼠标样式比较简单, 通过 hover event 获取鼠标坐标并使用如下方法修改为自定义图片:
- getWindow().getDecorView().setPointerIcon(PointerIcon.load(getResources(), R.drawable.pointer_spot_touch_icon));
- imageView = (ImageView) findViewById(R.id.image_view);
- imageView.setOnHoverListener(new View.OnHoverListener() {
- @SuppressLint({"SetTextI18n", "ResourceType"})
- @Override
- public boolean onHover(View v, MotionEvent event) {
- int what = event.getAction();
- textX.setText("X :" + event.getX());
- textY.setText("Y :" + event.getY());
- switch(what){
- case MotionEvent.ACTION_HOVER_ENTER: // 鼠标进入 view
- Log.i(TAG, "bottom ACTION_HOVER_ENTER...");
- mOrgPI = getWindow().getDecorView().getPointerIcon();
- getWindow().getDecorView().setPointerIcon(PointerIcon.load(getResources(), R.drawable.pointer_spot_touch_icon));
- break;
- case MotionEvent.ACTION_HOVER_MOVE: // 鼠标在 view 上
- Log.i(TAG, "bottom ACTION_HOVER_MOVE...");
- break;
- case MotionEvent.ACTION_HOVER_EXIT: // 鼠标离开 view
- Log.i(TAG, "bottom ACTION_HOVER_EXIT...");
- getWindow().getDecorView().setPointerIcon(mOrgPI);
- break;
- }
- return false;
- }
- });
- }
其中 pointer_spot_touch_icon.xml 需要声明为 pointer-icon :
- <?xml version="1.0" encoding="utf-8"?>
- <pointer-icon xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:bitmap="@drawable/pointer_red_dot_arrow"
- Android:hotSpotX="6dp"
- Android:hotSpotY="6dp" />
但是 App 修改鼠标样式的 view 关闭后, 鼠标样式会恢复成默认的黑箭头, 因此不依赖 App 去动态切换鼠标样式需要在 framework 层修改系统源码实现.
二, framework 层添加自定义鼠标样式并通过按键切换
(1) 添加自定义样式资源
系统图标资源在 frameworks/base/core/res/res/drawable-mdpi/ 目录, 其中 pointer_arrow.PNG,pointer_arrow_large.PNG 是系统默认的黑色箭头,
pointer_arrow_red_dot.PNG,pointer_arrow_red_dot_large.PNG 是自己添加的红点样式图片:
然后在 frameworks/base/core/res/res/drawable/ 目录添加对应的 xml:
pointer_arrow_red_dot_icon.xml
- <?xml version="1.0" encoding="utf-8"?>
- <pointer-icon xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:bitmap="@drawable/pointer_arrow_red_dot"
- Android:hotSpotX="5dp"
- Android:hotSpotY="5dp" />
pointer_arrow_red_dot_large_icon.xml
- <?xml version="1.0" encoding="utf-8"?>
- <pointer-icon xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:bitmap="@drawable/pointer_arrow_red_dot_large"
- Android:hotSpotX="10dp"
- Android:hotSpotY="10dp" />
修改 frameworks/base/core/res/res/values/styles.xml 添加资源配置, 注意名字的匹配!
修改 frameworks/base/core/res/res/values/attrs.xml 引用资源:
(2)Java 层获取资源
修改 frameworks/base/core/java/Android/view/PointerIcon.java , 添加如下定义:
在 getSystemIconTypeIndex(int type) 函数中返回之前配置的资源:
(3)c++ 层添加对应的 id 并加载资源
修改 frameworks/base/core/jni/android_view_PointerIcon.h
- * Pointer icon styles.
- * Must match the definition in Android.view.PointerIcon.
- */
- enum {
- POINTER_ICON_STYLE_CUSTOM = -1,
- POINTER_ICON_STYLE_NULL = 0,
- POINTER_ICON_STYLE_ARROW = 1000,
- POINTER_ICON_STYLE_CONTEXT_MENU = 1001,
- POINTER_ICON_STYLE_HAND = 1002,
- POINTER_ICON_STYLE_HELP = 1003,
- POINTER_ICON_STYLE_WAIT = 1004,
- POINTER_ICON_STYLE_CELL = 1006,
- POINTER_ICON_STYLE_CROSSHAIR = 1007,
- POINTER_ICON_STYLE_TEXT = 1008,
- POINTER_ICON_STYLE_VERTICAL_TEXT = 1009,
- POINTER_ICON_STYLE_ALIAS = 1010,
- POINTER_ICON_STYLE_COPY = 1011,
- POINTER_ICON_STYLE_NO_DROP = 1012,
- POINTER_ICON_STYLE_ALL_SCROLL = 1013,
- POINTER_ICON_STYLE_HORIZONTAL_DOUBLE_ARROW = 1014,
- POINTER_ICON_STYLE_VERTICAL_DOUBLE_ARROW = 1015,
- POINTER_ICON_STYLE_TOP_RIGHT_DOUBLE_ARROW = 1016,
- POINTER_ICON_STYLE_TOP_LEFT_DOUBLE_ARROW = 1017,
- POINTER_ICON_STYLE_ZOOM_IN = 1018,
- POINTER_ICON_STYLE_ZOOM_OUT = 1019,
- POINTER_ICON_STYLE_GRAB = 1020,
- POINTER_ICON_STYLE_GRABBING = 1021,
- POINTER_ICON_STYLE_SPOT_HOVER = 2000,
- POINTER_ICON_STYLE_SPOT_TOUCH = 2001,
- POINTER_ICON_STYLE_SPOT_ANCHOR = 2002,
- POINTER_ICON_STYLE_REDDOT = 10001, // 增加自定义样式的枚举定义, 与上面 PointerIcon.java 中的变量对应
- };
修改 frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp , 加载到自定义枚举变量对应的图片资源:
- void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources) {
- JNIEnv* env = jniEnv();
- for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_REDDOT;
- ++iconId) {
- PointerIcon pointerIcon;
- loadSystemIconAsSpriteWithPointerIcon(
- env, mContextObj, iconId, &pointerIcon, &((*outResources)[iconId]));
- if (!pointerIcon.bitmapFrames.empty()) {
- PointerAnimation& animationData = (*outAnimationResources)[iconId];
- size_t numFrames = pointerIcon.bitmapFrames.size() + 1;
- animationData.durationPerFrame =
- milliseconds_to_nanoseconds(pointerIcon.durationPerFrame);
- animationData.animationFrames.reserve(numFrames);
- animationData.animationFrames.push_back(SpriteIcon(
- pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY));
- for (size_t i = 0; i < numFrames - 1; ++i) {
- animationData.animationFrames.push_back(SpriteIcon(
- pointerIcon.bitmapFrames[i], pointerIcon.hotSpotX, pointerIcon.hotSpotY));
- }
- }
- }
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL,
- &((*outResources)[POINTER_ICON_STYLE_NULL]));
- }
(4) 按键切换鼠标样式
未完待续...
来源: http://www.bubuko.com/infodetail-3306698.html