tom91136
tom91136

Reputation: 8962

android get scroll position of listview populated with varied height

In android, how do i get the scroll position of the listview?

I know that I can retrieve the scroll position of a uniform populated listview with the following code:

int scrollY = -this.getChildAt(0).getTop() + this.getFirstVisiblePosition()* this.getChildAt(0).getHeight();

the code assumes all heights of children(item) in the listview to be equal(this.getChildAt(0).getHeight())

Now, if i populate my listview with not equally sized items, how do i get the proper scroll position?

My listview looks something like this: enter image description here

This is why I need the scroll position:

private Canvas drawIndicator(Canvas canvas) {

    int scrollY = getCurrentScrollPosition();



    paint.setColor(Color.GRAY);
    paint.setAlpha(100);
    canvas.drawRect(getLeft(), indicatorPosition[0] - scrollY, getRight(), indicatorPosition[1]
            - scrollY, paint);

     //Log.d(VIEW_LOG_TAG, "drawIndicator:" + (indicatorPosition[1] -
     //scrollY));

    paint.setColor(Color.parseColor("#47B3EA"));
    canvas.drawRect(getLeft(), indicatorPosition[1] - scrollY - (indicatorHeight / 2),
            getRight(), indicatorPosition[1] - scrollY + indicatorHeight, paint);

    return canvas;
}

i need to draw a indicator that follows the scroll of the listview

i would invoke it like

@Override
protected void onDraw(Canvas canvas) {
    canvas.save();
    canvas = drawIndicator(canvas);
    super.onDraw(canvas);
    canvas.restore();
}

Upvotes: 1

Views: 6105

Answers (3)

IliaEremin
IliaEremin

Reputation: 3397

I faced with same problem, but I used listView with random lenght text inside each item hence I don't know item height in advance. My implementation:

private static int[] heights;

public static int getScrollY(ListView lv) {
  if (heights == null || lv.getCount() != heights.length) {
        heights = new int[lv.getCount()];
    }
    View c = lv.getChildAt(0);
    if (c == null) {
        return 0;
    }

    int firstVisiblePosition = lv.getFirstVisiblePosition();
    if (firstVisiblePosition < lv.getCount() && heights[firstVisiblePosition + 1] == 0) {
        heights[firstVisiblePosition + 1] += heights[firstVisiblePosition] + c.getHeight();
    }
    return -c.getTop() + heights[firstVisiblePosition];
}

I think there are problems if any element of listView changed (add/remove/change height). Also height computes when you scroll listView and there is problem if you scroll listView programmatically. This is very sad, that listView implementaion prevents easy access to scroll Y position :(

Upvotes: 0

Malachiasz
Malachiasz

Reputation: 7226

or:

private Dictionary<Integer, Integer> listViewItemHeights = new Hashtable<Integer, Integer>();

private int getScroll() {
    View c = listView.getChildAt(0); //this is the first visible row
    int scrollY = -c.getTop();
    listViewItemHeights.put(listView.getFirstVisiblePosition(), c.getHeight());
    for (int i = 0; i < listView.getFirstVisiblePosition(); ++i) {
        if (listViewItemHeights.get(i) != null) // (this is a sanity check)
            scrollY += listViewItemHeights.get(i); //add all heights of the views that are gone
    }
    return scrollY;
}

This should be invoked in:

public void onScroll(AbsHListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)

will work only when scrolling from position 0 was done manually, not programatically.

Upvotes: 1

Anis BEN NSIR
Anis BEN NSIR

Reputation: 2555

Assuming that you know the size of All your items type:

int currentY = 0;
        for (int i = 0; i < listView.getFirstVisiblePosition(); i++) {

            int type = listView.getAdapter().getItemViewType(i);
            currentY += getHightForViewType(type);
        }

        int scrollY = -listView.getChildAt(0).getTop() + currentY;

and using your adapter:

 private int getHightForViewType(int itemViewType) {

        int hightItem;
        switch (itemViewType) {
            case 0:
                hightItem = 100;
                break;

            default:
                hightItem = 60;
                break;
        }
        return hightItem;

    }

Upvotes: 3

Related Questions