View.invalidate () doesn't seem to call View.onDraw ()

I have a library for drawing, and I have a custom view. When any updates are needed, the library calls the view invalidate() method. And then the onDraw() method is onDraw() , and everything works fine.

However, when I add the usesSdkVersion="14" attribute to my AndroidManifest.xml file , it stops working. I no longer like the onDraw() view method.

FURTHER INFORMATION: It appears that when I call invalidate() as a result of a button click in my application, the view is updated as expected. In addition, there is one animation in my library that works correctly. Therefore, apparently, it works correctly. But most of the time he does not redraw. Is there any state in which there may be a user view that will cause the OS to skip redrawing after calling invalidate() ?

+6
source share
3 answers

From Android 3.0, when using hardware acceleration, the display pattern is recorded and saved on the GPU.

So, when you get two views: A is above B, and you call B.invalidate , B.onDraw will be called and written to the GPU, but A.onDraw will not be called, because it is already written!

This differs from the non-hardware acceleration mode when all kinds of onDraw .

+5
source

official documents:

However, since hardware acceleration is not supported for all 2D drawing operations, enabling it may affect some of your applications that use custom views or drawing calls. Problems usually manifest as invisible elements, exceptions, or erroneously displayed pixels.

To fix this, Android gives you the ability to enable or disable hardware acceleration at the following levels:

Application

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

activity

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

Window

getWindow (). setFlags (WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

View

myView.setLayerType (View.LAYER_TYPE_SOFTWARE, null);

I check in my opinion.

+2
source

Sounds like a bug in Android. Instead of invalidate (), try using a method with the same name with four parameters:

 view.invalidate(0,0,view.getWidth(), view.getHeight()); 

By the way, it is better to apply the invalidity of only that area that is changing. Go through the left, top, right, bottom coordinates of the invalid area.

+1
source

Source: https://habr.com/ru/post/913171/


All Articles