Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

finding pixel location of Listview item seems to return wrong value

I have a ListView with a number of items (animals), of diverse heights. Using OnScrollListener I am trying to track which item intersects a specific location on the screen. Say the location in question is creatureMarkerBottom = 140. The code below seems to be returning faulty data when I run the code: I keep getting false positives and false negatives. Here is the code. The code is supposed to make the marker go solid or transparent depending if a chicken is intersecting it. However, the fading does not really obey whether the chicken is touching the slab/bar or not. My guess is the way I am getting the ListView pixel location is wrong.

OnScrollListener listviewScrollListener = new OnScrollListener() {
        int creatureLocationPixel[] = { 0, 0 };
        int creatureMarkerBottom;
        int creatureTop, creatureBottom;
        int[] creatureLocationPixel = { 0, 0 };
        View creatureView;
        boolean creatureMarkerIsFaded = false;

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

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            try {
                scrollBackgroundToFindCreature(visibleItemCount, firstVisibleItem);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void scrollBackgroundToFindCreature(int visibleItemCount, int index) {
            creatureMarkerSlabView.getLocationOnScreen(creatureLocationPixel);
            creatureMarkerBottom = creatureLocationPixel[1] + creatureMarkerSlabView.getHeight();
            Animal creature;
            boolean found = false;
            do {
                creature = mAdapter.getItem(index);
                creatureView = getViewForPosition(index);
                creatureView.getLocationOnScreen(creatureLocationPixel);
                creatureTop = creatureLocationPixel[1];
                creatureBottom = creatureTop + creatureView.getHeight();
                if (creatureTop < creatureMarkerBottom  && creatureMarkerBottom  < creatureBottom) {
                    found = true;
                } else {
                    index++;
                }
            } while (!found && index < visibleItemCount);

            if (creatureType.CHICKEN != creature.getType()) {
                if (!creatureMarkerIsFaded) {
                    creatureMarkerIsFaded = true;
                    for (int x = 0; x < creatureMarkerSlabView.getChildCount(); x++)
                        creatureMarkerSlabView.getChildAt(x).setAlpha(TRANSPARENCY_ALPHA);
                    creatureMarkerSlabView.setAlpha(TRANSPARENCY_ALPHA);
                }

            } else {
                if (creatureMarkerIsFaded) {
                    creatureMarkerIsFaded = false;
                    for (int x = 0; x < creatureMarkerSlabView.getChildCount(); x++)
                        creatureMarkerSlabView.getChildAt(x).setAlpha(255);
                    creatureMarkerSlabView.setAlpha(255);
                }
            }
        }

    };

public View getViewForPosition(int position) {
        int firstPosition = animalListview.getFirstVisiblePosition() - animalListview.getHeaderViewsCount();
        int wantedChild = position - firstPosition;
        // Say, first visible position is 8, you want position 10, wantedChild will now be 2
        // So that means your view is child #2 in the ViewGroup:
        if (wantedChild < 0 || wantedChild >= animalListview.getChildCount()) {
            return null;
        }
        return animalListview.getChildAt(wantedChild);
    }
like image 686
Cote Mounyo Avatar asked Nov 11 '22 21:11

Cote Mounyo


1 Answers

The solution to the problem is explained understanding ListView childAt method and what limits the index for listview.getChildAt(index). The problem was that I misunderstood the relationship between listView.getChildCount() and adapter.getCount().

In brief:

per my experiment, here is how it works. The ListView is a slice of the adapter. So if an adapter has 500 items and the ListView has ten (10). The ten in the ListView represent a dynamic view. So if the firstVisibleItem were item 217 in the adapter, then the ListView range of indices would be (217,…,226) whereas the listView.getChildCount() would still return 10.

Hence the answer is:

getChildAt(x) | x : [0+firstVisibleItem, listview.getChildCount()+firstVisibleItem)
like image 151
Cote Mounyo Avatar answered Nov 15 '22 00:11

Cote Mounyo