国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android ListView position詳解及實例代碼

2019-12-12 05:03:55
字體:
來源:轉載
供稿:網友

 我們在使用ListView的時候,一般都會為ListView添加一個響應事件android.widget.AdapterView.OnItemClickListener。對OnItemClickListener的position和id參數,我相信有些人在這上面走了些彎路。

    在使用listview的時候,我們經常會在listview的監聽事件中,例如OnItemClickListener(onItemClick)中,或listview的adapter中(getView、getItem、getItemId等)看到position這個變量。在我們沒有為listview添加headerView時,position和數據源集合的索引是一致的,當添加了headerView之后,某些地方的position值就會發生變化,如果不理解清楚,經常會犯一些糊涂。

  在listview添加了headerView后, 會將所有view交給HeaderViewListAdapter來處理,所以我們要在setAdapter之前添加headerView或footerView,否則將顯示不出來。

@Override  public void setAdapter(ListAdapter adapter) {    if (mAdapter != null && mDataSetObserver != null) {      mAdapter.unregisterDataSetObserver(mDataSetObserver);    }    resetList();    mRecycler.clear();    if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {      mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);    } else {      mAdapter = adapter;    }

  先看看HeaderListAdapter中幾個帶position參數的方法實現,我們可以看到在傳出的position為adjPosition,而adjPosition均為我們自動去掉了headerView的數量,所以adapter中幾個帶position變量的方法,得到的position值均和數據源集合索引一致,仔細翻看HeaderListAdapter中所有需要傳出position的方法,position的值都是自動減去了headerView數量。

public View getView(int position, View convertView, ViewGroup parent) {    // Header (negative positions will throw an ArrayIndexOutOfBoundsException)    int numHeaders = getHeadersCount();    if (position < numHeaders) {      return mHeaderViewInfos.get(position).view;    }    // Adapter    final int adjPosition = position - numHeaders;    int adapterCount = 0;    if (mAdapter != null) {      adapterCount = mAdapter.getCount();      if (adjPosition < adapterCount) {        return mAdapter.getView(adjPosition, convertView, parent);      }    }    // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)    return mFooterViewInfos.get(adjPosition - adapterCount).view;  }
public Object getItem(int position) {    // Header (negative positions will throw an ArrayIndexOutOfBoundsException)    int numHeaders = getHeadersCount();    if (position < numHeaders) {      return mHeaderViewInfos.get(position).data;    }    // Adapter    final int adjPosition = position - numHeaders;    int adapterCount = 0;    if (mAdapter != null) {      adapterCount = mAdapter.getCount();      if (adjPosition < adapterCount) {        return mAdapter.getItem(adjPosition);      }    }    // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)    return mFooterViewInfos.get(adjPosition - adapterCount).data;  }  public long getItemId(int position) {    int numHeaders = getHeadersCount();    if (mAdapter != null && position >= numHeaders) {      int adjPosition = position - numHeaders;      int adapterCount = mAdapter.getCount();      if (adjPosition < adapterCount) {        return mAdapter.getItemId(adjPosition);      }    }    return -1;  }
 

  我們再來分析分析OnItemClickListener的相關源碼,OnItemClickListener在android.widget.AdapterView的public boolean performItemClick(View view, int position, long id)函數中被調用。而performItemClick是在android.widget.AbsListView.PerformClick.run() 中被調用:

private class PerformClick extends WindowRunnnable implements Runnable {    int mClickMotionPosition;    public void run() {      // The data has changed since we posted this action in the event queue,      // bail out before bad things happen      if (mDataChanged) return;      final ListAdapter adapter = mAdapter;      final int motionPosition = mClickMotionPosition;      if (adapter != null && mItemCount > 0 &&          motionPosition != INVALID_POSITION &&          motionPosition < adapter.getCount() && sameWindow()) {        final View view = getChildAt(motionPosition - mFirstPosition);        // If there is no view, something bad happened (the view scrolled off the        // screen, etc.) and we should cancel the click        if (view != null) {          performItemClick(view, motionPosition, adapter.getItemId(motionPosition));        }      }    }  }

  從源碼中,我們可以看到position對應motionPosition,而motionPosition通過調試,我們發現就是listview中被點擊的位置,所以我們經常在onItemClick中需要獲取數據源集合中某個item時,會習慣性寫這樣代碼:sourceList.get(position-listView.getHeaderViewsCount())。

  我們發現onItemClick還有一個參數,其實就是上面源碼中傳遞給performItemClick的第三個參數,而第三個參數是通過調用adapter的getItemId將motionPosition減去了headerView的數量,所以這個參數的結果是與數據源集合的索引一致的。也就是說,我們完全可以使用onItemClick的id這個參數,這個參數是和數據源集合的索引一致的。

  另外我們需要注意,如果數據源沒有內容,則id的值會為-1,所以我們在使用id時,需要對id做適當判斷。

  總結:在OnItemClickListener的onItemClick方法中,當我們需要獲取點擊listview對應的數據源索引時,使用id參數即可。另外除了onItemClick的position參數是點擊listview對應view的位置外,adapter中所有position均為數據源索引位置。其實換個角度更容易記,在listview中,position理應是listview中view對應的位置,而在adapter中,理應是數據源的索引位置。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 正阳县| 千阳县| 杭州市| 绥中县| 巫山县| 班玛县| 四子王旗| 霞浦县| 都江堰市| 乾安县| 肃宁县| 齐河县| 合阳县| 周至县| 噶尔县| 襄樊市| 德惠市| 普兰店市| 仁怀市| 右玉县| 北安市| 剑川县| 泸西县| 古田县| 武安市| 漳平市| 邳州市| 湖北省| 荣成市| 三明市| 团风县| 温宿县| 尤溪县| 碌曲县| 沂南县| 武安市| 苍梧县| 广州市| 婺源县| 友谊县| 太湖县|