当前位置: 华文星空 > 知识

从技术上如何看待长截屏,如何实现这一功能?

2017-01-28知识

这个长截屏功能是我做的。我来讲讲其技术实现吧。

简单来讲,就是我让app里面的装内容的可滚动控件一边滚动,一边截屏,最后拼接起来。

下面我来几个自问自答。

我为什么能滚动第三方app里的控件?

Android里有个ApplicationThread,系统对Activity的控制如resume/pause等都是通过它来做跨进程调用,我们也可以通过扩展它,实现从系统调用到app里。不过事实上由于我们自己有另外一个类似的接口,我使用的是我们自己的那个。

我怎么知道第三方app中哪个控件里面装的是用户想滚动的内容?

我会从顶层的View从上往下遍历,直到找到符合我设定条件的View为止。我设定的条件大概是:能向下滚动、View在屏幕内的可见大小大于半个屏幕的大小。

实际使用发现这个简单的规则就够了。

为什么点击「长截屏」按钮后图片就无缝的自然变长,中间也不停顿,截屏究竟是在什么时候截的呢?

其实真实的app内容滚动与「截屏」这个动作是发生在当前窗口背后的,由于当前窗口完全不透明,所以挡住了背后发生的事情,我们完全看不到。

点击「长截屏」按钮之后,大概会发生下面的事情:

  1. 找到当前前台Activity,然后通过上面说的远程调用,调用过去。
  2. 在前台Activity里执行的代码收到调用后,找到用户要滚动的View,并滚动一定距离。然后停止滚动并通过Broadcast通知截屏窗口,包括View的位置及滚动的距离信息。
  3. 截屏窗口截取一张屏幕,当然,不包含自己这个窗口,只截Activity。然后根据传递过来的信息决定怎么裁剪,怎么拼接。
  4. 截屏窗口截屏之后告诉前台Activity已经截完屏了,可以继续滚动了。
  5. 注意,进行前面这些步骤的时候由于截屏app的窗口挡在上面,我们是完全看不到的。当滚动了一屏后的截屏内容得到后,那么我们已经有了不止当前屏幕的内容,还有了下一屏的内容,于是我们在界面上从原本的一张静态截屏图片,无缝的切换成由多张截屏拼接成的图片,然后开始做滚动动画(我自己感觉有种魔法般的感觉)。所以我们看到的内容滚动是滞后于真正的「截屏」动作的。
  6. 如此循环,直到点击了「结束」或到底。

大致就是这些。还有很多细节就不展开了。

值得一提的是,滚动的过程中,可以通过手指触摸切换成手动模式,这样我们可以精准的控制截到哪里。挺实用的。