想在Android上做一个透明视图,可在整个屏幕上任意涂鸦(包括状态导航栏),但是不想影响下层窗口的操作,偶然发现developer Option中的Pointer Location接近我的需求。于是顺便研究了一下:
PointerLocationView
PhoneWindowManager.java
public void updateSettings() { ContentResolver resolver = mContext.getContentResolver(); boolean updateRotation = false; View addView = null; View removeView = null; .................................
if (mSystemReady) { int pointerLocation = Settings.System.getInt(resolver, Settings.System.POINTER_LOCATION, 0); if (mPointerLocationMode != pointerLocation) { mPointerLocationMode = pointerLocation; if (pointerLocation != 0) { if (mPointerLocationView == null) { mPointerLocationView = new PointerLocationView(mContext); mPointerLocationView.setPrintCoords(false); addView = mPointerLocationView; } } else { removeView = mPointerLocationView; mPointerLocationView = null; } } }
.................................................
if (addView != null) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; lp.format = PixelFormat.TRANSLUCENT; lp.setTitle("PointerLocation"); WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; wm.addView(addView, lp); if (mPointerLocationInputChannel == null) { try { mPointerLocationInputChannel = mWindowManager.monitorInput("PointerLocationView"); InputQueue.registerInputChannel(mPointerLocationInputChannel, mPointerLocationInputHandler, mHandler.getLooper().getQueue()); } catch (RemoteException ex) { Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.", ex); } } } if (removeView != null) { if (mPointerLocationInputChannel != null) { InputQueue.unregisterInputChannel(mPointerLocationInputChannel); mPointerLocationInputChannel.dispose(); mPointerLocationInputChannel = null; } WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.removeView(removeView); }
TYPE_SYSTEM_OVERLAY,TYPE_TOAST,TYPE_SECURE_SYSTEM_OVERLAY三个类型的窗口不接收inputevent, 所以android为它单独注册InputQueue.registerInputChannel以响应触摸事件绘制滑动轨迹。