0

i am trying to send data in a listview when a button is clicked.

However my listview show 2 row on at once one full row and one partial row . Is there a way i can determine which row is showing partial and which is showing fully.

I am able to get the index that is showing only. is there another approach ?

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {


    if (scrollState == SCROLL_STATE_IDLE){
        Rect r = new Rect ();
        View child = recordListview.getChildAt(view.getFirstVisiblePosition());    // first visible child
        if (child == null)
            return; 
        double height = child.getHeight () * 1.0;

        recordListview.getChildVisibleRect (child, r, null);
        Log.d("Visible1 ", view.getFirstVisiblePosition() + "  "  + height + "  " + r.height()  );

        if (Math.abs (r.height ()) < height / 2.0) {
                    // show next child
            recordListview.smoothScrollToPosition(view.getFirstVisiblePosition()+1);
            Log.d("Visible1 Location", view.getFirstVisiblePosition() +1+ "");
        }

        else {
            recordListview.smoothScrollToPosition(view.getFirstVisiblePosition());
            Log.d("Visible1 Location", view.getFirstVisiblePosition()+ "");
        }

    }
}
});
sean
  • 717
  • 2
  • 9
  • 23
  • Have You tried getChildVisibleRect() ? – sandrstar Jul 09 '13 at 08:04
  • @sandrstar i have updated my code with the example shown at http://stackoverflow.com/questions/15338509/android-listview-stop-scrolling-at-whole-row-position . This causes my listview to be no longer scrollable. – sean Jul 09 '13 at 08:07
  • Is onScroll() called? I think You need to use onScrollStateChanged(), detect SCROLL_STATE_IDLE and then do your logic. – sandrstar Jul 09 '13 at 08:12
  • @sandrstar Yes onscrolled is fired . however , r.height is always zero. – sean Jul 09 '13 at 08:31

1 Answers1

2

Seems You've understood documentation of getChildVisibleRect() incorrectly.

It mentions:

r The input rectangle, defined in the child coordinate system. Will be overwritten to contain the resulting visible rectangle, expressed in global (root) coordinates

So, if You're providing empty rectangle in the child coordinate then it can be translated only into empty visible rectagle, right?

For me this code seems to work:

recordListview.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(final AbsListView view, final int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {
            final View child = recordListview.getChildAt(view.getFirstVisiblePosition());

            if (child == null) {
                return;
            }

            final Rect r = new Rect (0, 0, child.getWidth(), child.getHeight());
            final double height = child.getHeight () * 1.0;

            recordListview.getChildVisibleRect(child, r, null);
            Log.d("Visible1 ", view.getFirstVisiblePosition() + "  "  + height + "  " + r.height());

            if (Math.abs (r.height ()) < height / 2.0) {
                // show next child
                recordListview.smoothScrollToPosition(view.getFirstVisiblePosition()+1);
                Log.d("Visible1 Location", view.getFirstVisiblePosition() +1+ "");
            } else {
                recordListview.smoothScrollToPosition(view.getFirstVisiblePosition());
                Log.d("Visible1 Location", view.getFirstVisiblePosition()+ "");
            }
        }
    }

    @Override
    public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount, final int totalItemCount) {
        // nothing to do here
    }
});

Regarding initial question about determining which view is visible fully and which is not, I would suggest to use the following code:

@Override
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
    if (scrollState == SCROLL_STATE_IDLE) {

        final int firstVisiblePosition = view.getFirstVisiblePosition();
        View child = recordListview.getChildAt(firstVisiblePosition);

        if (child == null) {
            return;
        }

        if (mListItemsOnScreen == 0) {
            // number of total visible items, including items which are not fully visible
            mListItemsOnScreen = (int) Math.ceil(((double)recordListview.getHeight()) / (child.getHeight() + recordListview.getDividerHeight()));
        }

        final Rect r = new Rect(0, 0, child.getWidth(), child.getHeight());
        final double height = child.getHeight();

        recordListview.getChildVisibleRect(child, r, null);
        Log.d("Visible1", " items till " + firstVisiblePosition + " are not visible");
        // Check top item
        Log.d("Visible1", firstVisiblePosition + " is visible " + (r.height() >= height ? " fully" : "partially"));
        // check bottom item
        child = recordListview.getChildAt(firstVisiblePosition + mListItemsOnScreen);

        if (child != null) {
            r.set(0, 0, child.getWidth(), child.getHeight());
            recordListview.getChildVisibleRect(child, r, null);

            Log.d("Visible1", " items from " + firstVisiblePosition + " till " + (firstVisiblePosition + mListItemsOnScreen) + " are fully visible");
            Log.d("Visible1", (firstVisiblePosition + mListItemsOnScreen) + " is visible " + (r.height() >= height ? " fully" : "partially"));
        } else {
            Log.d("Visible1", " items from " + firstVisiblePosition + " till " + (firstVisiblePosition + mListItemsOnScreen) + " are fully visible");
            Log.d("Visible1", (firstVisiblePosition + mListItemsOnScreen) + " is invisible ");
        }
    }
}
sandrstar
  • 12,503
  • 8
  • 58
  • 65
  • Hi sandstar , i tried the solution above . The scroll from item 0 to 1 works fine nut when i scroll from item 1 to 2 . The list start to move from 1 - 2 - 1 - 2 ... indefinetly. `07-10 02:49:46.930: D/Visible1(2772): 1 190.0 190 2 07-10 02:49:46.930: D/Visible1 Location(2772): 1 07-10 02:49:46.980: D/Visible1(2772): 1 190.0 52 2 07-10 02:49:46.980: D/Visible1 Location(2772): 2 07-10 02:49:47.040: D/Visible1(2772): 1 190.0 190 2 07-10 02:49:47.070: D/Visible1 Location(2772): 1 07-10 02:49:47.113: D/Visible1(2772): 1 190.0 52 2 ` – sean Jul 10 '13 at 02:51
  • What are You trying to achieve? Actually, You question is 'way determine which row is showing partial' - was You able to achieve it? – sandrstar Jul 10 '13 at 02:56
  • Yes thats right . I am trying to determine which row is shown and then scroll to the row which have the biggest area shown. I am just curious why will it work for the scroll of item 0 to 1 and not for subsequent scroll. – sean Jul 10 '13 at 03:48
  • I've provided the code to determine which view is visible and which is not (or visible partially). I think 2 items is a corner case and, probably, usage of Math.abs (r.height ()) < height / 2 is not valid for it. However, I think it shouldn't be a problem for You to determine exact logic of checks for 2 two items (logging of exact values of visible heights would help). I've tested with 10 items list, because it's a common case for your question. – sandrstar Jul 10 '13 at 04:22
  • Hi sandrstar , thanks for the code. I am trying them now. Can you share what is assigned to the variable mListItemsOnScreen ? – sean Jul 10 '13 at 04:32
  • It's just number of visible item of the list, declared as private int mListItemsOnScreen = 0; – sandrstar Jul 10 '13 at 04:49