2013-04-06 15 views
3

使用一個GridView與擴展BaseAdapter我加載包含的圖像和字幕RelativeLayouts的集合。當用戶在GridView中點擊其中一個項目時,它應該從網格中移除並由它後面的項目替換。的Android GridView控件加載在之後的索引的插槽0索引項時,數據集將更改

這工作正常比第一次(在項目的該適配器管理ArrayList的索引0)以外的項目。

在我測試的裝置,所述屏幕能夠顯示12個項目的時候,屏幕被完全滾動到網格的頂部(3列和4行)與所述最後一排略微切斷。第五排根本沒有顯示。在這種情況下,如果我單擊第一個項目(將其刪除),則所有項目都會正確填寫,但是,第五行的第一個項目(索引12)會返回第一個項目(索引0)的視圖在指數的項目12

有些屏幕,以幫助解釋這個問題:

step 1

點擊布萊恩·麥肯奈特將刪除他,BECK其餘的將填寫

step 2

BECK與其餘部分一起填充,現在向下滾動到下一行。

step 3

嗯哦。 BECK也在那裏。我讓它部分滾動,所以你可以看到兩個項目都有BECK圖片。

step 4

滾動備份所以項目12(第5行)是在視野,然後回落可以解決該問題。

這個過程對於網格中的任何其他項目是否正常工作,只是項目0.我做了一些記錄,發現了兩件事情:

  • 的getView(...)方法的對象是0叫了很多。當網格首次加載時,它被稱爲3次,而所有其他項目只被調用一次。
  • 當比項0以外的項目被刪除,getView(...)爲0的位置被稱爲19倍。 3,然後在所有其他對象的getView(...)方法被調用之後多出16次。
  • 當項0被刪除時,getView(...)爲0方法被調用兩次後您向下滾動到第5行(12項)。我在想這是發生問題的地方,因爲有時如果你看到正確的項目在被項目@位置0覆蓋之前開始加載。

所以我很確定那些額外的調用位置爲0的getView(...),當項目@ index 12出現時調用,是導致此問題的原因。我不知道就是爲什麼getView(...)的位置0會在那個時候被調用,爲什麼它會決定覆蓋項目@位置12

我會包括下面我的適配器代碼,我認爲這將足以找出問題所在。

public class PopularArtistsGridAdapter extends BaseAdapter { 

    private ArrayList<ArtistsListItem> mArtists = new ArrayList<ArtistsListItem>(); 
    private LayoutInflater mInflater; 
    private Context mContext; 

    private int mRemovedIndex = -1; 
    private int mRefresher = -1; 
    private int mLastVisible = -1; 

    public PopularArtistsGridAdapter(Context context) { 
     mContext = context; 
     mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 

    public void setItems(ArrayList<ArtistsListItem> artists) { 
     if(artists == null) 
      throw new NullPointerException(); 

     mArtists = artists; 
     notifyDataSetChanged(); 
    } 

    @Override 
    public int getCount() { 
     return mArtists.size(); 
    } 

    public void removeItem(int position, int lastVisible) { 
     mLastVisible = lastVisible; 

     mRemovedIndex = position; 
     mRefresher = mRemovedIndex; 

     mArtists.remove(position); 
     notifyDataSetChanged(); 
    } 

    public void addItem(int position) { 
     ArtistsListItem item = getItem(position); 

     mArtists.add(0, item); 
     notifyDataSetChanged(); 
    } 

    @Override 
    public ArtistsListItem getItem(int position) { 
     return mArtists.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    private void iterateRefresher() { 
     mRefresher++; 

     if(mRefresher > mLastVisible) { 
      mRemovedIndex = -1; 
      mRefresher = -1; 
      mLastVisible = -1; 
     } 
    } 

    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 

     final ArtistsListItem item = getItem(position); 

     if(convertView == null) 
      convertView = mInflater.inflate(R.layout.popular_artist_item, null); 

     final TextView tv = (TextView) convertView.findViewById(R.id.pai_stupid_bubble_button); 
     final ImageView iv = (ImageView) convertView.findViewById(R.id.pai_image); 

     final BitmapDrawable drawable = DrawableManager.fetchBitmapDrawable(mContext, item.getImageURL(), true, false); 

     iv.invalidate(); 
     tv.invalidate(); 

     if(mRefresher >= 0 && position >= mRefresher) { 
      Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.grid_item_fadein); 
      anim.setAnimationListener(new AnimationListener() { 

       @Override 
       public void onAnimationStart(Animation animation) { 
        iv.setImageDrawable(drawable); 
        tv.setText(item.getName()); 
       } 

       @Override 
       public void onAnimationRepeat(Animation animation) { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void onAnimationEnd(Animation animation) { 
        // TODO Auto-generated method stub 

       } 
      }); 

      anim.setStartOffset(300 + (50 * (position - mRemovedIndex))); 

      convertView.startAnimation(anim); 
      iterateRefresher(); 
     } 
     else { 
      iv.setImageDrawable(drawable); 
      tv.setText(item.getName()); 
     } 

     return convertView; 
    } 

} 

刷新是我讓屏幕上的所有可見物品在替換刪除的項目時淡入的東西。如果任何人在這裏看到任何可疑的事情,或者有任何其他想法,爲什麼會發生這種情況,我會很感激幫助。謝謝!

+0

出於好奇,如果你刪除你的動畫,這是否修復了什麼? – 2013-04-06 02:46:19

+0

嗯,刪除動畫確實解決了這個問題。但是我希望它能夠與該動畫一起工作。我會繼續修補它,謝謝你的提示 – JMRboosties 2013-04-08 16:32:10

+0

好吧,我想我知道那是什麼問題。我稍後會發布解決方案。 – 2013-04-09 00:10:34

回答

2

問題出在您用於淡入視圖的動畫。您以至少350毫秒的偏移量開始動畫。這意味着動畫不會運行,直到這段時間過去。問題出現在AnimationListeneronAnimationStart方法中。它引用一個局部變量並對其進行操作。這是事情出錯的地方。

這是一個有點棘手的解釋,所以嘗試遵循。 當時onAnimationStart已被稱爲第一次getView將被調用很多次。由於項目視圖被回收(這就是convertView),因此調用onAnimationStart時,它引用的視圖可能位於不同的位置。

原油說明:

// Views being held by the adapter after first pass. 
view0 --> onScreenItemtemAtPosition0 
view1 --> onScreenItemtemAtPosition1 
view2 --> onScreenItemtemAtPosition2 

// schedule animation, listener uses view0 reference 

// Scrolling occurs, item0 goes offscreen 
view0 --> onScreenItemtemAtPosition3 // view0 is now being used in a new position onscreen 
view1 --> onScreenItemtemAtPosition1 
view2 --> onScreenItemtemAtPosition2 

// onAnimationStart triggers and mutates view0 
// !!!! Boom !!! view0 is being used for the onscreen item at position 3 
// which isn't what you want because the drawable in your case is for item 0 

正如你可以看到這是一個棘手的情況。一種解決方法是讓你的AnimationListener知道你打算進行變異的視圖的位置,以便它可以與它即將變異的視圖相協調。

大致爲:

class MyAnimationListener extends AnimationListener { 
    private int positionToMutate; 

    public MyAnimationListener(int positionToMutate) { 
     this.positionToMutate = positionToMutate; 
    } 

    @Override 
    public void onAnimationStart(Animation animation) { 
     Integer viewPosition = (Integer)localConvertView.getTag(); // add this to getView as final View localConvertView 
     if (positionToMutate == viewPosition) { 
      iv.setImageDrawable(drawable); 
      tv.setText(item.getName()); 
     } 
    } 
    // rest of the methods 
} 

而在你getView方法更新convertView與位置信息標籤:

final View localConvertView = convertView; 
localConvertView.setTag(new Integer(position)); 

這將確保動畫聽衆知道它是否發生變異的觀點或不。

+0

有道理,但由於AnimationListener是一個接口,它不能有構造函數和東西。我必須找到一些方法來實現這一點,但你是對的,用這個位置作爲視圖的標記來決定它是否應該生成動畫。謝謝 – JMRboosties 2013-04-09 16:31:50

+0

創建了一個擴展了AnimationListener的匿名內部類,現在就開始工作。謝謝你的提示! – JMRboosties 2013-04-09 17:40:13

相關問題