Recently I was working on a widget that extends Android’s Gallery class, which is typically used to show a horizontal list of images that the user can scroll through. I wanted to customize the Gallery to actually give a stacking effect to the images, by tucking parts of each image underneath the image next to it, while showing the image in the center on top of everything. (see any “cover flow” images from google images)
Luckily Android makes this very easy to accomplish with the method getChildDrawingOrder(int, int). The Gallery class actually already uses this method to make sure the center image is drawn last, but it draws the rest of the images from left to right, while I actually want to draw the outside images first, then the second and second to last images, etc.
To begin I overrode the getChildDrawingOrder() in my class that extends Gallery. Also it may be necessary to call setChildrenDrawingOrderEnabled(true) on your view to get the hook into getChildDrawingOrder(), but since the Gallery already implemented it I did not need to. The arguments passed into getChildDrawingOrder(), childCount and i are the amount of children of this view and the current drawing index respectively. What you are supposed to return is the index of the child that you want to be drawn on this drawing turn.
If I have 5 images (2 on the left, 1 in the center, and 2 on the right) then the child index order I want to give back is 0, 1, 4, 3, 2 to get the effect that I want. For this widget I will always have an odd number of items in my Gallery on the screen (3, 5, or 7) so I could make some assumptions in my code. As you will see in my code sample below, I solved this very simply with three if statements.
1. If our drawing index is the last index, then return the center child to be drawn, ensuring it will be drawn last.
2. If our drawing index is greater than the center child’s index, meaning this item is on the right side of the center item then return the last possible child index that has not already been drawn yet.
3. Else we will just return the same child index that corresponds to the drawing index, because the items on the left side can be drawn in order.
1 @Override
2 protected int getChildDrawingOrder(int childCount, int i) {
3 //Reset the last position variable everytime we are starting a new drawing loop
4 if(i == 0)
5 lastPosition = 0;
6
7 int centerPosition = getSelectedItemPosition() - getFirstVisiblePosition();
8
9 if (i == childCount - 1) {
10 return centerPosition;
11 } else if (i >= centerPosition) {
12 lastPosition++;
13 return childCount - lastPosition;
14 } else {
15 return i;
16 }
17 }