2013-12-10 3 views
0

У меня есть список, в котором каждая строка содержит флажок и текстовое представление, также у меня есть кнопка, которая должна проверять/снимать все флажки в списке, однако я не смог для достижения этого с помощью флажков OUTSIDE на экране, только с видимыми. И если я хорошо понял, это происходит из-за того, что элементы вне экранов не существуют, они перерабатываются для создания новых строк при прокрутке, вызывая нулевые указатели/из ошибок индекса при попытке проверить/получить доступ к флажкам за пределами экрана.Как проверить все флажки в ListView

I Googled для решений, но до сих пор ничего не работало.

Как я могу это решить?

Вот адаптер:

public class AlumnoArrayAdapter<T> extends BaseAdapter{ 

    Context mContext; 
    LayoutInflater mInflater; 
    ArrayList<T> mList; 
    ArrayList<Alumno> alumno; 
    boolean verEstadisticas; 
    SparseBooleanArray mSparseBooleanArray; 

    public AlumnoArrayAdapter(Context context, ArrayList<T> list, ArrayList<Alumno> alumno, boolean verEstadisticas) { 

     //TODO Auto-generated constructor stub 
     this.alumno = alumno; 
     this.verEstadisticas = verEstadisticas; 

     this.mContext = context; 

     mInflater = LayoutInflater.from(mContext); 
     mSparseBooleanArray = new SparseBooleanArray(); 
     mList = new ArrayList<T>(); 
     this.mList = list; 
    } 

    public ArrayList<T> getCheckedItems() { 
     ArrayList<T> mTempArry = new ArrayList<T>(); 

     for(int i=0;i<mList.size();i++) { 
      if(mSparseBooleanArray.get(i)) { 
       mTempArry.add(mList.get(i)); 
      } 
     } 
     return mTempArry; 
    } 

    public int getCount() { 
     return mList.size(); 
    } 

    public Object getItem(int position) { 
     return mList.get(position); 
    } 

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

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

     if(convertView == null) { 
      convertView = mInflater.inflate(R.layout.row, null); 
     } 

     TextView tvTitle = (TextView) convertView.findViewById(R.id.tvTitle); 
     tvTitle.setText(mList.get(position).toString()); 

     CheckBox mCheckBox = (CheckBox) convertView.findViewById(R.id.chkEnable); 
     mCheckBox.setTag((Integer) position); 
     mCheckBox.setChecked(mSparseBooleanArray.get(position)); 
     mCheckBox.setOnCheckedChangeListener(mCheckedChangeListener); 

     if(verEstadisticas){ 
      mCheckBox.setVisibility(View.GONE); 
     } 

     mCheckBox.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       CheckBox cb = (CheckBox) v; 
       Integer position = (Integer) cb.getTag(); 
       alumno.get(position).setChecked(cb.isChecked());     
      } 
     });  

     return convertView; 
    } 

    OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() { 

     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {    
      mSparseBooleanArray.put((Integer) buttonView.getTag(), isChecked);   
     } 
    }; 
} 

Если больше кода необходим, пожалуйста, дайте мне знать.

Поблагодарили бы за любую помощь.

Заранее благодарен!

EDIT: Есть решение !, модифицированный адаптер:

public class AlumnoArrayAdapter<T> extends BaseAdapter{ 

    Context mContext; 
    LayoutInflater mInflater; 
    ArrayList<T> mList; 
    ArrayList<Alumno> alumno; 
    boolean verEstadisticas; 
    SparseBooleanArray mSparseBooleanArray; 

    boolean checarTodo = false; 

    public AlumnoArrayAdapter(Context context, ArrayList<T> list, ArrayList<Alumno> alumno, boolean verEstadisticas) { 

     //TODO Auto-generated constructor stub 
     this.alumno = alumno; 
     this.verEstadisticas = verEstadisticas; 

     this.mContext = context; 

     mInflater = LayoutInflater.from(mContext); 
     mSparseBooleanArray = new SparseBooleanArray(); 
     mList = new ArrayList<T>(); 
     this.mList = list; 
    } 

    public ArrayList<T> getCheckedItems() { 
     ArrayList<T> mTempArry = new ArrayList<T>(); 

     for(int i=0;i<mList.size();i++) { 
      if(mSparseBooleanArray.get(i)) { 
       mTempArry.add(mList.get(i)); 
      } 
     } 
     return mTempArry; 
    } 

    public int getCount() { 
     return mList.size(); 
    } 

    public Object getItem(int position) { 
     return mList.get(position); 
    } 

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

    public void checkAll(){ 
     for(int x = 0; x < alumno.size(); x++){ 
      alumno.get(x).setChecked(!alumno.get(x).isChecked()); 
     } 
    } 

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

     if(convertView == null) { 
      convertView = mInflater.inflate(R.layout.row, null); 
     } 

     TextView tvTitle = (TextView) convertView.findViewById(R.id.tvTitle); 
     tvTitle.setText(mList.get(position).toString()); 

     CheckBox mCheckBox = (CheckBox) convertView.findViewById(R.id.chkEnable); 
     mCheckBox.setTag((Integer) position); 
     mCheckBox.setChecked(alumno.get(position).isChecked()); 

     if(verEstadisticas){ 
      mCheckBox.setVisibility(View.GONE); 
     } 

     mCheckBox.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       CheckBox cb = (CheckBox) v; 
       //Alumno Alumno = (Alumno) cb.getTag(); 
       Integer position = (Integer) cb.getTag(); 
       alumno.get(position).setChecked(cb.isChecked());     
      } 
     });  

     return convertView; 
    } 


} 

ответ

2

Вы можете попробовать следующее:

  1. Добавить одно логическое свойство в адаптере и способ установить то же самое.
  2. При нажатии кнопки, где вы хотите установить флажок. Вызовите метод адаптера для установки логического значения. И вызовите notifyDataSetChanged, это должно аннулировать и перерисовать вид списка.
  3. В процессе перерисовки вызывается метод getView адаптера. Поэтому в этом методе проверьте, установлено ли значение boolean равным true или false, и соответственно установите или снимите флажок.

Я надеюсь, что эта помощь поможет.

+0

Это работал в совершенстве. Просто немного изменили то, что вы точно предложили. Не удалось использовать логическое свойство для флага «checkAll». Вместо этого, в методе «checkAll» только что изменили логические данные для флажка в структуре данных и просто вызвали notifyDataSetChanged, чтобы перерисовать список, и вместо того, чтобы использовать mSparseBooleanArray для установки состояния флажков, я использовал ArrayList, где храню данные, которые мне нужны. Вы можете увидеть измененный адаптер в OP, отредактированный с ним. Еще раз спасибо! – Moko

1

Вы должны манипулировать «проверили» информацию в вашей структуре данных. Как вы правильно говорите, объекты GUI служат только для представления визуальной формы вашим базовым данным. Это заманчиво, но не такая хорошая идея использовать объекты GUI как единственное средство для хранения информации о статусе приложения.

1

Проверьте этот код. Попробуйте адаптироваться к адаптеру. Это не то же самое. Но небольшая модификация определенно будет работать.

class CustomAdapter extends ArrayAdapter<ContactPerson>{ 
     private ArrayList<ContactPerson> contactList; 

     public CustomAdapter(Context context, int textViewResourceId, 
       ArrayList<ContactPerson> contactList) { 
      super(context, textViewResourceId, contactList); 
      // TODO Auto-generated constructor stub 
      this.contactList = new ArrayList<ContactPerson>(); 
      this.contactList.addAll(contactList); 
     } 

     private class ViewHolder{ 
      TextView ContactName; 
      CheckBox contactCheck; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      // TODO Auto-generated method stub 

      ViewHolder holder = null; 
      Log.v("Convert View", String.valueOf(position)); 

      if(convertView==null){ 
       LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

       convertView = inflater.inflate(R.layout.checkbox_item, null); 

       holder = new ViewHolder(); 
       holder.ContactName = (TextView) convertView.findViewById(R.id.contact_name); 
       holder.contactCheck = (CheckBox) convertView.findViewById(R.id.contact_check); 

       convertView.setTag(holder); 

       holder.contactCheck.setOnClickListener(new View.OnClickListener() { 

        @Override 
        public void onClick(View v) { 
         // TODO Auto-generated method stub 
         CheckBox cb = (CheckBox) v; 
         ContactPerson contact = (ContactPerson) cb.getTag(); 
//      Log.i("clicked users", contact.getName()); 

         contact.setSelected(cb.isChecked()); 
        } 
       }); 
      } 
      else{ 
       holder = (ViewHolder) convertView.getTag(); 
      } 

      ContactPerson contacts = contactList.get(position); 
      holder.ContactName.setText("("+contacts.getName()+")"); 
      holder.contactCheck.setChecked(contacts.isSelected()); 
      holder.contactCheck.setTag(contacts); 
      holder.ContactName.setText(contacts.getName()); 
      return convertView; 
     } 
    } 



    private void checkButtonClick(){ 
     Button nextButton = (Button) findViewById(R.id.selected_done); 
     nextButton.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 
       StringBuffer display = new StringBuffer(); 
       display.append("the selected contacts are"); 

       ArrayList<ContactPerson> finalContactList = contactAdapter.contactList; 
       for(int i=0;i<finalContactList.size();i++){ 
        ContactPerson selected = finalContactList.get(i); 
        if(selected.isSelected()){ 
         display.append("\n"+selected.getName()+"\t"+selected.getPhoneNumber()); 
        } 
       } 
       Toast.makeText(getApplicationContext(), display, Toast.LENGTH_LONG).show(); 
      } 
     }); 
    } 
1

Я хотел бы использовать встроенную функцию ListView для маркировки предметов Проверили: setItemChecked, в сочетании с пользовательским триггерной точкой зрения для строк. Для отличного пошагового руководства по созданию просматриваемого вида (с разделом по обращению с флажками) см. Here.Для полноты картины, вот пример триггерной точки зрения:

public class ExampleListItemView extends RelativeLayout implements Checkable { 

    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; 

    public ExampleListItemView(Context context) { 
      super(context); 
    } 

    public ExampleListItemView(Context context, AttributeSet attrs) { 
      super(context, attrs); 
    } 

    public ExampleListItemView(Context context, AttributeSet attrs, 
        int defStyle) { 
      super(context, attrs, defStyle); 
    } 

    TextView txtExample; 
    CheckBox cbExample; 

    private boolean isChecked = false; 

    @Override 
    protected void onFinishInflate() { 
      super.onFinishInflate();   
      txtExample = (TextView) findViewById(R.id.txtExample); 
      cbExample = (CheckBox) findViewById(R.id.cbExample); 
      isChecked = false; 
    } 

    public void setText(String text){ 
      txtExample.setText(text); 
    } 

    @Override 
    public boolean isChecked() { 
      return isChecked; 
    } 

    @Override 
    public void setChecked(boolean checked) {     

      if (isChecked != checked) { 
        cbExample.setChecked(checked); 
        isChecked = checked; 
        refreshDrawableState(); 
      } 
    } 

    @Override 
    public void toggle() { 
      setChecked(!isChecked); 
    } 

    @Override 
    public int[] onCreateDrawableState(int extraSpace) { 
      final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); 
      if (isChecked()) { 
        mergeDrawableStates(drawableState, CHECKED_STATE_SET); 
      } 
      return drawableState; 
    } 

И ассоциированная XML макет:

<?xml version="1.0" encoding="utf-8"?> 
<com.example.ExampleListItemView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    ndroid:addStatesFromChildren="true" > 

    <CheckBox android:id="@+id/cbExample" /> 

    <TextView 
     android:id="@+id/txtExample" 
     android:layout_toRightOf="@id/cbExample" /> 

</com.example.ExampleListItemView> 

Вы бы тогда в конечном итоге с чем-то вроде этого:

for(int i = 0; i < adapter.getCount(); i++){ 
    listView.setItemChecked(i, true); 
} 

SparseBooleanArray checked = listView.getCheckedItemPositions(); 
Смежные вопросы