ListAdapter在滚动时显示已显示的项目

时间:2014-02-10 22:10:52

标签: java android listadapter convertview

我对Android很陌生,我目前在使用自定义列表适配器时遇到了一些问题。

基本上,我想制作一个问题列表,每个问题的类型不同(收音机,复选框,文本,数字)。 生成列表视图时,它显示正常。但是当我向下滚动时,顶部的项目会在底部重新生成。

我的代码是这样的:

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;    
}

我做错了什么?

我非常感谢你的帮助。我已经搜索了其他一些解决方案,但我的代码无法解决。

由于

1 个答案:

答案 0 :(得分:3)

之所以发生这种情况,是因为您错误地使用了convertViewViewHolder。向下滚动时,视图将被回收,converView将不为空。 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(非空时)是先前在列表中使用的视图,必须转换为显示此位置的正确数据。通过重复使用,您可以避免昂贵的布局膨胀。 ViewHolder是进一步的优化,可以避免昂贵的findViewById来电。