2014-02-10 2 views
0

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

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

Мой код выглядит так:

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

    View someView = convertView; 

    //get question type 
    String type = questions.get(position)[2]; 

    //declare viewholder 
    final ViewHolder holder; 
    Log.i("Position", Integer.toString(position)); 

    if (someView == null) { 
    Log.i("convertView", "null"); 
    holder = new ViewHolder(); 

    LayoutInflater inflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    someView = inflater.inflate(R.layout.list_survey, parent, false); 

    TextView textView = (TextView) someView.findViewById(R.id.surveyQuestion); 
    textView.setText(questions.get(position)[1]); 

    LinearLayout optionContainer = (LinearLayout) someView.findViewById(R.id.surveyOption); 

    int size = options.get(position).size(); 

    //radio button 
    if (type.equals("radio")) { 

     RadioGroup group = new RadioGroup(this.context); 
     RelativeLayout.LayoutParams groupParam = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
     optionContainer.addView(group, groupParam); 
     RadioButton radio = null; 

     ArrayList<RadioButton> radios = new ArrayList<RadioButton>(); 

     for (int i=0; i<size; i++){ 
      radio = new RadioButton(this.context); 
      radio.setId(i+1); 
      radio.setText(options.get(position).get(i)[1]); 
      group.addView(radio); 
      radios.add(radio); 
     }  
     group.setOnCheckedChangeListener(new OnCheckedChangeListener() 
     { 
      public void onCheckedChanged(RadioGroup group, int checkedId) { 
       //Model element = (Model)group; 
      } 
     }); 

     holder.radiogroup = group; 
     holder.radiobuttons = radios; 

    //checkbox 
    } else if (type.equals("check")) { 
     CheckBox checkbox = null; 

     ArrayList<CheckBox> checks = new ArrayList<CheckBox>(); 

     for (int i=0; i<size; i++){ 
      checkbox = new CheckBox(this.context); 
      checkbox.setId(i+1); 
      checkbox.setText(options.get(position).get(i)[1]); 
      optionContainer.addView(checkbox); 
      checks.add(checkbox); 
     } 

     holder.checkboxes = checks; 

    //textfield 
    } else if (type.equals("txt")) { 
     EditText field = null; 

     ArrayList<EditText> fields = new ArrayList<EditText>(); 

     for (int i=0; i<size; i++){ 
      field = new EditText(this.context); 
      field.setId(i+1); 
      field.setHint(options.get(position).get(i)[1]); 
      optionContainer.addView(field); 
      fields.add(field); 
     } 

     holder.edittext = fields; 
    //numeric 
    } else if (type.equals("num")) { 
     EditText field = null; 

     ArrayList<EditText> fields = new ArrayList<EditText>(); 

     for (int i=0; i<size; i++){ 
      field = new EditText(this.context); 
      field.setId(i+1); 
      field.setHint(options.get(position).get(i)[1]); 
      field.setInputType(InputType.TYPE_CLASS_NUMBER); 
      optionContainer.addView(field); 
      fields.add(field); 
     } 

     holder.edittext = fields; 
    } 

    someView.setTag(holder); 

    } else { 
    Log.i("convertView", "not null"); 
    holder = (ViewHolder) someView.getTag(); 
    } 


    return someView; 
} 

Класс viewHolder здесь:

//viewHolder 
static class ViewHolder { 
    ArrayList<CheckBox> checkboxes; 
    ArrayList<EditText> edittext; 
    RadioGroup radiogroup; 
    ArrayList<RadioButton> radiobuttons;  
} 

Что я делаю неправильно?

Я очень ценю вашу помощь. Я искал некоторые другие решения, но я не могу заставить его работать над своим кодом.

Благодаря

+0

** Только ** первый пункт? Не могли бы вы вставить, как вы создаете свой собственный экземпляр «ArrayAdapter»? – nKn

+0

Ах, извините, я заметил только первое появление, но потом увидел ваш пост и проверил его. По-видимому, каждый раз, когда он прокручивается, элемент, который вышел из экрана, вызывается и заменяет следующий элемент, который должен быть в списке. – alfa

+0

Тогда ответ @ LukaCiko правильный. Вы просто управляете тегом, но вы не обновляете '' '' '' '' '' '' '' '' '' '' 'ViewHolder''. – nKn

ответ

3

Это произошло потому, что вы используете convertView и ViewHolder неправильно. Когда вы прокрутите вниз, виды будут переработаны, а converView не будет равно NULL. ViewHolder модель обычно используется следующим образом:

public View getView(int position, View convertView, ViewGroup parent) { 
    if(convertView == null) { 
     inflate the view 
     create a ViewHolder and store the necessary views in it 
     use setTag to store the ViewHolder in the convertView 
    } 
    else { 
     use getTag to get the ViewHolder 
    } 
    update the views // <- you are not doing this when convertView != null 
} 

Причина, по которой convertView/ViewHolder шаблон используется в том, что виды в списке обычно имеют одинаковую структуру, но различные данные, показанные на них. По существу, convertView (если не null) является представлением, которое ранее использовалось в списке, и должно быть преобразовано для отображения правильных данных для этой позиции. При повторном использовании вы избегаете дорогостоящей инфляции. ViewHolder - это еще одна оптимизация, с помощью которой вы избегаете также дорогих звонков findViewById.

+0

'дорогие findView calls' Сколько стоит поиск' View' в 'ViewGroup' по его идентификатору? Это простая итерация ... – gunar

+0

Ну, похоже, это так, но она должна рекурсивно пересекать иерархию «ViewGroup». По моему опыту «оптимизация« ViewHolder »имеет заметный эффект, по крайней мере, когда макет не очень простой. – LukaCiko

+0

Я понимаю основную концепцию из вашего объяснения, но я все еще не понимаю, что мне делать, чтобы она работала. Что означает обновление представлений? Должен ли я взять код, который генерирует представление из инструкции if? Если да, то что я должен помещать внутри оператора if для сохранения состояния viewHolder? – alfa

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