After several more hours of debugging, I finally found the solution.
At first, I added this to my init()
method (which is called from all constructors):
setWillNotDraw(false);
Android must know that this View
must be rendered and drawn, which should be the default value, anyway. But if you extend ViewGroup
, for example, it is not the default setting, so you have to clear that flag.
As others have noted, one should only call that method once, in order to set correct flag for the View
. If you want to prevent drawing in the beginning, use a custom flag and only execute the statements in your onDraw(...)
if appropriate. Thus I remove the second call to setWillNotDraw(...)
from show(...)
.
In addition to that, I added a call to ...
invalidate();
... at the end of show(...)
, which is when I provide input to my custom View
and it must be re-drawn.
However, the problem of the View
not being drawn ("invisible" View
) did only occur on certain devices. It was, for example, a Samsung Galaxy S4 (Android 4.4). When I tested it on the emulator with Android 4.4, the problem did not occur. The reason for that was actually simple:
View.isHardwareAccelerated()
revealed that the Galaxy S4 (Android 4.4) was using hardware acceleration on the custom View
, while the Galaxy S3 Mini (Android 4.1.2), the Galaxy S2 and the emulator were not.
Here's what the docs say about hardware acceleration:
Hardware acceleration is not supported for all of the 2D drawing operations, turning it on might affect some of your custom views or drawing calls. Problems usually manifest themselves as invisible elements, exceptions, or wrongly rendered pixels.
And apart from that, the GPU can cache your custom View
as a static image.
The simple solution (in init()
) was therefore to disable hardware acceleration for the custom View
class:
if (Build.VERSION.SDK_INT >= 11) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}