2013-12-02 3 views
0

Это касается проблемы утилизации. Я использую пользовательский адаптер для заполнения списка. В пользовательской строке есть изображение, два текстовых поля и флажок. Все элементы заполняются, но флажок не заполнен правильно.Android listview с чекбоксами не ведет себя так, как ожидалось

Внутри getView() Выполняю условие, и если условие истинно, я устанавливаю флажок для включения состояния. Это работает отлично, но с правильной галочкой, которая отмечена галочкой, есть и другие флажки с галочкой. Я прошел через многие стеки переполнения аналогичных вопросов, но не смог найти ответ. Любая помощь приветствуется.

Ниже мой адаптер класс:

public class LocationsListAdapter extends BaseAdapter { 

    List<Locations> data; 
    Context context; 
    Locations userSelectedLocation; 
    private SharedPreferences locationPreferences; 
    private SharedPreferences.Editor locationPrefsEditor; 

    public LocationsListAdapter(List<Locations> data, Context c) { 
     this.data = data; 
     this.context = c; 
    } 

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

    @Override 
    public Object getItem(int position) { 
     // TODO Auto-generated method stub 
     return data.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     // TODO Auto-generated method stub 
     return position; 
    } 

    @SuppressWarnings("static-access") 
    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 


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

     if (convertView == null) { 
      LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = vi.inflate(R.layout.find_your_location_row, null); 

      holder = new ViewHolder(); 
      holder.LocationImage = (SmartImageView) convertView.findViewById(R.id.loca_row_image); 
      holder.locationName = (TextView) convertView.findViewById(R.id.txt_loca_name); 
      holder.LocationDescription = (TextView) convertView.findViewById(R.id.txt_loca_desc); 
      holder.locationCheckText = (TextView) convertView.findViewById(R.id.txt_check); 
      holder.locationCheck = (CheckBox) convertView.findViewById(R.id.location_check); 
      holder.locationCheck.setOnCheckedChangeListener(myCheckChangList); 
      convertView.setTag(holder); 

      locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE); 
      locationPrefsEditor = locationPreferences.edit(); 
      String locationID = locationPreferences.getString("locationID", ""); 

      try { 
       if(locationID.contains(String.valueOf(data.get(position).getLocationID()))){ 
        holder.locationCheck.setChecked(true); 
       } 
      } catch (Exception e) { 
       Log.e("Fatal", " Exception"); 
      } 


      holder.locationCheck.setOnClickListener(new OnClickListener() { 

        @Override 
        public void onClick(View v) { 
         userSelectedLocation = data.get(position); 
         locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE); 
         locationPrefsEditor = locationPreferences.edit(); 
         String userSelectedLocationID = userSelectedLocation.getLocationID(); 
         locationPrefsEditor.clear(); 
         locationPrefsEditor.putString("locationID", userSelectedLocationID); 
         locationPrefsEditor.commit(); 
         Intent intent = new Intent(context, HomeScreen.class); 
         context.startActivity(intent); 
         Log.e("Check Box ", "Clicked"); 
        } 
      }); 

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

     final Locations location = data.get(position); 

     holder.LocationImage.setImageUrl(location.getImagePath()); 
     holder.locationName.setText(location.getLocationName()); 
     holder.LocationDescription.setText(location.getLocationDescription()); 

     return convertView; 
    } 

    @Override 
    public void unregisterDataSetObserver(DataSetObserver observer) { 
     if (observer != null) { 
      super.unregisterDataSetObserver(observer); 
     } 
    } 

    protected class ViewHolder { 
     protected SmartImageView LocationImage; 
     protected TextView locationName; 
     protected TextView LocationDescription; 
     protected TextView locationCheckText; 
     protected CheckBox locationCheck ; 
    } 

    OnCheckedChangeListener myCheckChangList = new OnCheckedChangeListener() { 
     public void onCheckedChanged(CompoundButton buttonView, 
       boolean isChecked) { 
      Log.e("checked", ""); 
     } 
    }; 
} 
+0

возможный дубликат [Checkbox не работает должным образом с ListView] (HTTP: //stackoverflow.com/questions/12085661/checkbox-not-working-properly-with-listview) – Braj

ответ

1

Я считаю, что ваша проблема заключается в вашей инструкции if/else.

Если convertView равно null, вы создаете новое представление и заполняете его всеми правильными данными, но если оно не является нулевым (то есть оно является переработанным представлением), вы просто возвращаете тот же самый вид назад из тега. Вы ничего не делаете с учетом установки его свойств, чтобы поддерживать состояние, которое оно уже имело (некоторые из которых были проверены)

Задайте свои свойства после того, как у вас есть действительный viewHolder.

В настоящее время у вас есть эта модель.

if (convertView == null) { 
    //Your code to create the view 
    // Your code to set the view properties 
}else { 
    holder = (ViewHolder) convertView.getTag(); 
} 

Изменить его к этому (переместить код, который задает свойства вид снаружи, если/другое так, что свойства зрения может быть установлен для всех представлений, независимо от того, являются ли они переработаны.

if (convertView == null) { 
     LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = vi.inflate(R.layout.find_your_location_row, null); 

     holder = new ViewHolder(); 
     holder.LocationImage = (SmartImageView) convertView.findViewById(R.id.loca_row_image); 
     holder.locationName = (TextView) convertView.findViewById(R.id.txt_loca_name); 
     holder.LocationDescription = (TextView) convertView.findViewById(R.id.txt_loca_desc); 
     holder.locationCheckText = (TextView) convertView.findViewById(R.id.txt_check); 
     holder.locationCheck = (CheckBox) convertView.findViewById(R.id.location_check); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    Locations location = data.get(position); 

    holder.LocationImage.setImageUrl(location.getImagePath()); 
    holder.locationName.setText(location.getLocationName()); 
    holder.LocationDescription.setText(location.getLocationDescription()); 
    boolean ShouldBoxBeChecked = //Insert check for the current box here 
    holder.locationCheck.setChecked(ShouldBoxBeChecked); 
+0

Я пробовал это сейчас. Еще не повезло. Время SOme ведет себя так, как ожидалось, но в большинстве случаев этого не происходит. Три или два флажка выбираются порой с правильной строкой. Есть идеи? – TharakaNirmana

+0

Ваш код, устанавливающий состояние флажка, является 1) условным. 2) применяется только к новым представлениям, не переработанным. Установите состояние проверки перед возвратом convertView в конце метода. Обратите внимание, что ваш код только когда-либо устанавливает состояние флажка в true. Нет ничего, что бы установить значение false, если переработанное представление уже проверено, но не обязательно. – Kuffs

+0

locationCheck.setOnClickListener также устанавливается только для новых представлений, но он жестко кодирует позицию в методе. Это означает, что любые переработанные представления будут использовать старое значение позиции, а не текущее. – Kuffs

1

Вы должны сохранить CheckBox состояния в Array или нечто подобное, когда они проверяются/деинсталлировать проверяется, чтобы запомнить состояние и в конце метода getView(...) , необходимо установить состояние для CheckBox в зависимости от значений массива.

Посмотрите Checkbox not working properly with ListView ссылку для получения более подробной информации.

1

Вы должны сделать что-то вроде этого при запуске сделать список массива и хранить состояние как ложные

private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>();  

    for (int i = 0; i < this.getCount(); i++) { 
      itemChecked.add(i, false); // initializes all items value with false 
     } 

и всякий раз, когда вы щелкаете просто изменить состояние и заполнить список с обновленными значениями каждый раз.

1

OnClickListener() объявляется только для первой пары элементов списка и использует ту же «позицию» для всех остальных элементов.

Один из вариантов, который может работать в том, что вы можете установить позицию в теге каждого флажка в списке и получить его в OnClickListener из клиновых паров

1
locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE); 
    locationPrefsEditor = locationPreferences.edit(); 
    String locationID = locationPreferences.getString("locationID", ""); 

    try { 
     if(locationID.contains(String.valueOf(data.get(position).getLocationID()))){ 
      holder.locationCheck.setChecked(true); 
     } 
    } catch (Exception e) { 
     Log.e("Fatal", " Exception"); 
    } 

Эта часть коды выполняются только, если ваш convertView == null. Вы не делаете setChecked, когда ваш convertView != null, это означает, что при повторном просмотре просмотра оно будет неправильно проверено.

1

У меня есть решение для вас.

В основном я создал два списка массивов типов.Когда вы установите флажок, соответствующее значение текстового вида (или любое другое значение, которое вы можете сохранить в соответствии с этим элементом списка), хранит в нем список CHECKEDLIST. В другом списке ALLVALUES сохранены все значения.

На кнопке мыши я сопрягать как списки и в случае совпадения, то я удалить это значение из ALLVALUES и вызвать notifydatasetchanged

package com.example.test; 

import java.io.File; 
import java.util.ArrayList; 


import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.os.Environment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.View.OnClickListener; 
import android.widget.BaseAdapter; 
import android.widget.Button; 
import android.widget.CheckBox; 
import android.widget.CompoundButton; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.CompoundButton.OnCheckedChangeListener; 

public class MainActivity extends Activity implements OnClickListener { 
    private ArrayList<String> checkedIndices = new ArrayList<String>(); 
    ArrayList<String> list = new ArrayList<String>(); 
    AScustomadapter adapter; 
int count = 0; 
private String[] vidNames = {"a","b","c","d","e","f","g","h","i"}; 
private ListView myList; 

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

    Button b1 = (Button) findViewById(R.id.button1); 
    b1.setOnClickListener(this); 



    for (int i = 0; i < vidNames.length; i++) { 
     list.add(vidNames[i]); 
    } 

    myList = (ListView)findViewById(R.id.list); 
    adapter = new AScustomadapter(getApplicationContext(), list); 
    myList.setAdapter(adapter); 
} 

@Override 
public void onClick(View v) { 
    if(v.getId() == R.id.button1) { 


     for (int i = 0; i < checkedIndices.size(); i++) { 
      for(int j = 0; j <list.size();j++){ 
      if(list.get(j).contains(checkedIndices.get(i))){ 
       list.remove(j); 
      } 
      } 
     } 
     adapter.notifyDataSetChanged(); 



    } 

} 

public class AScustomadapter extends BaseAdapter { 

private ArrayList<String> mListItems; 
private LayoutInflater mLayoutInflater; 
int i = 0; 

public AScustomadapter(Context context, ArrayList<String> arrayList) { 
    mListItems = arrayList; 
    //get the layout inflater 
    mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

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

@Override 
public Object getItem(int i) { 
    return list.get(i); 
} 

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

public int getTotalCheckedCount() { 
    return checkedIndices.size(); 
} 

@Override 
public View getView(final int position, View view, ViewGroup viewGroup) { 
    ViewHolder holder; 

    if (view == null) { 
     holder = new ViewHolder(); 

     view = mLayoutInflater.inflate(R.layout.list_item, null); 
     holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view); 
     holder.cb1 = (CheckBox) view.findViewById(R.id.checkBox1); 

     view.setTag(holder); 
    } else { 
     holder = (ViewHolder)view.getTag(); 
    } 

    final String stringItem = mListItems.get(position); 

    if (stringItem != null) { 
     if (holder.itemName != null) { 
      holder.itemName.setText(stringItem); 
     } 
    } 

    holder.cb1.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
       //is chkIos checked? 
     if (((CheckBox) v).isChecked()) { 
      if(!checkedIndices.contains(getItem(index).toString())) 
       checkedIndices.add(getItem(index).toString());   } 
     else { 
      checkedIndices.remove(getItem(index).toString()); 

     } 
      //case 2 

     } 
    }); 

    if(checkedIndices.contains((Integer)position)) { 
     holder.cb1.setChecked(true); 
    } else { 
     holder.cb1.setChecked(false); 
    } 

    //this method must return the view corresponding to the data at the specified position. 
    return view; 
} 

private class ViewHolder { 

    protected TextView itemName; 
    protected CheckBox cb1; 

} 
    } 


} 
Смежные вопросы