首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SurfaceView在加载时呈黑色闪烁

SurfaceView在加载时呈黑色闪烁
EN

Stack Overflow用户
提问于 2012-01-08 04:28:59
回答 8查看 22.1K关注 0票数 34

我有一个绘图应用程序,需要大约2-5秒来加载复杂的绘图(通过AsyncTask完成)。为了获得更好的用户体验,在此期间,我将应用程序目录中存储的绘图的PNG版本刷新为ImageView,并在Activity构造函数中显示了一个调用setContentView()的加载ProgressBar

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
    android:id="@+id/flash"
    android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@color/note_bg_white"
        android:contentDescription="@string/content_desc_flash_img"
        android:focusable="false" />
<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="6dp"
        android:paddingLeft="6dp"
    android:paddingRight="6dp"
        android:gravity="bottom|center_vertical">
        <ProgressBar 
            style="?android:attr/progressBarStyleHorizontal"
    android:id="@+id/toolbar_progress"
    android:layout_width="match_parent"
    android:layout_height="18dp"
    android:gravity="bottom|center_vertical" />
    </RelativeLayout>
</FrameLayout>

AsyncTask完成后,我使用新的布局再次调用setContentView()

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff">
    <com.my.package.DrawingCanvas
        android:id="@+id/canvas"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="true"
        android:background="#ffffff" />
</RelativeLayout>

当我使用一个简单的Canvas模型时,这工作得很好,因为自定义的DrawingCanvas View会在显示给用户之前在初始的onDraw()上将绘图绘制到屏幕上,但是现在使用带有绘图循环的SurfaceView,我看到了闪烁的布局,然后当绘图加载时,黑屏大约一秒钟,最后是新的DrawingCanvas。

我假设原因与绘制循环线程的启动时间有关,并且我在SurfaceView中保留了我的onDraw()覆盖,它会被调用,但onDraw()中可用的画布似乎不能绘制到SurfaceView。我还尝试在上面的XML中设置纯色背景,希望至少显示白色背景,但这些设置似乎永远不会生效,即使是从代码中设置也是如此。

对我在黑屏上看到的东西有什么建议或解释吗?

编辑:

好的,我已经确认了onDraw()正在绘制相同的画布,所以我的绘制操作也留在了那里,希望在SurfaceView的初始显示中,用户可以像常规画布实现一样看到这些绘制,当绘制线程旋转起来时,它将覆盖画布。

但是,如果我清除了绘制线程操作,我确实会看到onDraw()结果,但在黑屏闪烁之后又一次看到了。如果我完全删除了onDraw()覆盖,我仍然可以看到黑色的闪光灯,然后我可以看到带有白色背景的布局。

所以,看起来不管怎样,我总是会看到黑屏,除非我不是切换布局,而是简单地修改已经激活的“flash”布局?

EDIT2:

我已经尝试使用ViewStub,以便我可以在加载注释后将SurfaceView膨胀到现有视图中,但同样的问题仍然适用。据我所知,在SurfaceView构造函数和执行surfaceCreated()调用之间有相当大的延迟(~200ms),但不确定这就是黑屏发生的地方,也不确定为什么屏幕被画成黑屏……

EDIT3:

我现在的最后一次尝试包括制作SurfaceView transparent。再加上保持现有布局不变并通过ViewStub简单地添加到该布局,我认为这将是一个可行的解决方案,但仍然有那么一瞬间,当SurfaceView加载时,屏幕在SurfaceView显示之前会闪烁黑色,显示为透明。如果任何人有任何其他想法可以尝试,请张贴。

EN

回答 8

Stack Overflow用户

发布于 2012-09-28 16:22:28

我想我找到黑色闪光灯的原因了。在我的例子中,我在片段中使用了一个SurfaceView,并在一些操作之后动态地将这个片段添加到activity中。当我将片段添加到活动中时,屏幕闪烁黑色。我检查了SurfaceView源代码的grepcode,下面是我发现的:当表面视图第一次出现在窗口中时,它会通过调用私有IWindowSession.relayout(..)方法来请求更改窗口的参数。这个方法“给”你一个新的框架、窗口和窗口表面。我想在那一刻屏幕就会闪烁。

解决方案很简单:如果你的窗口已经有了合适的参数,它不会刷新所有的窗口内容,屏幕也不会闪烁。最简单的解决方案是在活动的第一个布局中添加一个0px height纯SurfaceView。这将在活动显示在屏幕上之前重新创建窗口,当您设置第二个布局时,它将继续使用当前参数的窗口。我希望这能帮到你。

更新:看起来多年后这个行为仍然存在。我建议使用TextureView而不是SurfaceView。从字面上来说,这是一个更新的实现,同样的东西没有这个副作用,而且当你移动它时也不会有黑色背景的问题(例如在ScrollView,ViewPager,RecyclerView等)。

票数 150
EN

Stack Overflow用户

发布于 2012-01-16 20:02:20

我不会用两个单独的布局来做这件事。

尝试将根元素设置为RelativeLayout,然后让SurfaceView和ImageView成为它的同级子元素。无论线程等发生什么情况,ImageView都应该在SurfaceView上完全不透明地绘制,这样就不会出现闪光。

一旦工作线程加载了绘图并且SurfaceView可以自行绘制,请从视图层次结构中删除进度条和ImageView。

票数 5
EN

Stack Overflow用户

发布于 2012-01-17 19:40:10

我假设您在曲面视图中绘制了一些繁重的代码,因为据我所知,曲面视图将在一次绘制所有内容后显示完整的视图。我建议您首先转到表面视图的onDraw()方法,然后在画布的背景上设置,然后调用强制无效以避免黑屏。添加一个条件以确保这个强制无效只被调用一次。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8772862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档