android8修改默认壁纸,给surfaceview设置默认背景

最近搞视频通话,SurfaceView是必不可少的,因为启动视频要加载一些资源,比较耗时,会有1.2s黑屏的现象,为了改善用户体验,咱们须要设置Activity的Theme为透明风格(QQ 也是如此),下面是我截取的日志,QQ和咱们启动视频通话界面(Activity)所花费的时间:html

Displayed com.xxx.xxx/.activity.voip.CallVoipVideoActivity: +491ms:接收视频邀请java

Displayed com.xxx.xxxx/.activity.voip.CallVoipVideoActivity: +1s737ms:发起视频邀请(包括加载视频预览)

Displayed com.tencent.mobileqq/com.tencent.av.ui.AVActivity: +1s977ms :发起视频邀请(QQ加载的资源更多,故会稍微再慢点,不过差异不大)

查看后台日志,发现一直在GC,当时我觉得内存泄露了,电脑卡的要死,Mat了半天。。。

问题来了,经测试发现,在视频预览出现时,常常界面上的按钮可见,可是包含SurfaceView的FrameLayout布局处倒是透明的,尽管我在主Activity的根布局设置了默认背景,只要你嵌套了SurfaceView而且SurfaceView未加载进内容,就会出现这种问题。

主Activity的布局以下:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/mainLayout"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="@drawable/a">

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/mainLayout"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="@drawable/a" >

其中,a是默认的背景图片,test1_item.xml是包含SurfaceView的子布局,以下:

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/testFr"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent"/>

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:text="挂断"/>

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/testFr"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:text="挂断" />

测试发现,在SurfaceView有内容加载进来以前,那部分一直是透明的,无论你根布局有木有设置默认背景。

关于这个问题的解释,咱们须要去了解下SurfaceView及Activity的原理:可参照:http://www.2cto.com/kf/201303/196117.html(SurfaceView理解);android

http://blog.csdn.net/qinjuning/article/details/7226787(关于Activity的原理)。ide

其中注意下两段话:布局

一、用来描述SurfaceView的Layer或者LayerBuffer的Z轴位置是小于用来其宿主Activity窗口的Layer的Z轴位置的,可是前者会在后者的上面挖一个“洞”出来,以便它的UI能够对用户可见。实际上,SurfaceView在其宿主Activity窗口上所挖的“洞”只不过是在其宿主Activity窗口上设置了一块透明区域。测试

二、DecorView类 :该类是PhoneWindow类的内部类,说明: 该类是一个FrameLayout的子类,而且是PhoneWindow的子类,该类就是对普通的FrameLayout进行功能的扩展,更确切点能够说是修饰(Decor的英文全称是Decoration,即“修饰”的意思),好比说添加TitleBar(标题栏),以及TitleBar上的滚动条等 。最重要的一点是,它是全部应用窗口的根View 。ui

解决办法就是动态添加SurfaceView,可是前提是要保证SurfaceView已经有咱们所须要的内容;第二个解决办法能够为SurfaceView设置一个默认的背景,背景的设置能够参照:http://bbs.csdn.net/topics/380141705,咱们能够分析到:surfaceview默认是黑色的背景,因此使用SurfaceView要特别注意这个问题(你所要显示的可能会被覆盖等现象),下边这三行代码是设置surfaceView控件背景透明:this

this.setZOrderOnTop(true);

//this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

this.getHolder().setFormat(PixelFormat.TRANSLUCENT);

不过中间那句是OpenGl的,视状况使用,无用可注释掉了,也能实现了透明,可是GLSurfaceView就必须使用

this.setZOrderOnTop(true);

//this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

this.getHolder().setFormat(PixelFormat.TRANSLUCENT);

不过中间那句是OpenGl的,视状况使用,无用可注释掉了,也能实现了透明,可是GLSurfaceView就必须使用

注意:SurfaceView添加背景后,要掉用setZOrderOnTop(true)这个方法才能把咱们的内容画上,要否则咱们所绘制的内容就在背景后面了,被背景覆盖。另外,在ViewPage中用到SurfaceView时,它所取到的画布是整个程序的画布,也就是在某个Activity里调用ViewPage时,ViewPage里包含SurfaceView,当ViewPage显示此SurfaceView就切换到别的Activity,那么SurfaceView所画的图会覆盖该Activity的界面。spa

哥们发现个人程序上述两个方法都没办法解决,只能设置默认背景了,就是你启动的时候的背景,在style文件中修改:.net

//黑屏问题

@drawable/voip_video_default_big

@null

//黑屏问题

@drawable/voip_video_default_big

@null

这样也能达到效果啦!不过若是要不黑屏,实质上仍是要分析下究竟是哪里的问题致使主线程较耗时,有些东西能够适当延后加载

Android SurfaceView 绘制默认黑色背景的原因是因为 SurfaceView 的绘制是在独立的线程中进行的,而不是在主线程(UI 线程)中进行的。在 SurfaceView 初始化时,默认情况下,它的背景是黑色。 要改变 SurfaceView背景颜色,可以通过在 SurfaceView 中重写 `draw` 方法来实现自定义绘制。在 `draw` 方法中,你可以使用 `Canvas` 对象进行绘制操作,包括设置背景颜色。以下是一个简单的示例代码: ```java public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holder; public MySurfaceView(Context context) { super(context); init(); } public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { holder = getHolder(); holder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { // 绘制方法 draw(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 空实现 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 空实现 } private void draw() { Canvas canvas = holder.lockCanvas(); // 获取画布对象 if (canvas != null) { try { // 设置背景颜色 canvas.drawColor(Color.WHITE); // 绘制其他内容 // ... } finally { holder.unlockCanvasAndPost(canvas); // 解锁画布,提交绘制内容 } } } } ``` 在这个示例中,我们通过重写 `surfaceCreated` 方法,在 SurfaceView 创建时调用 `draw` 方法来绘制内容。在 `draw` 方法中,我们使用 `Canvas` 对象设置了白色背景,并可以进行其他的绘制操作。记得在合适的时机解锁画布并提交绘制内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值