在开发者选项中打开input的指针轨迹显示,就会显示出一个view,显示出屏幕的touch轨迹,非常方便。其实现原理就是显示了一个系统级的全屏弹窗,如果写过全局弹窗应用,这个就很好理解了,因为非常相似。
如下方式,可以在app里通过addView的方式显示弹窗,
DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
floatView = (ViewGroup) inflater.inflate(R.layout.float_layout, null);
int layoutType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
WindowManager.LayoutParams floatLp = new WindowManager.LayoutParams(
(int) (width * (0.4f)),
(int) (height * (0.3f)),
layoutType,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
);
再看看PointerLocationView的添加,如出一辙,
在frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java中,有
2550 private void enablePointerLocation() {
2551 if (mPointerLocationView == null) {
2552 mPointerLocationView = new PointerLocationView(mContext);
2553 mPointerLocationView.setPrintCoords(false);
2554 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
2555 WindowManager.LayoutParams.MATCH_PARENT,
2556 WindowManager.LayoutParams.MATCH_PARENT);
2557 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
2558 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
2559 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
2560 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
2561 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
2562 lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
2563 if (ActivityManager.isHighEndGfx()) {
2564 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
2565 lp.privateFlags |=
2566 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
2567 }
2568 lp.format = PixelFormat.TRANSLUCENT;
2569 lp.setTitle("PointerLocation");
2570 WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
2571 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
2572 wm.addView(mPointerLocationView, lp);
2573 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
2574 }
2575 }
可以看到,以弹框的方式进行了显示,窗口属性没有touch,能够跟踪touch是由于PointerLocationView注册了监听,走的特殊通道
其定义如下
public class PointerLocationView extends View implements InputDeviceListener,
PointerEventListener {
就这么清楚,如果我们想实现类似的窗口,可以仿照这种方式来实现