Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GridView get view by position, first child view different

Android GridView is quite interesting, it reuses the child views. The ones scrolled up comes back from bottom. So there is no method from GridView to get the child view by its position. But I really need to get view by its position and do some work on it. So to do that, I created an SparseArray and put views by their position in it from getView of BaseAdapter.

SparseArray<View> ViewArray = new SparseArray<View>();

public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;    
    if (view == null)
       view = li.inflate(layoutID, null);
    ViewArray.put(position, view);
}

Now, I can get all visible views by their position. Everything works perfect as it should but in some devices, the first child view(position 0) is not same as the one in array. I logged the getView and found that for position 0, getView got called many times and each time array was set with different view. I have no idea why GridView is calling getView for position 0 many times and that happens only on few devices. Any solution ?

like image 886
xmen Avatar asked Dec 12 '13 16:12

xmen


2 Answers

After reading source of getPositionForView, I have wrote this method in own GridView, works perfect by API 18

public View GetViewByPosition(int position) {
    int firstPosition = this.getFirstVisiblePosition();
    int lastPosition = this.getLastVisiblePosition();

    if ((position < firstPosition) || (position > lastPosition))
        return null;

    return this.getChildAt(position - firstPosition);
}
like image 139
xmen Avatar answered Nov 10 '22 00:11

xmen


You can't reach the views directly because of the recycling. The view at position 0 may be re-used for the position 10, so you can't be sure of the data present in a specific view.

The way to go is to use the underlying data. If you need to modify data at position 10, then do it in the List or array under your adapter and call notifyDataSetChanged() on the adapter.

if you need to have different views for different data subtypes, you can override the two following method in your adapter: getItemViewType() and getViewTypeCount()

Then, in getView() you can 1) decide which layout to inflate 2) know the type of view recycled using getItemViewType()

You can find an example here: https://stackoverflow.com/a/5301093/990616

like image 27
znat Avatar answered Nov 10 '22 00:11

znat