效果图

修改后动画如下

系统原动画如下

三指截屏

PhoneWindowManager 同级目录下的 SystemGesturesPointerEventListener.java 主要负责处理界面的手势监听

public class SystemGesturesPointerEventListener implements PointerEventListener {public void systemReady() {Handler h = new Handler(Looper.myLooper());mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), h);mOverscroller = new OverScroller(mContext);}@Overridepublic void onPointerEvent(MotionEvent event) {if (mGestureDetector != null && event.isTouchEvent()) {mGestureDetector.onTouchEvent(event);}switch (event.getActionMasked()) {case MotionEvent.ACTION_DOWN:mSwipeFireable = true;mDebugFireable = true;mDownPointers = 0;captureDown(event, 0);if (mMouseHoveringAtEdge) {mMouseHoveringAtEdge = false;mCallbacks.onMouseLeaveFromEdge();}mCallbacks.onDown();break;....case MotionEvent.ACTION_MOVE:if (mSwipeFireable) {final int swipe = detectSwipe(event);mSwipeFireable = swipe == SWIPE_NONE;if (swipe == SWIPE_FROM_TOP) {if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");mCallbacks.onSwipeFromTop();} else if (swipe == SWIPE_FROM_BOTTOM) {if (DEBUG) Slog.d(TAG, "Firing onSwipeFromBottom");mCallbacks.onSwipeFromBottom();} else if (swipe == SWIPE_FROM_RIGHT) {if (DEBUG) Slog.d(TAG, "Firing onSwipeFromRight");mCallbacks.onSwipeFromRight();}//addif(event.getPointerCount() == 3){mCallbacks.onMorePointerSwipe();}}break;....        }....}interface Callbacks {void onSwipeFromTop();void onSwipeFromBottom();void onSwipeFromRight();void onMorePointerSwipe();//addvoid onFling(int durationMs);void onDown();void onUpOrCancel();void onMouseHoverAtTop();void onMouseHoverAtBottom();void onMouseLeaveFromEdge();void onDebug();}}

从字面意思理解可知从顶部、底部、右边滑动,接鼠标时从顶部、底部按住滑动,我们在 Callbacks 中增加一个 void onMorePointerSwipe(); 用来回调三指同时滑动的情况,通过 event.getPointerCount() 获取当前屏幕手指按下个数,也可打开调试模式里的指针和触点显示。
当手指数 == 3 时,同时滑动,则我们在 case MotionEvent.ACTION_MOVE 中添加

if(event.getPointerCount() == 3){mCallbacks.onMorePointerSwipe();
}

接口这边搞定了接下来我们就需要来实现具体截屏逻辑

 // monitor for system gesturesmSystemGestures = new SystemGesturesPointerEventListener(context,new SystemGesturesPointerEventListener.Callbacks() {@Overridepublic void onSwipeFromTop() {if (mStatusBar != null) {requestTransientBars(mStatusBar);}}//add@Overridepublic void onMorePointerSwipe() {if (mStatusBar != null) {mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);mHandler.post(mScreenshotRunnable);}}@Overridepublic void onSwipeFromBottom() {if (mNavigationBar != null && mNavigationBarOnBottom) {requestTransientBars(mNavigationBar);}}
}

这样就搞定了三指滑动截屏,是不是很容易,mmm 编译重新 push 替换可查看效果

仿 IOS 截屏动画

再看下原来的动画效果,是一个组合动画,分为 screenshotDropInAnim 和 screenshotFadeOutAnim,有点类似 ppt 中的移入和移出动画,screenshotDropInAnim 中先将缩略图进行适当的缩小和透明度减小,然后在 500 ms的延时后再执行 createScreenshotDropOutAnimation 动画,将缩略图恢复初始的大小和透明度,并相对当前位置朝着自身左上角平移。在移动的同时缩小宽高和降低透明度,直到最终消失在左上角。

来看下我们的预期,修改移出动画为向左下角平移,最终停留在距离屏幕左边和右边各 100 处,超过 3 s 未点击则向左移出屏幕,点击则跳转至图库界面放大查看。

既然是动画我们先来搞清坐标系,因为缩略图是通过 WindowManager 的 addView 方法添加,layoutParams.gravity 如果未指定,则初始位置默认在屏幕正中间,经过测试发现,mScreenshotView 的坐标系是以自身左上角的点为原点的。

没错,就像你看到的上图,这个移出动画我们需要分三段来完成(我们先在 Demo 中进行调试)

第一段

public ValueAnimator loadScreenThumbAnimation(){//起点Point startPoint = new Point(layoutParams.x, layoutParams.y);//终点Point endPoint = new Point(-260, 380);ValueAnimator valueAnimator = ValueAnimator.ofObject(new ObjectEvaluator(), startPoint, endPoint);valueAnimator.setDuration(800);valueAnimator.setStartDelay(SCREENSHOT_DROP_OUT_DELAY);valueAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);//screenShotThumbView.setTranslationX(-50);//第一段动画执行完成,3 S 后执行第二段new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {@Overridepublic void run() {slowSlideScreenThumb();}},3000);}});//移动过程中改变 x 和 yvalueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Point animatedValue = (Point) animation.getAnimatedValue();Log.e("anim", "currentX="+animatedValue.x);layoutParams.x = animatedValue.x;layoutParams.y = animatedValue.y;windowManager.updateViewLayout(screenShotThumbView, layoutParams);}});//valueAnimator.start();return valueAnimator;}public class ObjectEvaluator implements TypeEvaluator{@Overridepublic Object evaluate(float fraction, Object startValue, Object endValue) {Log.i("anim", "fraction="+fraction);// 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象Point startPoint = (Point) startValue;Point endPoint = (Point) endValue;// 根据fraction来计算当前动画的x和y的值int x = (int) (startPoint.x + fraction * (endPoint.x - startPoint.x));int y = (int) (startPoint.y + fraction * (endPoint.y - startPoint.y));Log.i("anim", "fractionX="+x);// 将计算后的坐标封装到一个新的Point对象中并返回return new Point(x, y);}}

第二段

 //第二段只改变 xpublic void slowSlideScreenThumb(){//        final ValueAnimator animator = ValueAnimator.ofInt(80, -10);final ValueAnimator animator = ValueAnimator.ofInt(layoutParams.x, layoutParams.x - 80);animator.setDuration(200);animator.setInterpolator(new LinearInterpolator());animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {Log.e("Screenshots","onAnimationEnd=");//windowManager.removeViewImmediate(screenShotThumbView);//screenShotThumbView.setTranslationX(-50);//第二段结束,执行第三段,移出屏幕dismissScreenThumbAnimation();}});animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {int current = (int) animator.getAnimatedValue();Log.i("anim", "current="+current);//layoutParams.x = Math.abs(current);//screenShotThumbView.setTranslationX(current);layoutParams.x = current;windowManager.updateViewLayout(screenShotThumbView, layoutParams);}});animator.start();}

第三段

//执行第三段,移出屏幕private void dismissScreenThumbAnimation(){final ValueAnimator animator = ValueAnimator.ofInt(0, -thumbWidth);animator.setDuration(230);animator.setInterpolator(new LinearInterpolator());animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {Log.e("Screenshots","onAnimationEnd=");windowManager.removeViewImmediate(screenShotThumbView);}});animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {int current = (int) animator.getAnimatedValue();Log.i("anim", "current="+current);screenShotThumbView.setTranslationX(current);}});animator.start();}

点击跳转

screenShotThumbView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//removeScreenShotThumbWindow();//Uri imageUri =  Uri.fromFile(queryNearestScreenShotFile());Uri imageUri =  FileProvider.getUriForFile(mContext,"com.cczheng.androiddemo.fileprovider", queryNearestScreenShotFile());// Create the intent to show the screenshot in galleryIntent launchIntent = new Intent(Intent.ACTION_VIEW);launchIntent.setDataAndType(imageUri, "image/png");launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);startActivity(launchIntent);}
});//查询最新时间的截屏图片
private File queryNearestScreenShotFile(){final String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()+ "/Screenshots/";File rootFile = new File(path);File nearestFile = null;long maxModifiedTime = 0;for (File file : rootFile.listFiles()){long lastModified = file.lastModified();//Log.e("Screenshots","lastModified="+lastModified + " fileName="+file.getName());if (lastModified > maxModifiedTime){maxModifiedTime = lastModified;nearestFile = file;}}return nearestFile;}

上面获取跳转图片的 URI,需要采用 FileProvider 的方式,不然会崩溃,在 manifest 中添加如下配置

<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.cczheng.androiddemo.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths"/>
</provider>

同时在 res 目录下新建 xml 文件夹,增加** file_paths.xml**

<?xml version="1.0" encoding="utf-8"?>
<paths ><external-path name="png" path="."/>
</paths>

Android8.1 MTK平台 增加三指截屏(仿IOS左下角显示缩略图点击放大显示)相关推荐

  1. Android N版本 三指截屏

    首先自己恭喜自己找到新的工作,这段时间也把自己的写过的一些功能做个总结. 手势快捷操作现在很多手机厂商都有做,三指截屏只是一个例子,可以通过这个例子去实现某个操作<->某个动作.本文只是写 ...

  2. 滚动截屏软件_华为指关节截屏不如三指截屏好用?一步到位,实践出真知

    华为手机的指关节截屏功能想必只要是用过的朋友都知道,熟悉的朋友更会以此为依赖,比如我,现在换了个其他品牌手机用,一到截屏的时候还是会不由自主地拿指关节划区截屏,因为指关节截屏不仅仅是双击截屏,这个划区 ...

  3. Android三指截屏的实现

    三指截屏是用户三个手机点击屏幕向下滑,最终调用systemui的截屏服务实现截屏.所以其他只是做一个策略的实现.目前很多不少手机都实现了该功能,因此自己也尝试着实现该功能.1.首先是注册事件,监听用户 ...

  4. Android三指截屏实现,一个简单的三指截屏功能实现

    最近做了很多客制化的Touch需求,很多情况都可以直接通过GestureDetector来完成,这里挑选三指截屏简述原理.先来说说主要思路,在view的onInterceptTouchEvent方法中 ...

  5. Android 基于4.4系统截屏的三指截屏

    根据上一篇文章Android 4.4系统原生截图解析 ,我们知道系统截屏是调用了TakeScreenshotService,为实现在任何界面都能实现三指截屏,我们就得在PhoneWindow(fram ...

  6. SystemUI 三指截屏或Power键加音量键连续截屏比较慢

    不积跬步无以至千里 了解SystemUI模块的童鞋都知道截屏是处在SystemUI的代码逻辑中的,因此这里出现了截屏比较慢的问题,就是你连续的三指截屏或者power+音量键,但是不会去快速的截屏. 修 ...

  7. unity打包的apk无法三指截屏

    unity打包的apk无法三指截屏 环境 华为手机 问题 unity打包的游戏在手机上无法用三指截屏 原因 首先华为手机有一个应用助手 游戏空间的概念或者说是应用. 华为手机当判断此应用为游戏时,会将 ...

  8. Mr.Alright---基于安卓O(8.0)三指截屏的实现

    介绍:使用这种方式下拉状态栏也可以截图,思路就是拦截触摸事件,判断是不是三指并且符合一定的距离,最后发送截屏的广播,代码如下,后面的代码没有修改 //alps/vendor/mediatek/prop ...

  9. Android8.1 MTK平台 Dialer修改(来电全屏、归属地显示)

    来电默认全屏 默认情况下,来电android是以通知窗口的形式显示,只在屏幕的顶部显示,现在改为全屏显示 修改位置 alps\vendor\mediatek\proprietary\packages\ ...

最新文章

  1. React使用ES6语法重构组件代码
  2. Object C学习笔记20-结构体
  3. 数据结构-Hash总结(三):实践基础篇
  4. 线程与线程池(一条龙详解)
  5. Linux系统下,虚拟终端开启256色_虚拟终端类型xterm开启256色
  6. 【渝粤教育】国家开放大学2018年秋季 1313T学前儿童卫生与保健 参考试题
  7. python元类_Python元类
  8. UvaLive 6664 Clock Hands
  9. 3D建模软件有哪些?
  10. TwinCAT 3 马达程序
  11. 微信用户绑定java实例_第三方网站微信登录java代码实现
  12. 消费者满意度调查方案
  13. 新川抖音短视频营销平台是怎么样帮助企业运营抖音蓝V号的?
  14. Unity打包生成APK文件提交应用宝踩坑记录
  15. 招商软文如何写:推广诱人的广告——文芳阁传媒有话说
  16. MongoDB面试问题
  17. 简单十步创建个人博客网站
  18. C++ 函数指针 指向类成员函数
  19. Gingko Framework:session的使用
  20. nacos报错,.BeanCreationException: Error creating bean with name ‘nacosProperties‘ defined in class

热门文章

  1. MATLAB robotics tools工具箱下载安装
  2. win11 node 环境变量配置
  3. Vue底层原理之变化侦测 —— 让对象每一个属性都变得“可侦测”(一)
  4. 区分authentication、authorization、Identification
  5. 基于myeclipse的静态访问自创表格
  6. 以太坊开发之搭建宠物商店
  7. Python 字符串string()2021-08-27
  8. Matlab学习笔记(三)--菜单与控件
  9. Google的中文名字应该叫什么?
  10. 万元大奖等你拿!北京乌金石科技集团面向社会征集歌词