Mr.Alright---基于安卓O(8.0)三指截屏的实现
介绍:使用这种方式下拉状态栏也可以截图,思路就是拦截触摸事件,判断是不是三指并且符合一定的距离,最后发送截屏的广播,代码如下,后面的代码没有修改
//alps/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.javapackage com.android.systemui.statusbar.phone;import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.LayoutRes;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.view.InputDevice;
import android.view.InputQueue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.view.FloatingActionMode;
import com.android.internal.widget.FloatingToolbar;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;public class StatusBarWindowView extends FrameLayout {public static final String TAG = "StatusBarWindowView";public static final boolean DEBUG = StatusBar.DEBUG;private DragDownHelper mDragDownHelper;private DoubleTapHelper mDoubleTapHelper;private NotificationStackScrollLayout mStackScrollLayout;private NotificationPanelView mNotificationPanel;private View mBrightnessMirror;private int mRightInset = 0;private int mLeftInset = 0;private StatusBar mService;private final Paint mTransparentSrcPaint = new Paint();private FalsingManager mFalsingManager;// Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by// DecorView, but since this is a special window we have to roll our own.private View mFloatingActionModeOriginatingView;private ActionMode mFloatingActionMode;private FloatingToolbar mFloatingToolbar;private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;private boolean mTouchCancelled;private boolean mTouchActive;// add by alright on 2018/9/10 start private Context mConext;private int pointy1 = 0;private int pointy2 = 0;private int pointy3 = 0;private int mpointy1 = 0;private int mpointy2 = 0;private int mpointy3 = 0;private int mCanMoveDistance;private static boolean canget = false;// add by alright on 2018/9/10 end public StatusBarWindowView(Context context, AttributeSet attrs) {super(context, attrs);setMotionEventSplittingEnabled(false);mTransparentSrcPaint.setColor(0);mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));mFalsingManager = FalsingManager.getInstance(context);mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> {mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this);return true;}, null, null);// add by alright on 2018/9/10 start mConext = context;WindowManager mWm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);mCanMoveDistance = (int)(mWm.getDefaultDisplay().getHeight()/5);// add by alright on 2018/9/10 end }@Overrideprotected boolean fitSystemWindows(Rect insets) {if (getFitsSystemWindows()) {boolean paddingChanged = insets.top != getPaddingTop()|| insets.bottom != getPaddingBottom();// Super-special right inset handling, because scrims and backdrop need to ignore it.if (insets.right != mRightInset || insets.left != mLeftInset) {mRightInset = insets.right;mLeftInset = insets.left;applyMargins();}// Drop top inset, and pass through bottom inset.if (paddingChanged) {setPadding(0, 0, 0, 0);}insets.left = 0;insets.top = 0;insets.right = 0;} else {if (mRightInset != 0 || mLeftInset != 0) {mRightInset = 0;mLeftInset = 0;applyMargins();}boolean changed = getPaddingLeft() != 0|| getPaddingRight() != 0|| getPaddingTop() != 0|| getPaddingBottom() != 0;if (changed) {setPadding(0, 0, 0, 0);}insets.top = 0;}return false;}private void applyMargins() {final int N = getChildCount();for (int i = 0; i < N; i++) {View child = getChildAt(i);if (child.getLayoutParams() instanceof LayoutParams) {LayoutParams lp = (LayoutParams) child.getLayoutParams();if (!lp.ignoreRightInset&& (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) {lp.rightMargin = mRightInset;lp.leftMargin = mLeftInset;child.requestLayout();}}}}@Overridepublic FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {return new LayoutParams(getContext(), attrs);}@Overrideprotected FrameLayout.LayoutParams generateDefaultLayoutParams() {return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);}@Overrideprotected void onFinishInflate() {super.onFinishInflate();mStackScrollLayout = (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller);mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);mBrightnessMirror = findViewById(R.id.brightness_mirror);}@Overridepublic void onViewAdded(View child) {super.onViewAdded(child);if (child.getId() == R.id.brightness_mirror) {mBrightnessMirror = child;}}public void setService(StatusBar service) {mService = service;setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout, mService));}@VisibleForTestingvoid setDragDownHelper(DragDownHelper dragDownHelper) {mDragDownHelper = dragDownHelper;}@Overrideprotected void onAttachedToWindow () {super.onAttachedToWindow();// We need to ensure that our window doesn't suffer from overdraw which would normally// occur if our window is translucent. Since we are drawing the whole window anyway with// the scrim, we don't need the window to be cleared in the beginning.if (mService.isScrimSrcModeEnabled()) {IBinder windowToken = getWindowToken();WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();lp.token = windowToken;setLayoutParams(lp);WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);setWillNotDraw(false);} else {setWillNotDraw(!DEBUG);}}@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {if (mService.interceptMediaKey(event)) {return true;}if (super.dispatchKeyEvent(event)) {return true;}boolean down = event.getAction() == KeyEvent.ACTION_DOWN;switch (event.getKeyCode()) {case KeyEvent.KEYCODE_BACK:if (!down) {mService.onBackPressed();}return true;case KeyEvent.KEYCODE_MENU:if (!down) {return mService.onMenuPressed();}case KeyEvent.KEYCODE_SPACE:if (!down) {return mService.onSpacePressed();}break;case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_UP:if (mService.isDozing()) {MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);return true;}break;}return false;}public void setTouchActive(boolean touchActive) {mTouchActive = touchActive;mStackScrollLayout.setTouchActive(touchActive);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;if (!isCancel && mService.shouldIgnoreTouch()) {return false;}if (isDown && mNotificationPanel.isFullyCollapsed()) {mNotificationPanel.startExpandLatencyTracking();}if (isDown) {setTouchActive(true);mTouchCancelled = false;} else if (ev.getActionMasked() == MotionEvent.ACTION_UP|| ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {setTouchActive(false);}if (mTouchCancelled) {return false;}mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {// Disallow new pointers while the brightness mirror is visible. This is so that you// can't touch anything other than the brightness slider while the mirror is showing// and the rest of the panel is transparent.if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {return false;}}if (isDown) {mStackScrollLayout.closeControlsIfOutsideTouch(ev);}if (mService.isDozing()) {mService.mDozeScrimController.extendPulse();}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// Add by alright on 2018/10/13 for start >>>>>>>>>>if ((Settings.System.getInt(mContext.getContentResolver(), "Three_fingers_screenshots", 0) == 1)&& ev.getPointerCount() == 3) {if (canShot(ev)) {Intent intent = new Intent("com.android.screen.shot");mContext.sendBroadcast(intent);return true;} else {return super.onInterceptTouchEvent(ev);}}// Add by alright on 2018/10/13 for 3-finger screenshot end <<<<<<<<<<<<<<<if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {// Capture all touch events in always-on.return true;}boolean intercept = false;if (mNotificationPanel.isFullyExpanded()&& mStackScrollLayout.getVisibility() == View.VISIBLE&& mService.getBarState() == StatusBarState.KEYGUARD&& !mService.isBouncerShowing()&& !mService.isDozing()) {intercept = mDragDownHelper.onInterceptTouchEvent(ev);}if (!intercept) {super.onInterceptTouchEvent(ev);}if (intercept) {MotionEvent cancellation = MotionEvent.obtain(ev);cancellation.setAction(MotionEvent.ACTION_CANCEL);mStackScrollLayout.onInterceptTouchEvent(cancellation);mNotificationPanel.onInterceptTouchEvent(cancellation);cancellation.recycle();}return intercept;}// Add by alright on 2018/10/13 for start >>>>>>>>>>private boolean canShot(MotionEvent ev) {Log.d(TAG, "canShot: " + ev.getAction());if (ev.getAction() == MotionEvent.ACTION_POINTER_3_DOWN) {pointy1 = (int) ev.getAxisValue(MotionEvent.AXIS_Y, 0);pointy2 = (int) ev.getAxisValue(MotionEvent.AXIS_Y, 1);pointy3 = (int) ev.getAxisValue(MotionEvent.AXIS_Y, 2);canget = true;} else if (ev.getAction() == MotionEvent.ACTION_UP|| ev.getAction() == MotionEvent.ACTION_POINTER_2_UP|| ev.getAction() == MotionEvent.ACTION_POINTER_3_UP) {try {mpointy1 = (int) ev.getAxisValue(MotionEvent.AXIS_Y, 0);mpointy2 = (int) ev.getAxisValue(MotionEvent.AXIS_Y, 1);mpointy3 = (int) ev.getAxisValue(MotionEvent.AXIS_Y, 2);} catch (IllegalArgumentException e) {e.printStackTrace();}if (canget && Math.abs(mpointy1 - pointy1) >= mCanMoveDistance&& Math.abs(mpointy2 - pointy2) >= mCanMoveDistance&& Math.abs(mpointy3 - pointy3) >= mCanMoveDistance) {canget = false;return true;}canget = false;}return false;}// add by alright on 2018/9/3 end
Mr.Alright---基于安卓O(8.0)三指截屏的实现相关推荐
- Android 基于4.4系统截屏的三指截屏
根据上一篇文章Android 4.4系统原生截图解析 ,我们知道系统截屏是调用了TakeScreenshotService,为实现在任何界面都能实现三指截屏,我们就得在PhoneWindow(fram ...
- 滚动截屏软件_华为指关节截屏不如三指截屏好用?一步到位,实践出真知
华为手机的指关节截屏功能想必只要是用过的朋友都知道,熟悉的朋友更会以此为依赖,比如我,现在换了个其他品牌手机用,一到截屏的时候还是会不由自主地拿指关节划区截屏,因为指关节截屏不仅仅是双击截屏,这个划区 ...
- Android三指截屏的实现
三指截屏是用户三个手机点击屏幕向下滑,最终调用systemui的截屏服务实现截屏.所以其他只是做一个策略的实现.目前很多不少手机都实现了该功能,因此自己也尝试着实现该功能.1.首先是注册事件,监听用户 ...
- Android三指截屏实现,一个简单的三指截屏功能实现
最近做了很多客制化的Touch需求,很多情况都可以直接通过GestureDetector来完成,这里挑选三指截屏简述原理.先来说说主要思路,在view的onInterceptTouchEvent方法中 ...
- Android N版本 三指截屏
首先自己恭喜自己找到新的工作,这段时间也把自己的写过的一些功能做个总结. 手势快捷操作现在很多手机厂商都有做,三指截屏只是一个例子,可以通过这个例子去实现某个操作<->某个动作.本文只是写 ...
- Android8.1 MTK平台 增加三指截屏(仿IOS左下角显示缩略图点击放大显示)
效果图 修改后动画如下 系统原动画如下 三指截屏 PhoneWindowManager 同级目录下的 SystemGesturesPointerEventListener.java 主要负责处理界面的 ...
- unity打包的apk无法三指截屏
unity打包的apk无法三指截屏 环境 华为手机 问题 unity打包的游戏在手机上无法用三指截屏 原因 首先华为手机有一个应用助手 游戏空间的概念或者说是应用. 华为手机当判断此应用为游戏时,会将 ...
- SystemUI 三指截屏或Power键加音量键连续截屏比较慢
不积跬步无以至千里 了解SystemUI模块的童鞋都知道截屏是处在SystemUI的代码逻辑中的,因此这里出现了截屏比较慢的问题,就是你连续的三指截屏或者power+音量键,但是不会去快速的截屏. 修 ...
- 荣耀android手机怎么截图,华为荣耀8怎么截图/截屏 荣耀8三种截屏方法教程
昨天晚上,荣耀带来了又一款小屏旗舰新机----荣耀8,主打高颜值外观.该机关于7月19日正式全国上市.相信小伙伴们拿到真机之后,在使用过程当中难免会使用截图分享.那么荣耀8怎么截图呢?下面脚本之家小编 ...
最新文章
- 更大的工字型电感作为150kHz导航信号接收天线
- 使用R实现一个简单的连续系统模拟
- 图像分类、目标检测、语义分割、实例分割和全景分割的区别
- openstack-neutron基本的网络类型
- matlab上位机串口通信,MATLAB GUIDE 上位机串口通信开发 绘制图形
- WSS页面定制系列(1)--如何启用表单页面的编辑模式
- 字符串的展开(洛谷-P1098)
- Linux Shell脚本入门教程系列之(十六) Shell输入输出重定向
- python中返回值为ture表达式_python return逻辑判断表达式(21)|python教程|python入门|python教程...
- 为什么是 OnDraw(CDC* /*pDC*/) 而不是 OnDraw(CDC* pDC)
- Python快速构建神经网络
- System Verilog面向对象编程(OPP)基础——类(class)的基本使用
- radiobutton模拟tab点击效果
- Android如何实现音频输出路由的切换
- HTML动态视频背景全代码
- 华为荣耀8C安装Google play store的记录
- 均匀分布的期望和方差
- 服务器间文件拷贝显示busy,网站解决和优化Server is too busy的一些方法
- Markdown字体,字号,颜色和背景色设置
- Python图像处理【5】图像扭曲与逆扭曲详解
热门文章
- 实验八 :8259中断控制器实验(综合)
- 给自己留个发泄的地方
- 【编译原理】《编译原理第二版》LR0例题代码
- android SwitchPreference ListPreference使用
- 《最优化理论与算法》(陈宝林)——第10章:使用导数的最优化方法
- 早上被裁下午走人,女朋友也失业在家4个月,投字节简历堆成山
- html 偶数项 替换,JS通过奇数项和偶数项实现两种背景颜色的表格实现代码
- 2014年百度之星程序设计大赛 - 资格赛 (未完成)
- java语句witch,java程序流程控制--witch
- 开机黑屏显示html,电脑开机黑屏怎么办,教您电脑开机黑屏的解决方法