Android SurfaceView在加载时闪烁黑色

Android SurfaceView在加载时闪烁黑色,android,surfaceview,android-canvas,Android,Surfaceview,Android Canvas,我有一个绘图应用程序,为复杂的绘图加载绘图大约需要2-5秒(通过AsyncTask完成)。为了获得更好的用户体验,在此期间,我以ImageView的形式将应用程序目录中存储的图形的PNG版本闪存,并在活动构造函数中显示加载ProgressBar调用setContentView(): <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/r

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

<?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>
当我使用一个简单的
Canvas
模型时,它工作得非常好,因为定制的DrawingCanvas
视图将在向用户显示之前将图形绘制到初始的
onDraw()
屏幕上,但现在使用带有绘图循环的
SurfaceView
,我看到了闪烁的布局,然后,当加载绘图时,会出现大约一秒钟的黑屏,最后是新的DrawingCanvas

我假设原因与绘图循环线程的启动时间有关,我将
onDraw()
的覆盖部分留在
SurfaceView
中,并调用它,但
onDraw()
中可用的画布似乎没有绘制到
SurfaceView
。我还尝试在上面的XML中设置纯色背景,希望至少显示白色背景,但这些似乎从未起作用,甚至从代码中设置

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

编辑:

好的,我们已经确认onDraw()是在同一画布上绘制的,所以将我的draw ops放在那里,希望在SurfaceView的初始显示中,用户可以像常规画布实现中一样看到这些图形,当绘制线程旋转时,它会覆盖画布

但是,如果我清除绘图线程操作,我确实会看到onDraw()结果,但是在黑屏闪烁之后。如果我完全删除onDraw()覆盖,我仍然会看到黑色的闪光,然后从XML中看到白色背景的布局

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

编辑2:

已尝试使用,以便在加载便笺后将SurfaceView充气到现有视图中,但相同的问题仍然适用。据我所知,SurfaceView构造函数和对surfaceCreated()的调用执行之间有相当大的延迟(~200ms),但不确定这是否是黑屏发生的地方,也不确定为什么屏幕会变黑

编辑3:

我现在的最后一次尝试包括做最后一次。这与保留现有布局并通过ViewStub简单地添加到该布局相结合,将产生一个可行的解决方案,尽管如此,当SurfaceView加载时,屏幕会在SurfaceView显示为透明之前闪烁黑色。如果有人有其他想法可以尝试,请发布。

“onDraw()中提供的画布似乎没有吸引到SurfaceView”
-是否确实不创建曲面视图的第二个(或第三个…)实例?其中一些可能是黑色的,可以显示一秒钟。我在这里看不到代码,所以我不能确定,但是如果它在我的应用程序中,我会首先检查这个错误

我不会在两个单独的布局中这样做

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


工作线程加载图形并且SurfaceView可以自己绘制后,从视图层次结构中删除进度条和ImageView。

您需要确保onSurfaceChanged()直到您完全绘制并发布SurfaceView曲面的内容后才会返回。

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

我想我找到了黑色闪烁的原因。在我的例子中,我在片段中使用了一个SurfaceView,并在一些操作之后动态地将该片段添加到活动中。当我将片段添加到活动中时,屏幕会闪烁黑色。我检查了SurfaceView源代码的grepcode,我发现:当SurfaceView第一次出现在窗口中时,它通过调用private
IWindowSession.relayout(…)
方法请求更改窗口的参数。此方法“提供”了一个新的框架、窗口和窗口曲面。我想屏幕在那一刻会闪烁

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


更新:看起来多年后这种行为仍然存在。我建议使用SurfaceView而不是SurfaceView。这实际上是一个更新的实现,没有这种副作用,也没有移动它时出现黑色背景的问题(例如在ScrollView、ViewPager、RecyclerView等中)

如果将NavigationDrawer与片段一起使用,Evos解决方案将无法工作<
<?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>
getWindow().setFormat(PixelFormat.TRANSLUCENT);