2012-07-05 45 views
3


我有什麼:用Textviews和複選框的自定義列表視圖。
問題:如果我檢查屏幕上顯示的初始項目,然後查找列表,當我返回列表頂部(向上滾動)時,它們的值將被正確保存。但是,如果我滾動列表,例如我想檢查我的列表中的最後一棵樹複選框,然後如果我上下滾動,他們變得沒有檢查....爲什麼?????? **
我見過各種解決方案在其他論壇同樣的問題,也在這裏在stackoverflow,但問題仍然存在。
下面我getView功能,我認爲是好的:當滾動我的自定義列表查看框丟失檢查值

@Override 
     public View getView(final int position, View convertView, ViewGroup parent) { 
    final ViewHolder viewHolder; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item_select_friends, null); 
     viewHolder=new ViewHolder(); 
     viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); 
     viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); 
     viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); 
     viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); 

     convertView.setTag(viewHolder); 

     viewHolder.nameText.setTag(viewHolder.nameText); 
     viewHolder.nameText.setTag(viewHolder.surnameText); 
     viewHolder.contactImage.setTag(data[position]); 
     viewHolder.checkBox.setChecked(data[position].isCheck()); 
     viewHolder.checkBox.setOnClickListener(new OnClickListener() { 

      public void onClick(View arg0) { 

       if(viewHolder.checkBox.isChecked()==true) 
        data[position].setCheck(true); 
       else 
        data[position].setCheck(false); 
      } 
     }); 

    } 
    else{ 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    viewHolder.nameText.setText(data[position].getName()); 
    viewHolder.surnameText.setText(data[position].getSurname()); 
    viewHolder.contactImage.setImageResource(data[position].getPhotoRes()); 
    viewHolder.contactImage.setScaleType(ScaleType.FIT_XY); 
    viewHolder.checkBox.setChecked(data[position].isCheck()); 
    return convertView; 
} 

請幫我......兩天,我解決不了這個問題:( 感謝您的答案:)

解決:我解決我的getView的問題絲毫驗證碼:

public class NewQAAdapterSelectFriends extends BaseAdapter { 
private LayoutInflater mInflater; 
private Person[] data; 
boolean[] checkBoxState; 
ViewHolder viewHolder; 

public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context); 
} 


public void setData(Person[] data) { 
    this.data = data; 
    checkBoxState=new boolean[data.length]; 
} 

@Override 
public int getCount() { 
    return data.length; 
} 

@Override 
public Object getItem(int item) { 
    return data[item]; 
} 

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



@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item_select_friends, null); 
     viewHolder=new ViewHolder(); 

     viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); 
     viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); 
     viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); 
     viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); 

     convertView.setTag(viewHolder); 

    } 
    else{ 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    viewHolder.nameText.setText(data[position].getName()); 
    viewHolder.surnameText.setText(data[position].getSurname()); 
    viewHolder.contactImage.setImageResource(data[position].getPhotoRes()); 
    viewHolder.contactImage.setScaleType(ScaleType.FIT_XY); 
    viewHolder.checkBox.setChecked(checkBoxState[position]); 
    viewHolder.checkBox.setOnClickListener(new View.OnClickListener() { 

      public void onClick(View v) { 
       if(((CheckBox)v).isChecked()){ 
        checkBoxState[position]=true; 
        data[position].setCheck(true); 
       }else{ 
        checkBoxState[position]=false; 
        data[position].setCheck(false); 
       } 
      } 
     }); 
    return convertView; 
} 


static class ViewHolder { 
    TextView nameText; 
    TextView surnameText; 
    ImageView contactImage; 
    CheckBox checkBox; 
} 

}

我已經看到這個教程做我的getView:http://androidcocktail.blogspot.it/2012/04/adding-checkboxes-to-custom-listview-in.html

回答

1

當您使用new甚至在方法中創建類時,您已爲您的變量創建了一個不同的作用域。換句話說:

// Creating a new scope here -->  vvv 
viewHolder.checkBox.setOnClickListener(new OnClickListener() { 
    // Any variables not visible to the entire class, won't work properly in here! 
    // (variables like: viewHolder, position, possibly data) 
    public void onClick(View arg0) { 
     if(viewHolder.checkBox.isChecked()==true) 
      data[position].setCheck(true); 
     else 
      data[position].setCheck(false); 
    } 
}); // Exited "new class'" scope 

position是不一樣的position,你認爲它是。請嘗試保存的position的價值在那裏你可以再次引用它:

viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkBox); 
viewHolder.position = position; 
convertView.setTag(viewHolder); 
... 

viewHolder.checkBox.setOnClickListener(new OnClickListener() { 
    public void onClick(View view) { 
     ViewHolder viewHolder = (ViewHolder) view.getTag(); 
     data[viewHolder.position].setCheck(viewHolder.checkBox.isChecked()); 
    } 
}); 

既然你正在處理一個複選框,雖然我會建議使用OnCheckedChangeListener

但是,如果你改變了ChoiceMode你可能不需要定義任何聽衆爲ListView行:

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
+0

嗨,感謝的答案。我改變了我的代碼,如你所建議的,但現在當我點擊一個複選框,我有一個NullPointerException行數據[viewHolder.position] .setCheck(viewHolder.checkBox.isChecked());爲什麼??? – 2012-07-05 21:33:11

+0

使用你的調試器或logcat語句來確認'viewHolder'不是null,有'position',有CheckBox和data [viewHolder.position]也是有效的。但我認爲我看到我瘋了,試試這個:'ViewHolder viewHolder =(ViewHolder)((View)view.getParent())。getTag();;' – Sam 2012-07-05 23:01:47

+0

Sam,我改變我的代碼, Log.i(String,String)我已經看到,當我點擊複選框時,viewHolder.position是正確的(我的dislapy可以顯示8個項目,所以viewHolder.position有一個範圍在0,1,2,3。 .7和下一個元素重新啓動爲0,1,..(用於回收)。使用日誌我檢查數據[viewHolder.position] .getNamePerson()也適用於每個元素。firts 8個元素(0,1 ,2..7)在列表頂部起作用(當我滾動時,它們的複選框狀態被保存)。在第一個8之後的下一個元素仍然存在問題,他們從不保持它們的值 – 2012-07-06 08:08:14

0

而且viewHolder.checkBox.setOnCheckedChangedListenerviewHolder.checkBox.setOnClickListener之後添加viewHolder.checkBox.setChecked(checkBoxState[position]);

因爲滾動後,當listview回收它的視圖時,它將使用setChecked基於舊的偵聽器,這可能在某些情況下鬆散值。

所以這裏是流 -

getView() 
--- 
--- 
--- 
viewHolder.checkBox.setOnCheckedChangedListener() 
--- 
--- 
--- 
viewHolder.checkBox.setChecked() 
0
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> 
{ 
    boolean[] checkBoxState; 


    public MyAdapter(Context context, ArrayList<String> list) { 
     checkBoxState = new boolean[list.size()]; 
    } 

    @Override 
    public void onBindViewHolder(final ViewHolder holder, final int position) { 
     holder.checkBox.setTag(position); 

      holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){ 
       @Override 
       public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 
        if(compoundButton.isPressed()) // check whether user pressed the checkbox. 
        { 
         int getPosition = (Integer) compoundButton.getTag(); // Here we get the position that we have set for the checkbox using setTag. 
         checkBoxState[getPosition] = compoundButton.isChecked(); // Set the value of checkbox to maintain its state. 
        } 
       } 
      }); 

      holder.checkBox.setChecked(checkBoxState[position]); 
    } 

    public class ViewHolder extends RecyclerView.ViewHolder { 
     public CheckBox checkBox; 
     public ViewHolder(View v,MainActivity mainActivity) { 
      super(v); 
      checkBox= (CheckBox) v.findViewById(R.id.checkBox); 
     } 
    } 

    @Override 
    public int getItemCount() { 
     return list.size(); 
    } 
} 

滾動時,onCheckedChanged()方法可以被自動調用。因此,您可能需要使用isPressed()方法來檢查用戶是否按下了複選框。我的適配器類如上所示。請注意,當你添加新的元素到列表中,那麼當您一個元素添加到列表中,你應該調用下面的更新您的布爾數組checkBoxState,例如:

checkBoxState = new boolean[list.size()+1]; 

或使用ArrayList舉行布爾變量並添加元素到這個數組列表中,無論你想要什麼。

我也爲此解決方案實施了一個項目。你可以從這裏下載: https://www.dropbox.com/s/ssm58w62gw32i29/recyclerView_checkbox_highlight.zip?dl=0

截圖低於:

screen1 screen2 screen3 screen4

+0

問題是關於'ListView'類,而不是'RecyclerView' – crgarridos 2017-10-10 22:57:54

+0

同樣的問題也在recyclerView中發生。通過爲listView實現一個自定義適配器類,可以爲listView執行相同的解決方案。 – oiyio 2017-10-11 07:36:32