Android SurfaceView在加载时闪烁黑色
我有一个绘图应用程序,为复杂的绘图加载绘图大约需要2-5秒(通过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
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第一次出现在窗口中时,它通过调用privateIWindowSession.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);