Android8.1 MTK平台 增加三指截屏(仿IOS左下角显示缩略图点击放大显示)
效果图
修改后动画如下
系统原动画如下
三指截屏
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左下角显示缩略图点击放大显示)相关推荐
- Android N版本 三指截屏
首先自己恭喜自己找到新的工作,这段时间也把自己的写过的一些功能做个总结. 手势快捷操作现在很多手机厂商都有做,三指截屏只是一个例子,可以通过这个例子去实现某个操作<->某个动作.本文只是写 ...
- 滚动截屏软件_华为指关节截屏不如三指截屏好用?一步到位,实践出真知
华为手机的指关节截屏功能想必只要是用过的朋友都知道,熟悉的朋友更会以此为依赖,比如我,现在换了个其他品牌手机用,一到截屏的时候还是会不由自主地拿指关节划区截屏,因为指关节截屏不仅仅是双击截屏,这个划区 ...
- Android三指截屏的实现
三指截屏是用户三个手机点击屏幕向下滑,最终调用systemui的截屏服务实现截屏.所以其他只是做一个策略的实现.目前很多不少手机都实现了该功能,因此自己也尝试着实现该功能.1.首先是注册事件,监听用户 ...
- Android三指截屏实现,一个简单的三指截屏功能实现
最近做了很多客制化的Touch需求,很多情况都可以直接通过GestureDetector来完成,这里挑选三指截屏简述原理.先来说说主要思路,在view的onInterceptTouchEvent方法中 ...
- Android 基于4.4系统截屏的三指截屏
根据上一篇文章Android 4.4系统原生截图解析 ,我们知道系统截屏是调用了TakeScreenshotService,为实现在任何界面都能实现三指截屏,我们就得在PhoneWindow(fram ...
- SystemUI 三指截屏或Power键加音量键连续截屏比较慢
不积跬步无以至千里 了解SystemUI模块的童鞋都知道截屏是处在SystemUI的代码逻辑中的,因此这里出现了截屏比较慢的问题,就是你连续的三指截屏或者power+音量键,但是不会去快速的截屏. 修 ...
- unity打包的apk无法三指截屏
unity打包的apk无法三指截屏 环境 华为手机 问题 unity打包的游戏在手机上无法用三指截屏 原因 首先华为手机有一个应用助手 游戏空间的概念或者说是应用. 华为手机当判断此应用为游戏时,会将 ...
- Mr.Alright---基于安卓O(8.0)三指截屏的实现
介绍:使用这种方式下拉状态栏也可以截图,思路就是拦截触摸事件,判断是不是三指并且符合一定的距离,最后发送截屏的广播,代码如下,后面的代码没有修改 //alps/vendor/mediatek/prop ...
- Android8.1 MTK平台 Dialer修改(来电全屏、归属地显示)
来电默认全屏 默认情况下,来电android是以通知窗口的形式显示,只在屏幕的顶部显示,现在改为全屏显示 修改位置 alps\vendor\mediatek\proprietary\packages\ ...
最新文章
- React使用ES6语法重构组件代码
- Object C学习笔记20-结构体
- 数据结构-Hash总结(三):实践基础篇
- 线程与线程池(一条龙详解)
- Linux系统下,虚拟终端开启256色_虚拟终端类型xterm开启256色
- 【渝粤教育】国家开放大学2018年秋季 1313T学前儿童卫生与保健 参考试题
- python元类_Python元类
- UvaLive 6664 Clock Hands
- 3D建模软件有哪些?
- TwinCAT 3 马达程序
- 微信用户绑定java实例_第三方网站微信登录java代码实现
- 消费者满意度调查方案
- 新川抖音短视频营销平台是怎么样帮助企业运营抖音蓝V号的?
- Unity打包生成APK文件提交应用宝踩坑记录
- 招商软文如何写:推广诱人的广告——文芳阁传媒有话说
- MongoDB面试问题
- 简单十步创建个人博客网站
- C++ 函数指针 指向类成员函数
- Gingko Framework:session的使用
- nacos报错,.BeanCreationException: Error creating bean with name ‘nacosProperties‘ defined in class