Android应用截图和SurfaceView截图问题(学生PAD抽奖系统)

来源:互联网 发布:js兄弟节点 编辑:程序博客网 时间:2024/06/05 11:13

问题描述

在开发用户中心“抽奖系统”项目模块时,有个功能是抽中奖品,中奖物品弹出时将背景全部模糊,效果图如下图1-1

图1-1 抽奖系统中奖界面效果图

要将背景进行模糊后并进行一系列的动画效果,这个处理流程大致为:

      ①  获取中奖后的最后一帧背景图

      ②  将背景图进行缩放、模糊处理

      ③  将处理后的背景图设置给中奖界面,并进行后续动画效果。

思路很简单,但是在实际开发中就会出现了不少问题,主要难点还是在于第一步: 如何获取中奖后最后一帧的背景图片。可能大部分同学都觉得系统提供了截屏的接口,直接调用就可以获取到了或者从Window的DrawbleCache中直接获取。 那么我们可以来看一下,通过这些方式我们获取的背景图片会是什么样的,见下图1-2:




图1-2 正常截屏效果图

是不是很奇怪,为什么会有黑屏,是不是我截屏的方式错误了? 那么出现这个原因我们得先大致描述一下该界面搭建所采用的技术。


抽奖系统界面搭建方案说明

① 由于策划事先声明后期可能存在多种方式的抽奖,所以我采用了Activity+(ViewPager+Fragment)的方式搭建了这个界面结构。

② 抽奖的主界面,考虑到界面刷新的频率较高,有玩过的同学会知道,该抽奖的效果较多,所以采用了具备双缓冲特性的SurfaceView来完成这个矩形抽奖界面。

③ 整个外围的界面搭建主要就是采用上述描述的技术。具体内部实现比如这个一个个选项框如何绘制成一个矩形(后续会有博文进行说明)


截屏黑屏原因分析

通过上述描述,对SurfaceView有了解的同学应该会知道,黑屏的原因就是在于SurfaceView的实现原理:

       SurfaceView通常有两个缓冲区(buffer), 一个front buffer,一个back buffer。而back buffer就是Canvas对应的bitmap。每当frong buffer显示时,back buffer就迅速的绘制,然后front buffer迅速将当前的back buffer显示给用户。由于速度十分快,所以便形成了动画效果。View是在UI的主线程中更新画面,而SurfaceView是在一个新线程中更新画面。这就需要你new一个新线程,在新线程里面进行绘画的工作。 SurfaceView通过SurfaceHolder对象将back buffer画好的内容更新到front buffer。 这也就是为什么我们在使用SurfaceView时需要将canvas进行锁定。 这里就不具体描述SurfaceView的用法,不太了解的同学可以自行去google一下。

       那么说了这么多,SurfaceView和普通View有什么区别? (静态与动态的区别)

主要在于普通View内容draw之后,是静态的,我们不调用invalidate它就放在那, 拿到了Bitmap之后,我们可以获取到里面的内容。但是SurfaceView不同,我们无法拿到back buffer里面的bitmap。所以我们以往常用的截屏方案就不能够达到截下SurfaceView的效果。

黑屏解决方案

普通截屏代码如下:

// View是你需要截图的View  View view = activity.getWindow().getDecorView();  view.setDrawingCacheEnabled(true); // 开启cache  view.buildDrawingCache();  Bitmap b1 = view.getDrawingCache();// 获取cache的图片 通过以上代码我们就可以获取到静态界面的背景图片


SurfaceView的截屏代码如下:

分析:由于SurfaceHolder.lockCanvas()返回的Canvas是用来更新SurfaceView的,所以我们只需要自己定义个画板Canvas将当前SurfaceView绘制的内容绘制到我们自己的画板上,那么我们之前提供的Bitmap就绘制上了当前SurfaceView  back buffer里面的内容。

Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);   Canvas canvas = new Canvas(bitmap);   draw(canvas);  // SurfaceHolder.lockCanvas()返回的Canvas 绘制什么内容,我们定义的也绘制一遍。

绘制结束后我们传入的bitmap就已经有了我们需要的内容


普通View和SurfaceView图片组合问题

Rect r = new Rect(); vLotteryRectView.getGlobalVisibleRect(r); fuzzyBgBitmap = vLotteryRectView.takeScreenShot(r, mActivity); // 模糊掉的背景图

主要是通过vLotteryRectView.getGlobalVisibleRect(r);   方法来获取当前vLotteryRectView (SurfaceView) 的Rect值。 通过Rect我们就可以非常完美的获取到抽奖界面距离屏幕的上下左右数值。

进而将SurfaceView 完美的绘制在普通View黑屏的地方。获取到组合的背景图片之后,我们就可以将该图片进行相应的图片处理。来达到我们想要的效果


实际项目效果图

通过上述方案最终达到的效果如下图1-4所示:



图1-4 实现的效果图

PS: 图片中背景有点怪其实是因为缩放的原因,可以采用很多方案进行解决,这里就不做处理了,希望本篇文章可以帮助到需要帮助的朋友。





0 2
原创粉丝点击