2014-07-22 76 views
2

我正在創建一個ArrayAdapter爲我的GridView考慮頁眉和頁腳視圖。Android - 非常奇怪的行爲與GridView

activity_main.xml中:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <GridView 
     android:id="@+id/activity_main_gridview" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:numColumns="4" /> 

</RelativeLayout> 

的問題是,當我滾動到頂部或網格標題的底部/底部的觀點得到了網格項目,並在任何項目上點擊時,它可以追溯到原始位置(如果需要,我會放置屏幕截圖)

這是我的GridView適配器(params按順序:上下文,網格項目的arraylist(沒有頁眉/頁腳),所有第一行的頁眉視圖,行,gridview列數):

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    mGridView = (GridView) findViewById(R.id.activity_main_gridview); 

    List<String> list = new ArrayList<String>(); 
    for (int i = 0; i < 500; i++) { 
     list.add("item " + i); 
    } 
    View headerView = new View(this); 
    headerView.setMinimumHeight(70); 
    headerView.setBackgroundColor(Color.argb(255, 63, 81, 181)); 

    GridHeaderFooterAdapter adapter = 
      new GridHeaderFooterAdapter(this, list, headerView, headerView, 4); 
    mGridView.setAdapter(adapter); 
} 

private final class GridHeaderFooterAdapter extends ArrayAdapter<String> { 

    private int mNumColumns; 
    private int mListSize; 

    private List<String> mList; 
    private View mHeaderView; 
    private View mFooterView; 

    private LayoutInflater mInflater; 

    public GridHeaderFooterAdapter(ActivityMain context, List<String> list, View headerView, View footerView, int numColumns) { 
     super(context, 0); 
     this.mNumColumns = numColumns; 
     this.mListSize = list.size(); 
     this.mList = list; 
     this.mHeaderView = headerView; 
     this.mFooterView = footerView; 

     mInflater = context.getLayoutInflater(); 
    } 

    @Override 
    public int getCount() { 
     int count = 0; 
     //headers 
     count += mNumColumns; 
     //list items 
     count += mListSize; 
     //footers 
     count += mNumColumns + (mNumColumns - mList.size() % mNumColumns); 
     Log.w("ActivityMain", "getCount() = " + count); 
     return count; 
    } 

    @Override 
    public String getItem(int position) { 
     //discard header items 
     return mList.get(position - mNumColumns); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     //headers 
     if (position < mNumColumns){ 
      Log.w("ActivityMain", "headers: position = " + position); 
      return mHeaderView; 
     } 
     //listitems 
     if (position >= mNumColumns && position < mNumColumns + mListSize) { 
      Log.w("ActivityMain", "listitems: position = " + position); 
      LinearLayout ll = (LinearLayout) mInflater.inflate(R.layout.listitem_main, null); 
      TextView tv = (TextView) ll.findViewById(R.id.textView); 
      tv.setText(getItem(position)); 
      return ll; 
     } 
     //footers 
     if (position >= mNumColumns + mListSize){ 
      Log.w("ActivityMain", "footers: position = " + position); 
/*TODO: some footers might be in the same row as listitem, which is wrong because Gridview uses last item of the row to determine row height... */ 
      return mFooterView; 
     } 

     return null; 
    } 
} 

前SCROLLING: enter image description here 後滾動: enter image description here

正如你所看到的,目標是增加一個頭,以避免第一項是狀態欄

+0

如果有問題的快照,最好.... –

+0

@ i.n.e.f好的,完成 – BamsBamx

+0

你正在用你的適配器做一些非常錯誤的事情。爲了幫助我解釋一下,首先你有什麼打算使用頁腳和頁眉?此外,這些屏幕截圖中的頁眉/頁腳視圖是什麼? –

回答

2

手動位置玩弄背後數字是一件危險的事情,儘管如果做得正確的話也是可能的這裏的問題在於,您試圖繞過getView()方法的運行方式。 getView()將維護它自己對返回視圖的引用並回收或相應地銷燬它。它已經得到了極大的優化,能夠提供出色的性能,並且爲了達到最終目標,您希望與之合作......不會違背。

最終,您希望GridView中第一行(頁眉)和最後一行(頁腳)行的間距避免與半透明狀態/導航欄重疊。我會給你一個更高級的需要發生的概況。

getCount()需要返回:

mListSize + (mNumColumns * 2) 

爲什麼?因爲每個列都需要一個標題視圖,每個列也需要一個頁腳視圖。

getItem()需要爲所有可能的位置返回一些東西。這意味着任何由getCount()返回的值都需要能夠返回某些內容......即使它是空字符串。因此,像:

// if a header position or a footer position 
if (position < mNumColumns || position > mListSize + mNumColumns) { 
    return "" 
} else { 
    return mList.get(position - mNumColumns); 
} 

注意,這可能受了一點考慮計數被關閉是不是從零開始的,但位置是......但它顯示了你所需要的基本精神。

getView()需要渲染一個正常的視圖。區別在於,如果位置編號表示頁眉/頁腳位置,則返回空白視圖。例如:

ViewHolder vh = null; 
if (convertView == null) { 
    //inflate your view 
    convertView.setTag(vh); 
} else { 
    vh = (ViewHolder) convertView; 
} 

//If position is indicative of a header/footer. Alternatively you could see if getItem() returns an empty string...assuming your data can never contain an empty string. 
if (position < mNumColumns || position > mListSize + mNumColumns) { 
    //Don't fill the view with any data. Make any visible elements INVISIBLE 
} else { 
    //populate convertView with data 
} 

擺脫傳遞給適配器使用的視圖的整個概念。這將確定一切。如果表現非常值得關注,那麼更好的替代方案(以及適當的方案...更多,然後我發佈的內容)是使用getItemViewType()getViewTypeCount()。但是,這需要您創建一個可以表示實際數據的類對象(例如字符串)和一個表示它是頁眉,頁腳和數據的標誌。

+0

試過這個,但唯一讓它工作的方法是在getView方法內擴展頭部,如果convertView == null ...爲什麼不能將它作爲參數傳遞? – BamsBamx

+0

因爲在內部,對於適配器,Android將確定視圖何時被銷燬......或者被循環使用以用於不同的位置編號。當您滾動並且視圖熄滅屏幕時,會發生這種情況。 –

+0

好的,謝謝你的迴應。您讓我瞭解了有關適配器的更多信息 – BamsBamx