2013-06-21 59 views
1

我在下面的代碼中遇到了一些奇怪的行爲。我在我的ListView的每一行都有一個按鈕,如果它被點擊,我想灰化該行並隱藏按鈕。爲了使更改永久,我已經在自定義ViewHolder中設置了一個屬性,所以更改是持久的。操作ViewHolder中包含的ListView項目 - 意外的行爲

然而,點擊按鈕(比如說第1項)也會應用對項目6的更改。在其他項目上,它不會影響其他行或影響多個行。我懷疑這跟我聲明一些final變量有關,但我無法確定。我試着實現不同的解決方案(減少最終變量的數量,使用不同的變量等),但似乎沒有任何工作。

我需要一些幫助。謝謝!

public class FruitLoopsAdapter extends BaseAdapter 
{ 
    private ArrayList<FruitLoopsNode> provider; 
    private Activity parent; 
    /** 
    * Constructor. 
    * @param parent 
    *  The parent activity of the fragment using the FruitLoop. Needed as the adapter will 
    *  be used in a fragment which only its parents has access to the data providers. 
    */ 
    public FruitLoopsAdapter(Activity parent) 
    { 
     this.parent = parent; 
     provider = ((Box)parent).getFruitLoops(); 
    } 

    /** 
    * Method returning the size of the underlying data provider. 
    * @return 
    *  The size of the data provider. 
    * @see android.widget.Adapter#getCount() 
    */ 
    @Override 
    public int getCount() 
    { 
      return provider.size(); 
    } 

    /**{@inheritDoc}*/ 
    @Override 
    public Object getItem(int position) 
    { 
      return provider.get(position); 
    } 

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

    /** 
    * Method building the composite custom view and returning it as one view. 
    * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup) 
    */ 
    @Override 
    public View getView(int position, View convertView, ViewGroup parentViewGroup) 
    {  
      FruitLoopsViewHolder viewHolder; 
      final FruitLoopsNode FruitLoopsNode = provider.get(position); 

      if (convertView == null) 
      { 
        convertView = LayoutInflater.from(parentViewGroup.getContext()).inflate(R.layout.list_FruitLoops, null); 

        viewHolder = new FruitLoopsViewHolder(
            (TextView) convertView.findViewById(R.id.time), 
            (Button) convertView.findViewById(R.id.consume), 
            (ImageView) convertView.findViewById(R.id.thumbnail), 
            (TextView) convertView.findViewById(R.id.content_title), 
            (TextView) convertView.findViewById(R.id.content_brief), 
            (RatingBar) convertView.findViewById(R.id.ratingBar)); 
        convertView.setTag(viewHolder); 
      } else { 
        viewHolder = (FruitLoopsViewHolder) convertView.getTag(); 
        determinePresentationMode(convertView, viewHolder); 
      } 

      /** [Omitted some code setting many of the fields above to] */ 

      final Button button = viewHolder.getButton(); 
      final View finalConvertView = convertView; 
      button.setOnClickListener(new OnClickListener() 
      { 
        public void onClick(View view) 
        { 
          button.setEnabled(false); 
          button.setVisibility(View.INVISIBLE); 
          finalConvertView.setAlpha(0.5f); 
          finalConvertView.setBackgroundColor(Color.GRAY); 
        } 
      }); 

      /** 
      * As using a final viewHolder to set the value inside the onClick() method of the 
      * button will cause the images not to update anymore, investigating the alpha value 
      * of the convertView seemed the only easy way to get there. Also, as it is a float, 
      * I want to leave a bit of extra padding in the test. 
      */ 
      if(finalConvertView.getAlpha() < 0.9) 
      { 
        viewHolder.setConsumed(true); 
      } 

    return convertView; 
    } 

    private void determinePresentationMode(View convertView, FruitLoopsViewHolder viewHolder) 
    { 
      if(viewHolder.wasConsumed()) 
      { 
        convertView.setAlpha(0.5f); 
        convertView.setBackgroundColor(Color.GRAY); 
      } 
    } 
} 

回答

2

我相信你需要重新設置阿爾法到初始狀態,如果wasConsumed()是假的。

喜歡的東西:

private void determinePresentationMode(View convertView, FruitLoopsViewHolder viewHolder) 
    { 
      if(viewHolder.wasConsumed()) 
      { 
        convertView.setAlpha(0.5f); 
        convertView.setBackgroundColor(Color.GRAY); 
      } else { 
        convertView.setAlpha(1f); // A value higher of 0.9 
        convertView.setBackgroundColor(Color.WHITE); // or whatever color 
      } 
    } 

您的問題是你重複使用相同的視圖,但你有相同的字母。 我會保持狀態信息在ViewHolder而不是確定基於的狀態convertView#alpha

+0

這個技巧。我錯過了'View'被重用。如果可能的話,如果你知道,爲什麼系統重用同一個對象?我原以爲列表的每一行都會有一個'View'。 – Eric

+2

@Eric Tobias在這裏,你有一個谷歌大家3年前做的會議,他們談論它,[GoogleI/O 2010](http://www.youtube.com/watch?v=wDBM6wVEO70#t=3m10s) – AlexBcn

+0

我會看看它。非常感謝您的參考! – Eric

0

刪除if (convertView == null)條件,然後嘗試在getView()

@Override 
    public View getView(int position, View convertView, ViewGroup parentViewGroup) 
    {  
      FruitLoopsViewHolder viewHolder; 
      final FruitLoopsNode FruitLoopsNode = provider.get(position); 


       convertView = LayoutInflater.from(parentViewGroup.getContext()).inflate(R.layout.list_FruitLoops, null); 

       viewHolder = new FruitLoopsViewHolder(
           (TextView) convertView.findViewById(R.id.time), 
           (Button) convertView.findViewById(R.id.consume), 
           (ImageView) convertView.findViewById(R.id.thumbnail), 
           (TextView) convertView.findViewById(R.id.content_title), 
           (TextView) convertView.findViewById(R.id.content_brief), 
           (RatingBar) convertView.findViewById(R.id.ratingBar)); 
       convertView.setTag(viewHolder); 


     /** [Omitted some code setting many of the fields above to] */ 

     final Button button = viewHolder.getButton(); 
     final View finalConvertView = convertView; 
     button.setOnClickListener(new OnClickListener() 
     { 
       public void onClick(View view) 
       { 
         button.setEnabled(false); 
         button.setVisibility(View.INVISIBLE); 
         finalConvertView.setAlpha(0.5f); 
         finalConvertView.setBackgroundColor(Color.GRAY); 
       } 
     }); 

     /** 
     * As using a final viewHolder to set the value inside the onClick() method of the 
     * button will cause the images not to update anymore, investigating the alpha value 
     * of the convertView seemed the only easy way to get there. Also, as it is a float, 
     * I want to leave a bit of extra padding in the test. 
     */ 
     if(finalConvertView.getAlpha() < 0.9) 
     { 
       viewHolder.setConsumed(true); 
     } 

return convertView; 
} 
+0

這不會刪除所有使用'ViewHolder'的好處嗎? – Eric

+0

只是爲了完成我以前的評論;該文檔鼓勵'null'檢查。看看'getView()'方法的文檔。 – Eric

+0

是的,它將刪除ViewHolder的所有好處。不過,我也遇到了很多與Listview相關的問題,雖然很奇怪。這種方法解決了我的問題。如果您的列表對於大型列表項目很小,則不使用這種方法,這不是推薦的。 –

相關問題