forceLayout(),requestLayout()和invalidate()的用法

sda*_*bet 163 android android-layout android-view

我有点困惑的角色forceLayout(),requestLayout()以及invalidate()该方法的View类.

他们何时被召唤?

Bar*_*ski 329

为了更好地理解FrançoisBOURLIEUXDalvik提供的答案,我建议您看看Arpit Mathur的这个令人敬畏的视图生命周期图: 在此输入图像描述

  • 我经常看到在调用invalidate之后直接调用requestLayout,我甚至看到在Android源代码中发生了像TextView这样的事情,但根据这个图表这样做是多余的,对吧?这样做有什么目的吗? (26认同)
  • **(1/2)**:我不认为你明白这两种方法(`无效()`和`requestLayout()`)正确.这些方法的目的是告诉`View`发生了什么类型的*invalidation*(就像你所说的那样).它不像"View"决定在调用其中一种方法后要遵循的路径.选择"视图" - 生命周期路径背后的逻辑是选择适当的方法来调用自身.如果有相关的尺寸变化的东西 - `requestLayout()`应该叫,如果有改变,而一个尺寸仅为视觉变化 - 你应该叫'无效()`. (13认同)
  • **(2/2):**如果你改变你的`View`的大小以某种方式,例如,你**获取当前`LayoutParams`**的`View`并加以修改,但不****请调用`requestLayout`或`setLayoutParams`(它调用`内部requestLayout`),那么你可以调用`无效()`只要你想得多,而且`View`不会通过测量布局过程中去,因此,不会改变它的大小.如果你不告诉你`View`它的大小发生了变化(以`requestLayout`方法调用),那么'View`将假设没有,和`onMeasure`和`onLayout`不会调用. (10认同)
  • 那是一个有趣的问题,说实话,我真的不知道为什么他们在例如`TextView`中调用这两种方法.我想也许他们想要在改变布局相关参数之前最后一次绘制`View`,但是如果我们考虑以不同的顺序调用这些调用它们并没有任何意义(并且它们调用在`TextView`中的`requestLayout()`之后``invalidate()`.也许它值得StackOverflow上的另一个问题:)? (5认同)
  • @tcox 更多在这里 --> http://stackoverflow.com/questions/35279374/why-is-requestlayout-being- called-directly-after-invalidate/40402309#40402309 (2认同)

Sur*_*gch 113

invalidate()

invalidate()当您想要重新绘制视图时,将进行调用.它onDraw最终会被调用(很快,但不会立即).自定义视图调用它的示例是文本或背景颜色属性发生更改时的示例.

视图将被重绘,但大小不会改变.

requestLayout()

如果您的视图的某些内容发生变化会影响大小,那么您应该致电requestLayout().这将触发onMeasure并且onLayout不仅针对此视图,而且针对父视图一直向上触发.

呼叫requestLayout()不能保证导致onDraw(相反的是在公认的答案图暗示),因此它通常是与结合invalidate().

invalidate();
requestLayout();
Run Code Online (Sandbox Code Playgroud)

例如,自定义标签的文本属性已更改.标签会改变尺寸,因此需要重新测量和重新绘制.

forceLayout()

如果requestLayout()在父视图组上调用了该视图,则无需重新测量并重新传输其子视图.但是,如果孩子应该被包括在重新测量和重新布局中,那么你可以打电话forceLayout()给孩子.forceLayout()仅适用于requestLayout()与其直接父母一起发生的儿童.单独调用forceLayout()将不起作用,因为它不会触发requestLayout()视图树.

阅读此问答以获取更详细的说明forceLayout().

进一步研究

  • @scholt,据我所知,顺序并不重要,所以如果你愿意,你可以在 `invalidate()` 之前调用 `requestLayout()` 。两者都不会立即进行布局或绘制。相反,他们设置的标志最终将导致重新布局和重绘。 (2认同)

Fra*_*EUX 25

在这里您可以找到一些回复:http: //developer.android.com/guide/topics/ui/how-android-draws.html

对我来说,调用invalidate()只刷新视图和调用requestLayout()刷新视图并计算屏幕上视图的大小.

  • @suitianshi然后设置标志有什么后果? (7认同)
  • 那么forceLayout()呢? (3认同)

Ehs*_*adi 6

invalidate()--->onDraw()来自 UI 线程

postInvalidate()--->onDraw()来自后台线程

requestLayout()--->onMeasure()并且onLayout()并且不一定 onDraw()

  • 重要提示:调用此方法不会影响被调用类的子类。

forceLayout()--->onMeasure()并且onLayout() 只要直接父级调用requestLayout().