Android 什么时候需要在视图上执行 invalidate()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10647558/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When it's necessary to execute invalidate() on a View?
提问by mjaskowski
My answer to this questionwas just accepted but I started to wonder when exactly one needs to invalidate() a View and when it is not necessary?
我对这个问题的回答刚刚被接受,但我开始想知道什么时候需要 invalidate() 视图,什么时候不需要?
After a bit of thinking I came to realization that it shouldwork more or less like this:
经过一番思考,我意识到它应该或多或少像这样工作:
- actual drawing of "everything" occurs after
onResume()
- in "free" time parts of the screen can be redrawn but only those that were
invalidated
(and everything underneath)
- “一切”的实际绘制发生在
onResume()
- 在“空闲”时间部分屏幕可以重绘,但只能重绘那些
invalidated
(以及下面的所有内容)
Therefore, it would seem, if I change something after onResume()
(e.g. as a response to a button click, I should invalidate()
the changed View
).
因此,看起来,如果我在之后更改某些内容onResume()
(例如,作为对按钮单击的响应,我应该invalidate()
更改View
)。
However, from what scana in this questionsays, it must be more complex then that and it depends somethimes on what method one uses.
但是,从这个问题中的scana 所说的来看,它一定比那更复杂,这取决于人们使用的方法。
E.g. on whether one uses
例如,关于一个人是否使用
lastClicked.setImageBitmap();
or
或者
lastClicked.setImageResource();
So, when it's necessary to execute invalidate() on a View and how does it really work ?
那么,什么时候需要在 View 上执行 invalidate() 以及它是如何真正工作的?
采纳答案by Srdjan Grubor
Usually, the system handles resizing, hiding, showing and a ton of other things for your widgets automatically but it sometimes has issues if the underlying buffer for drawn pixels or backing data has changed or is stale (you swap the image resource on a View or the raw dataset changes). This occurs because there is no way that the OS can know that the data changed in the specific manner that it did.
通常,系统会自动为您的小部件处理调整大小、隐藏、显示和大量其他事情,但如果绘制像素或支持数据的底层缓冲区已更改或陈旧(您在 View 或原始数据集发生变化)。发生这种情况是因为操作系统无法知道数据以它所做的特定方式更改。
In these cases where you are dealing with drawing, you have to tell the system that its underlying data is not in a good state with Widget.invalidate()and the re-drawing gets queued on the main thread just as you mentioned. Depending on the system implementation and Android version what is tracked for changes by the system varies but what I normally do is assume that system resources (byte arrays, char arrays, resource indexes, manual drawing on the context) are not tracked and need an invalidateand everything else will be handled by the system.
在处理绘图的这些情况下,您必须使用Widget.invalidate()告诉系统其底层数据处于不良状态,并且正如您提到的那样,重新绘图在主线程上排队。根据系统实现和 Android 版本,系统跟踪更改的内容会有所不同,但我通常做的是假设系统资源(字节数组、字符数组、资源索引、上下文手动绘制)未被跟踪并且需要无效其他一切都将由系统处理。
回答by Nikolay Elenkov
(Do consider accepting some answers)
(请考虑接受一些答案)
Generally, invalidate()
means 'redraw on screen' and results to a call of the view's onDraw()
method. So if something changes and it needs to be reflected on screen, you need to call invalidate()
. However, for built-in widgets you rarely, if ever, need to call it yourself. When you change the state of a widget, internal code will call invalidate()
as necessary and your change will be reflected on screen. For example, if you call TextView.setText()
, after doing a lot of internal processing (will the text fit on screen, does it need to be ellipsised, etc.), TextView
will call invalidate()
before setText()
returns. Similarly for other widgets.
通常,invalidate()
意味着“在屏幕上重绘”并导致调用视图的onDraw()
方法。因此,如果某些内容发生变化并且需要反映在屏幕上,则需要调用invalidate()
. 但是,对于内置小部件,您很少(如果有的话)需要自己调用它。当您更改小部件的状态时,内部代码将invalidate()
根据需要调用,您的更改将反映在屏幕上。例如,如果您调用TextView.setText()
,在进行大量内部处理后(文本是否适合屏幕,是否需要省略等),TextView
将invalidate()
在setText()
返回之前调用。其他小部件也是如此。
If you implement a custom view, you will need to call invalidate()
whenever the backing model changes and you need to redraw your view. It can also be used to create simple animations, where you change state, then call invalidate()
, change state again, etc.
如果您实现自定义视图,您将需要invalidate()
在支持模型更改时调用,并且需要重新绘制视图。它还可以用于创建简单的动画,您可以在其中更改状态,然后调用invalidate()
,再次更改状态等。
回答by Remario
Please remember that drawing on the screen is frequent process, whenever you update a view, that change should be propogated and redrawn to notify such change right. invalidate()
is a trigger method,that signals force reDrawing of any view you wish to show changes for.
请记住,在屏幕上绘制是一个频繁的过程,每当您更新视图时,应该传播并重绘该更改以通知此类更改。invalidate()
是一种触发方法,它表示强制重新绘制您希望显示更改的任何视图。
回答by Maryam Azhdari
I had this problem when I wanted to draw a textPaint! My code was
当我想绘制 textPaint 时遇到了这个问题!我的代码是
canvas.drawPaint(textPaintNumber)
canvas.drawText("MyText", 30F, 63F, textPaintNumber)
I cleared the first lint and the problem was solved
我清除了第一个 lint,问题就解决了
canvas.drawText("MyText", 30F, 63F, textPaintNumber)