Android: счетчики внутри ListView теряют свои значения, когда я добавляю динамически новые записи ListView - PullRequest
4 голосов
/ 05 февраля 2012

Моя активность содержит кнопку и ListView. ListView содержит Spinner и представление EditText. Я использую кнопку каждый раз, когда хочу вставить новую запись строки в ListView моей активности.

Я следовал инструкциям предыдущих потоков stackoverflow, как этот здесь: Android Listview со спиннером и флажок о том, как заполнять ListViews фокусируемыми объектами, такими как Spinners.

Моя проблема в том, что каждый раз, когда я динамически добавляю новую запись ListView в ListView, значение Spinner предыдущей записи ListView теряется (фактически, Spinner возвращается к своей настройке по умолчанию). Скажем для простоты, что мои Spinner заполнены следующими данными:

 String spinner_data[] = {"apple", "banana", "pear", "watermelon", "strawberry"};

Например, если я выберу в первом значении Spinner моего ListView значение «pear», а затем добавлю новую запись ListView с моей кнопкой, запись «pear» исчезнет из 1-го Spinner ListView и появится значение по умолчанию «apple» ).

Любая помощь приветствуется!

Это моя деятельность:

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

    lv = (ListView) findViewById(R.id.lv);       
    da = new DataAdapter(this, new ArrayList<RawData>());
    lv.setAdapter(da);

    btn_new = (Button)findViewById(R.id.btn_new);

    btn_new.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            da.add(new RawData(this));
                      da.notifyDataSetChanged();
        }
    });

}

Вот класс RawData:

 public class RawData {
private int selected_position;
private ArrayAdapter<CharSequence> adapter;

public RawData(Context context)
{
    adapter = ArrayAdapter.createFromResource(context, R.array.data, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}

public ArrayAdapter<CharSequence> getAdapter() 
{         
    return adapter;     
}

/**
 * get adapter's item text from selected position
 * @return
 */
public String getText() 
{         
    return (String) adapter.getItem(selected_position);     
}

public int getSelected() 
{   
    return selected_position;     
}

public void setSelected(int selected) 
{         
    this.selected_position = selected;     
}
 }

DataArrayAdapter имеет следующий вид:

 public class DataArrayAdapter extends ArrayAdapter<RawData> {
private Activity myContext;
//private final List<RawData> list;

public DataArrayAdapter(Activity context, List<RawData> list) 
{         
    super(context, R.layout.row_view, list);         
    myContext = context;
} 

static class ViewHolder
{
    protected RawData data;
    protected Spinner spn;
    protected EditText edt;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    View view = null;
    if ( convertView == null )
    {
        LayoutInflater inflator = myContext.getLayoutInflater();             
        view = inflator.inflate(R.layout.row_view, null);

        final ViewHolder viewHolder = new ViewHolder(); 

        viewHolder.edt = (EditText)view.findViewById(R.id.edt);
        viewHolder.data = new RawData(myContext);
        viewHolder.spn = (Spinner)view.findViewById(R.id.spn);
        viewHolder.spn.setAdapter(viewHolder.data.getAdapter());

    viewHolder.spn.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int arg2_position, long arg3) {
                // TODO Auto-generated method stub
    viewHolder.data.setSelected(arg2_position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
                // TODO Auto-generated method stub

            }
        });

        // Update the TextView to reflect what's in the Spinner
        view.setTag(viewHolder);
    }
    else
    {
        view = convertView;
    }

    // This is what gets called every time the ListView refreshes
    ViewHolder holder = (ViewHolder) view.getTag();

               holder.spn.setSelection(getItem(position).getSelected());

    return view;
}

 }

1 Ответ

4 голосов
/ 05 февраля 2012

Вы не справляетесь с ситуацией, когда getView получает ненулевое значение convertView.В вашем примере, после добавления элемента, ListView обновляется, и позиция, которая должна отображать «груша», получает существующий convertView (тот, который использовался ранее для отображения «яблока»), и вы просто передаете егоListView без установки данных для текущей позиции.Вы не можете полагаться на элементы ListView для хранения каких-либо данных, вы всегда должны устанавливать правильное содержимое для позиции в методе getView вашего адаптера.Просто чтобы прояснить, я вижу, что ваш код устанавливает выбранную позицию в конце getView, но проблема в том, что все, что помечено для вашего convertView, когда оно передается в getView механизмом утилизации в ListView, является случайным иможет быть связан с любой позицией, которую он использовал для отображения ранее.

Чтобы приложение работало, вам нужно будет создать массив значений selectedItem для всех ваших счетчиков и прикрепить его в качестве члена к адаптеру.Вам нужно будет обновить соответствующее значение для каждого события OnItemSelected, и вы будете добавлять новое значение для каждого нажатия кнопки «Добавить».А когда вы подготавливаете представление в getView, вы просто устанавливаете индекс выбранного счетчика на соответствующее значение в вашем массиве.

...