为什么硬件加速在我的视图上不起作用?

2024-01-14

我在用着Facebook 的 Rebound 库 http://facebook.github.io/rebound/复制聊天头实现中看到的弹性动画。问题是,大多数时候动画都会断断续续。几张图片会更好地解释这一点。这是黄油般流畅的聊天头动画:

这是我的尝试(注意白色的动画如何View跳过几乎所有帧):

偶尔它会顺利运行:

下面是我当前使用的代码(整个项目是在 Github 上 https://github.com/vickychijwani/BubbleNote/tree/eb708e3910a7279c5490f614a7150009b59bad0b如果您想快速设置)。我猜这与我的硬件加速未正确启用有关View。有2个Springs in my SpringSystem,一个代表“气泡”(Android 图标),另一个代表内容(白色View点击气泡时显示)。任何有关如何解决此问题的帮助将不胜感激。谢谢。

AndroidManifest.xml:

    <application android:hardwareAccelerated="true" ...>
        ...
    </application>

AppService.java:

    // the following code is in AppService#onCreate()
    // AppService extends android.app.Service
    // full code at https://github.com/vickychijwani/BubbleNote

    mContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);

    final Spring bubbleSpring = system.createSpring();
    bubbleSpring.setCurrentValue(1.0);
    bubbleSpring.addListener(new SpringListener() {
        @Override
        public void onSpringUpdate(Spring spring) {
            float value = (float) spring.getCurrentValue();
            params.x = (int) (mPos[0] * value);
            params.y = (int) (mPos[1] * value);
            mWindowManager.updateViewLayout(mBubble, params);
            // fire the second animation when this one is about to end
            if (spring.isOvershooting() && contentSpring.isAtRest()) {
                contentSpring.setEndValue(1.0);
            }
        }

        // ...
    });

    final Spring contentSpring = system.createSpring();
    contentSpring.setCurrentValue(0.0);
    contentSpring.addListener(new SpringListener() {
        @Override
        public void onSpringUpdate(Spring spring) {
            // always prints false?!
            Log.d(TAG, "hardware acc = " + mContent.isHardwareAccelerated());
            float value = (float) spring.getCurrentValue();
            // clamping is required to prevent flicker
            float clampedValue = Math.min(Math.max(value, 0.0f), 1.0f);
            mContent.setScaleX(value);
            mContent.setScaleY(value);
            mContent.setAlpha(clampedValue);
        }

        // ...
    });

我通过查看框架源代码已经弄清楚了。

TL;DR: add WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED当您手动附加一个布局标志时View to a Window / WindowManager;环境android:hardwareAccelerated=true在清单中将不起作用。


I'm 手动附加我的View to the WindowManager https://github.com/vickychijwani/BubbleNote/blob/eb708e3910a7279c5490f614a7150009b59bad0b/app/src/main/java/io/github/vickychijwani/bubblenote/BubbleNoteService.java#L54(因为我需要在Service模拟聊天头),如下所示:

    // code at https://github.com/vickychijwani/BubbleNote/blob/eb708e3910a7279c5490f614a7150009b59bad0b/app/src/main/java/io/github/vickychijwani/bubblenote/BubbleNoteService.java#L54
    mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    mBubble = (LinearLayout) inflater.inflate(R.layout.bubble, null, false);
    // ...
    final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);
    // ...
    mWindowManager.addView(mBubble, params);

我们去挖吧...

欢迎使用 Android 框架

我开始调试View#draw(...) http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/view/View.java?av=f#14069,然后向上调用堆栈ViewRootImpl#draw(boolean) http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/view/ViewRootImpl.java?av=f#2280。在这里我遇到了这段代码:

    if (!dirty.isEmpty() || mIsAnimating) {
        if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) {
            // Draw with hardware renderer.
            mIsAnimating = false;
            mHardwareYOffset = yoff;
            mResizeAlpha = resizeAlpha;

            mCurrentDirty.set(dirty);
            dirty.setEmpty();

            attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
                    animating ? null : mCurrentDirty);
        } else {
            // If we get here with a disabled & requested hardware renderer, something went
            // wrong (an invalidate posted right before we destroyed the hardware surface
            // for instance) so we should just bail out. Locking the surface with software
            // rendering at this point would lock it forever and prevent hardware renderer
            // from doing its job when it comes back.
            // Before we request a new frame we must however attempt to reinitiliaze the
            // hardware renderer if it's in requested state. This would happen after an
            // eglTerminate() for instance.
            if (attachInfo.mHardwareRenderer != null &&
                    !attachInfo.mHardwareRenderer.isEnabled() &&
                    attachInfo.mHardwareRenderer.isRequested()) {

                try {
                    attachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
                            mHolder.getSurface());
                } catch (OutOfResourcesException e) {
                    handleOutOfResourcesException(e);
                    return;
                }

                mFullRedrawNeeded = true;
                scheduleTraversals();
                return;
            }

            if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {
                return;
            }
        }
    }

就我而言ViewRootImpl#drawSoftware() http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/view/ViewRootImpl.java?av=f#2420被调用,它使用软件渲染器。嗯……这意味着HardwareRenderer is null。所以我去寻找建造的点HardwareRenderer,这是在ViewRootImpl#enableHardwareAcceleration(WindowManager.LayoutParams) http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/view/ViewRootImpl.java?av=f#681:

    // Try to enable hardware acceleration if requested
    final boolean hardwareAccelerated =
            (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
    if (hardwareAccelerated) {
        // ...
        mAttachInfo.mHardwareRenderer = HardwareRenderer.createGlRenderer(2, translucent);
        // ...
    }

啊哈!我们的罪魁祸首就在这里!

回到手头的问题

在这种情况下Android不会自动设置FLAG_HARDWARE_ACCELERATED为了这Window,尽管我已经设置了android:hardwareAccerelated=true在清单中。所以修复方法很简单:

    mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    mBubble = (LinearLayout) inflater.inflate(R.layout.bubble, null, false);
    // ...
    final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            // NOTE
            WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);
    // ...
    mWindowManager.addView(mBubble, params);

虽然动画还是不如Facebook的流畅。我想知道为什么......(在有人问之前:不,动画期间没有大量日志;是的,我尝试过发布版本)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么硬件加速在我的视图上不起作用? 的相关文章

随机推荐

  • 将文本/标签添加到 D3 力定向图中的链接上

    我一直在研究修改后的力定向图 并且在将文本 标签添加到链接上时遇到一些问题 其中链接与节点未正确对齐 如何修复它 如何向 SVG 文本元素添加事件侦听器 添加 on dblclick function d 就是不行 这是代码片段
  • 如何动态计算 UILabel 高度[重复]

    这个问题在这里已经有答案了 我有以下代码 label numberOfLines 0 allows label to have as many lines as needed label text some long text label
  • 基于 SSL 的 CFHTTP

    我正在尝试使用 ColdFusion 通过 SSL 从服务器检索文件CFHTTP标记没有成功 我们的环境是使用服务器配置的Linux 使用的密钥库位于cf root runtime jre lib security cacerts 我从目标
  • 如何在Flask中实现基于角色的访问控制?

    是否有任何积极维护的插件可以帮助我创建具有基于角色的访问控制的 Flask 应用程序 例如管理员角色 会计角色 人力资源角色 Flask User看起来不错 但这些讨论表明维护者已经走了 Flask Login needs Flask Se
  • lambda 捕获的生命周期

    给出以下程序 include
  • 找不到分段用户的资源 - 应用程序令牌

    我能够进行身份验证并获取应用程序令牌以使用 Microsoft Graph API 我已设置所有委派和管理权限来访问用户 我还使用图形浏览器来验证我需要什么权限 https developer microsoft com en us gra
  • IIS 7.5 自定义 404 错误页面不适用于 Web 根索引/默认

    我使用 IIS 7 5 创建了一个自定义 404 和 403 14 错误页面 如果未找到静态文件 该页面将显示数据库中的内容 换句话说 如果我浏览到http mysite com test http mysite com test 如果在该
  • 当应用程序运行时,如何在android中以编程方式关闭通知?

    我正在尝试开发一个android我正在其中实现聊天功能的应用程序 但当我收到消息时 它会发出通知声音 用户使用应用程序时如何停止通知以编程方式 private void ChatNotifications String uid String
  • 引导多选搜索从数据库获取值

    我正在使用引导多选 https davidstutz github io bootstrap multiselect 在我的项目中 在搜索中我试图通过以下方式获取数据库值ajax请求 但它没有附加 这是我的代码 example gettin
  • 如何解析包含多个文档的 YAML 文件?

    这是我的解析代码 import yaml def yaml as python val Convert YAML to dict try return yaml load all val except yaml YAMLError as e
  • Locust:如何让 Locust 运行特定的时间

    官方的蝗虫文档 http docs locust io en latest 讲述如何编写无限期运行的简单 Locust 任务 无法找到如何运行持续特定时间的负载 以便测试在指定的时间间隔后自动停止 我不需要从网络界面获得它 命令行 代码选项
  • Git:执行提交后,显示上次推送到每个远程的日期

    我想要一个简单的 git 提交后操作 打印上次将更改推送到每个远程的日期 这样做的动机是简单地提醒您的存储库可能会变得不同步 或者很好地提醒您将更改备份到远程裸存储库 这是否存在 如果没有关于如何做到这一点的快速建议 如果它不存在 我最初的
  • aurelia 中的自定义属性不起作用?

    我正在学习 Aurelia 的工作原理 并且正在尝试让一个简单的自定义属性正常工作 它所做的只是根据某些值的变化来改变 div 文本的颜色 我有一个 div 其中包含 high bind changeColor 在我的属性中我有 impor
  • 适合简单游戏的易于使用的 3D 图形引擎? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 Entity Framework 5 Code First 迁移中重命名数据库列而不丢失数据?

    我使用 EF 5 0 Code First 迁移成功运行了默认的 ASP NET MVC 4 模板 但是 当我更新模型属性名称时 EF 5 0 会删除相应的表列数据 是否可以在不以自动方式删除数据的情况下重命名表列 手动编辑迁移的Up和Do
  • 如何使用 EF6 删除 1,000 行?

    我正在使用实体框架 6 我有一个包含测试信息的表 称为 测试 我正在删除 通过首先获取测试列表 执行以下操作从该表中获取行 每个删除然后提交 var testList testService GetTests 1 userId ToList
  • 如何在 Numba 中使用指针包装 CFFI 函数

    这应该是一项简单的任务 但我找不到如何将标量值的指针传递给 Numba 函数内的 CFFI 函数的方法 使用以下命令将指针传递给数组可以毫无问题ffi from buffer 示例函数 import cffi ffi cffi FFI de
  • 将两个字节读入一个整数?

    我有一个byte 我已经从文件中读取了 并且我想要得到一个int从其中的两个字节 这是一个例子 byte bytes new byte byte 0x00 byte 0x2F byte 0x01 byte 0x10 byte 0x6F in
  • 正在使用的 Azure 应用服务部署文件

    在我的项目中 我们使用 Azure App Service Deploy 任务来部署我们的 webdeploy 包 我注意到有时在部署时会出现文件使用错误 即使已设置 使应用程序离线 选项也是如此 解决这个问题的最佳方法是什么 这是错误 2
  • 为什么硬件加速在我的视图上不起作用?

    我在用着Facebook 的 Rebound 库 http facebook github io rebound 复制聊天头实现中看到的弹性动画 问题是 大多数时候动画都会断断续续 几张图片会更好地解释这一点 这是黄油般流畅的聊天头动画 这