2

I have a ListView, and I want to make a background that scrolls with the list.

I saw the code for Shelves, which works because all of the items in the GridView are the same height, which is a guarantee that I can't make. I figure that I can use a similar technique (that is, override dispatchDraw), but I need to know the distance from the top of the ListView for each item - how can I pre-calculate this? The ListView is mostly static and fairly small, so it's okay if I have to recalculate when adding a new item to the list.

So my question is this: Given a ListView and an List adapter, how can I calculate the distance of each item from the top of the list? That is, item 0 would be 0 pixels from the top, item 20 might be 4032 pixels from the top. Alternately, is there a better way to do what I want to do?

mindvirus
  • 5,016
  • 4
  • 29
  • 46
  • I haven't tried this, so I won't put it as an answer yet, but i believe you can use `getItemAtPosition` to retrieve the `View`. You can use the `View`'s method `getTop()` to get the pixel coordinate within the `ListView`. – DeeV Oct 28 '12 at 18:50

2 Answers2

1

It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent.

In addition, several convenience methods are offered to avoid unnecessary computations, namely getRight() and getBottom(). These methods return the coordinates of the right and bottom edges of the rectangle representing the view. For instance, calling getRight() is similar to the following computation: getLeft() + getWidth() (see Size for more information about the width.)

http://developer.android.com/reference/android/view/View.html

Retrieve the view using getItemAtPosition()

speakingcode
  • 1,518
  • 13
  • 12
1

In your adapter, keep a second list of distances that is the same size of your list. Initialize it in your constructor. Then, for each getView() call, you can add the height of the view to the value stored at the previous index of this new list. So for example, say you have List<Integer> distances. When you call getView(...) with position = 0, you set distances.add(0 + view.getHeight()); (once your view has been initialized). And for position 1, you will use distance.add(distances.get(position-1) + view.getHeight); and so on. Then just have a method for getting the distance for a given view index, which returns the value stored at that index in distances.

Phil
  • 35,852
  • 23
  • 123
  • 164
  • This sounds like the right approach, but trying to do this, I find that my adaptor's getView calls keep having height of zero. I'm using the standard approach of inflater.inflate if the convertView is null, else just using the convertView. Any idea what's up? – mindvirus Oct 28 '12 at 19:55
  • Hmm... It may not set its height until after its parent adds the view. This question has a solution: http://stackoverflow.com/questions/5375631/get-view-width-height-or-font-width-height-other-sizes-before-first-display – Phil Oct 28 '12 at 19:59
  • This worked, however the subtlety was that you have to call measure (as per your link) in the getView function in the adapter. Thank you for the advice. – mindvirus Oct 29 '12 at 00:54
  • Taking off accepted answer for this - I mean, I think that you have the right idea still, but the height changes for these elements - getHeight() still sometimes zero. And I haven't figured this out yet. – mindvirus Oct 30 '12 at 00:39
  • @mdkess, that could very easily be a different problem. According to the link I sent you, that solution has worked for many people, and as you stated, this is the right idea. Telling from experience, you will have better luck at this point if you post a new question, linking the question linked above, and showing your current code. – Phil Oct 30 '12 at 02:36
  • I figured this out. Your approach was correct - but with an addition that I needed to add an onLayoutChange listener to the row to calculate the height when it's finally measured. I answered my own question here: http://stackoverflow.com/q/13131948/31455 and posted the code to GitHub if you are interested. Thank you very much for the help, you can have your accepted answer back :) – mindvirus Nov 01 '12 at 16:20