【问题标题】:How do I trigger the redraw of a parent View when any of it's children are redrawn?重绘任何子视图时,如何触发父视图的重绘?
【发布时间】:2011-10-13 11:22:19
【问题描述】:

背景

我已经编写了一个基于LinearLayout 的自定义Android 视图,我称之为ReflectingLayout。这个想法相当简单,在ReflectingLayout 中声明的任何子视图下方呈现反射效果。比如……

我通过在ReflectingLayout 中覆盖dispatchDraw() 来实现这一点,如下所示:

@Override
protected void dispatchDraw(Canvas canvas) {

  Bitmap bitmap = Bitmap.createBitmap(...); 
  Canvas tempCanvas = new Canvas(bitmap);

  // Draw child views to bitmap using tempCanvas
  super.dispatchDraw(tempCanvas);

  ...
  // some tranformations performed on bitmap
  ...

  // draw transformed image on to main canvas
  canvas.drawBitmap(bitmap, 0, 0, null);
}

问题

如果我的ReflectingLayout 包含TextView 并且我更改了TextView 的文本内容,则反射效果不会更新。

我相信这是因为 Android 只会重绘 TextView 本身,而不是所有父视图,这意味着我的覆盖 dispatchDraw() 方法不会被调用。

是否有任何简单的方法来触发父视图的重绘以响应其任何子视图的变化?

特别是,当子视图被重绘时,我怎样才能让我的ReflectingLayout 被重绘?

我已经考虑过的事情

  • 我注意到在 API 级别 11 中添加了一个新的View.OnLayoutChangeListener。大概这可用于注册父视图的回调并触发重绘(?)。无论如何,我需要一个适用于 API Level 7 以上的解决方案。

  • 我可以简单地扩展 TextView 和我想在 ReflectingLayout 中声明的任何其他 View 类,以便在重绘它们时使其父级无效,但这是一个笨拙的解决方案。

收到的任何帮助(包括如果您认为整体方法是错误的)。

谢谢。

【问题讨论】:

  • 您是否尝试通过调用invalidate() 使您的视图无效(= 重绘标记)?是整个ReflectingLayout 还是通过编写一个帮助方法来更改textviews 文本并在此之后使反射视图无效?
  • 这就是我现在正在使用的当前 hack 作为我的活动中的解决方法。即在我更改TextView 时,我在ReflectingLayout 上调用invalidate()。我只是不希望 ReflectingLayout 不得不依赖主机活动来使其无效 - 可移植性差、封装等。
  • 你有没有找到更好的解决方案?
  • 恐怕黑客仍然存在...... :-(

标签: android user-interface android-layout android-widget


【解决方案1】:

在你看来使用getParent() 方法怎么样?像这样的:

if (getParent() instanceof View)
    ((View) getParent()).invalidate();

【讨论】:

    【解决方案2】:

    我刚遇到这个问题。我发现这是由于 3.0+ 中的新硬件加速支持我解决它的方法是使用View#setLayerType 和使用LAYER_TYPE_SOFTWARE。为了继续针对 API 级别 8,我使用反射在支持 android 平台上调用此方法。这解决了问题,现在我的自定义 ViewGroup 在子级无效时正确绘制。

    我不知道这是否能完全解决您的问题,但它可能会帮助其他同样被此问题困扰的人。

    反射代码,非常基础:

    try {
        Method method =
                CustomViewGroup.class.getMethod("setLayerType", new Class[] { Integer.TYPE, Paint.class });
        // 0x1 == LAYER_TYPE_SOFTWARE
        method.invoke(this, new Object[] { Integer.valueOf(0x1), null });
    } catch(SecurityException e) {
        Log.e(TAG, "reflectSetLayerType", e);
    } catch(NoSuchMethodException e) { // don't care
    } catch(IllegalArgumentException e) {
        Log.e(TAG, "reflectSetLayerType", e);
    } catch(IllegalAccessException e) {
        Log.e(TAG, "reflectSetLayerType", e);
    } catch(InvocationTargetException e) {
        Log.e(TAG, "reflectSetLayerType", e);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多