jjzjj

android - SurfaceView 在加载时闪烁黑色

coder 2023-06-06 原文

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

<?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():

<?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() 中可用的 Canvas 似乎没有绘制到 SurfaceView。我还尝试在上面的 XML 中设置纯色背景,希望至少显示白色背景,但这些似乎从未生效,即使从代码中设置也是如此。

对我在黑屏中看到的内容有何建议或解释?

编辑:

好的,已经确认 onDraw() 正在绘制到同一个 Canvas 上,所以将我的绘制操作留在了那里,同时希望在 SurfaceView 的初始显示时,用户会像在常规 Canvas 实现中一样看到这些绘图,当绘图线程启动时,它会覆盖 Canvas 。

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

所以,看起来无论如何,我总是会看到黑屏,除非我可能不是切换布局,而是简单地修改已经处于 Activity 状态的现有“flash”布局?

EDIT2:

已尝试使用 ViewStub这样我就可以在加载注释后将 SurfaceView 充气到现有 View 中,但同样的问题仍然适用。据我所知,在 SurfaceView 构造函数和对 surfaceCreated() 的调用之间存在相当大的延迟(~200ms),但不确定这是黑屏发生的地方,或者屏幕被绘制到的原因黑...

EDIT3:

我现在的最后一次尝试包括制作 SurfaceView transparent .这与保留现有布局并简单地通过 ViewStub 添加到该布局相结合,虽然会产生一个可行的解决方案,但仍然在 SurfaceView 加载时的一瞬间,屏幕在 SurfaceView 显示之前闪烁黑色,一样透明。如果有人有任何其他想法可以尝试,请发布。

最佳答案

我想我找到了黑闪的原因。在我的情况下,我在 Fragment 中使用 SurfaceView 并在某些操作后动态将此 fragment 添加到 Activity 中。当我将 fragment 添加到 Activity 中的那一刻,屏幕闪烁黑色。我检查了 SurfaceView 源的 grepcode,这是我发现的:当表面 View 第一次出现在窗口中时,它通过调用私有(private) IWindowSession.relayout(..) 请求更改窗口的参数> 方法。这种方法“给”你一个新的框架、窗口和窗口表面。我认为屏幕在那一刻闪烁。

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

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

关于android - SurfaceView 在加载时闪烁黑色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8772862/

有关android - SurfaceView 在加载时闪烁黑色的更多相关文章

  1. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  4. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  5. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  6. ruby-on-rails - 使用 gmaps4rails 动态加载谷歌地图标记 - 2

    如何只加载map边界内的标记gmaps4rails?当然,在平移和/或缩放后加载新的。与此直接相关的是,如何获取map的当前边界和缩放级别? 最佳答案 我是这样做的,我只在用户完成平移或缩放后替换标记,如果您需要不同的行为,请使用不同的事件监听器:在你看来(index.html.erb):{"zoom"=>15,"auto_adjust"=>false,"detect_location"=>true,"center_on_user"=>true}},false,true)%>在View的底部添加:functiongmaps4rail

  7. ruby-on-rails - 是否可以让 ActiveRecord 为使用 :joins option? 加载的行创建对象 - 2

    我需要做这样的事情classUser'User',:foreign_key=>'abuser_id'belongs_to:gameendclassGame['JOINabuse_reportsONusers.id=abuse_reports.abuser_id','JOINgamesONgames.id=abuse_reports.game_id'],:group=>'users.id',:select=>'users.*,count(distinctgames.id)ASgame_count,count(abuse_reports.id)asabuse_report_count',:

  8. ruby - 运行 rackup private_pub.ru -s thin -E production 命令时无法加载此类文件 -- thin (LoadError) - 2

    我指的是pubrailscasttutorial并已正确执行所有步骤,但在运行最后一个命令时,即rackupprivate_pub.ru-sthin-Eproduction为了架设faye服务器,我收到以下错误:/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in`require':cannotloadsuchfile--thin(LoadError)from/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in`require'from/var/lib/gems/1.9.1/gems

  9. ruby - libxml-ruby 无法在 x86_64 上加载 - 2

    我们在服务器端遇到libxml-rubygem的问题可能是因为它使用x86_64架构:$uname-aLinuxip-10-228-171-642.6.21.7-2.fc8xen-ec2-v1.0#1SMPTueSep110:25:30EDT2009x86_64GNU/Linuxrequire'libxml'LoadError:/usr/local/ruby-enterprise/lib/ruby/gems/1.8/gems/libxml-ruby-1.1.4/lib/libxml_ruby.so:invalidELFheader-/usr/local/ruby-enterprise/

  10. Ruby 不从 stdlib 加载 CSV - 2

    我不太确定为什么这不起作用,我一直在寻找解决方案。很简单,我正在运行一个执行require'CSV'的小脚本。,它在我的Mac1.9.3-p327上运行良好,但在p374上的服务器上无法运行。我得到的错误是/home/deployer/.rbenv/versions/1.9.3-p374/lib/ruby/1.9.1/rubygems/custom_require.rb:36:inrequire':cannotloadsuchfile--CSV(LoadError)from/home/deployer/.rbenv/versions/1.9.3-p374/lib/ruby/1.9.1/

随机推荐