如何在 2.2 之前的 Android 中禁用布局优化?

发布于 2024-10-13 10:36:51 字数 1165 浏览 0 评论 0原文

我创建了一个基于 LinearLayout 的自定义组件。这个想法是使其成为 XML 布局的一部分,例如:

<com.test.MyComponent 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical|center_horizontal"
    />

在运行时,组件动态创建其内容(通过添加 View 子类的实例)。这在 Android 2.2 和 2.3 上运行得很好,但在早期平台上该组件根本不显示。我花了很多时间去弄清楚为什么它消失了,终于弄清楚了原因。

在2.2之前的平台上,Android做了“聪明”的优化。它发现 XML 布局中使用的自定义类是 LinearLayout,并且它没有任何子级 - 因此它根本不需要显示它。

我尝试了多种解决方法。唯一或多或少成功的方法是向组件添加一个虚拟视图,使其不为空:

<com.test.MyComponent 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical|center_horizontal"
    >
    <View
        android:layout_width="1px"
        android:layout_height="1px"
        />
</com.test.MyComponent>

然后向组件的代码添加以下覆盖:

protected void dispatchDraw (Canvas canvas) {
    super.dispatchDraw(canvas);

    for (ChildView c : children) {
        c.draw(canvas);
    }
}

这允许组件及其内容出现,但存在虚拟视图的错误扰乱了与组件的交互,任何隐藏虚拟视图的尝试都会导致组件消失。

看起来有人投入了相当多的精力来创建优化,现在导致我花了一整天的时间来摆脱它。有人知道是否有办法禁用这种“有用的”优化?

I've created a custom component based on a LinearLayout. The idea is to make it a part of the XML layout, like:

<com.test.MyComponent 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical|center_horizontal"
    />

At runtime, the component creates its content dynamically (by adding instances of a View subclass). This works perfectly well on Android 2.2 and 2.3 but on the earlier platforms the component is simply not displayed. I spent a lot of time to figure out why it disappears and finally was able to figure out the reason.

On pre-2.2 platforms, Android does a "clever" optimisation. It figures out that the custom class used in the XML layout is a LinearLayout, and it doesn't have any children - so it doesn't bother displaying it at all.

I have tried numerous workarounds. The only one that was more or less successful is adding to the component a dummy view, so that it wasn't empty:

<com.test.MyComponent 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical|center_horizontal"
    >
    <View
        android:layout_width="1px"
        android:layout_height="1px"
        />
</com.test.MyComponent>

And then adding to the component's code the following override:

protected void dispatchDraw (Canvas canvas) {
    super.dispatchDraw(canvas);

    for (ChildView c : children) {
        c.draw(canvas);
    }
}

This allowed the component and its contents to appear, but the presence of the dummy view messed up the interaction with the component, and any attempt to hide the dummy causes the component to disappear.

Looks like someone has put quite a lot of effort into creating an optimisation that now causes me to spend the whole day to get rid of it. Does anybody know, if there is a way to disable this "helpful" optimisation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一场春暖 2024-10-20 10:36:51

没有这样的优化。如果视图的大小为 0、不与剪切矩形相交或者完全被不透明视图覆盖,则不会绘制视图。顺便说一句,如果您之前没有调用 setWillNotDraw(false) ,布局将不会调用其 onDraw() 方法。

你的问题听起来更像是布局问题。你实现了 onMeasure() 吗?向我们展示您实施的相关部分会有所帮助。

There's no such optimization. A view is not drawn if it has a size of 0, doesn't intersect with the clipping rectangle or if it's entirely covered by an opaque view. BTW, a layout will not invoke its onDraw() method if you don't call setWillNotDraw(false) before.

Your problem sounds more like a layout issue. Did you implement onMeasure()? Showing us the relevant parts of your implementation would help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文