ListViewis one of Android's most widely used widgets. It is rather easy to use, very flexible and incredibly powerful.ListViewcan also be difficult to understand at times.
One of the most common issues withListViewhappens when you try to use a custom background. By default, like many Android widgets,ListViewhas a transparent background which means yo can see through the default window's background, a very dark gray (#FF191919with the current dark theme.) Additionally,ListViewenables thefading edgesby default, as you can see at the top of the following screenshot; the first text item gradually fades to black. This technique is used throughout the system to indicate that the container can be scrolled.
The fade effect is implemented using a combination ofCanvas.saveLayerAlpha() and thePorter-Duff Destination Out blending mode. This technique is similar to the one explained inFilthy Rich Clientsand various presentations. Unfortunately, things start to get ugly when you try to use a custom background on theListViewor when you change the window's background. The following two screenshots show what happens in an application when you change the window's background. The left image shows what the list looks like by default and the right image shows what the list looks like during a scroll initiated with a touch gesture:
This rendering issue is caused by an optimization of the Android framework enabled by default on all instances ofListView(for some reason, I forgot to enable it by default onGridView.) I mentioned earlier that the fade effect is implemented using a Porter-Duff blending mode. This implementation works really well but is unfortunately very costly and can bring down drawing performance by quite a bit as it requires to capture a portion of the rendering in an offscreen bitmap and then requires extra blending (which implies readbacks from memory.)
SinceListViewis most of the time displayed on a solid background, there is no reason to go down that expensive route. That's why we introduced an optimization called the "cache color hint." The cache color hint is an RGB color set by default to the window's background color, that is #191919 in Android's dark theme. When this hint is set,ListView(actually, its base classView) knows it will draw on a solid background and therefore replaces th expensivesaveLayerAlpha()/Porter-Duffrendering with a simple gradient. This gradient goes from fully transparent to the cache color hint value and this is exactly what you see on the image above, with the dark gradient at the bottom of the list. However, this still does not explain why the entire list turns black during a scroll.
As I said before,ListViewhas a transparent/translucent background by default, and so all default Android widgets. This implies that whenListViewredraws its children, it has to blend the children with the window's background. Once again, this requires costly readbacks from memory that are particularly painful during a scroll or a fling when drawing happens dozen of times per second. To improve drawing performance during scrolling operations, the Android framework reuses the cache color hint. When this hint is set, the framework copies each child of the list in aBitmapfilled with the hint value (this assumes that another optimization, calledscrolling cache, is not turned off.)ListViewthen blits these bitmaps directly on screen and because these bitmaps are known to be opaque, no blending is required. And since the default cache color hint is#191919, you get a dark background behind each item during a scroll.
To fix this issue, all you have to do is either disable the cache color hint optimization, if you use a non-solid color background, or set the hint to the appropriate solid color value. This can be domefrom codeor preferably from XML, by using theandroid:cacheColorHintattribute. To disable the optimization, simply use the transparent color#00000000. The following screenshot shows a list withandroid:cacheColorHint="#00000000"set in the XML layout file:
As you can see, the fade works perfectly against the custom wooden background. I find the cache color hint feature interesting because it shows how optimizations can make developers' life more difficult in some situations. In this particular case, however, the benefit of the default behavior outweighs the added complexity for the developer.
本文详细解析了Android ListView中自定义背景时遇到的问题及解决方案,包括背景消失、阴影显示和间距设置等常见问题,并提供了解决方法。通过调整ListView的属性,如设置背景颜色、透明度和分割线样式,可以有效解决这些问题,实现美观且高效的UI设计。
257

被折叠的 条评论
为什么被折叠?



