Android列表视图重复滚动时编辑文本值

时间:2013-10-24 04:04:10

标签: android listview

我有一个listview,每行有一个textview和一个edit text。如果我在一个编辑文本字段中设置一个值然后向下滚动,我将在其他一些编辑文本字段中获得该输入字段值的重复值。我该如何解决这个问题?

我的适配器类如下所示:

public class CustomAdapter extends ArrayAdapter<String> {
  private Context       context;
  private String[]  names;
  ViewHolder holder;

  static class ViewHolder {
    public TextView text;
    public EditText editText;
  }

  public CustomAdapter(Context context, int textViewResourceId, String[] names) {
    super(context, textViewResourceId, names);
    this.context = context;
    this.names = names;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.row_design, parent, false);
        holder = new ViewHolder();
        holder.text = (TextView) convertView.findViewById(R.id.textView1);
        holder.editText = (EditText) convertView.findViewById(R.id.editText1);
        convertView.setTag(holder);         
    } else {            
        holder = (ViewHolder) convertView.getTag();
    }

    String s = names[position];
    holder.text.setText(s);
    return convertView;
  }
}

我已经提到了这个链接: Listview duplicate actionAndroid listview duplicates the item on scroll

4 个答案:

答案 0 :(得分:5)

首先这个问题的原因是Listview在滚动时重用它的视图, 所以我们应该在get视图中有一个逻辑来管理

if(convertview == null)
{
 //code here 
}else {
 //code here 
}    

, 但如果您不想重复使用,那么您可以使用以下内容:

 @Override
  public int getItemViewType(int position) {
    return position;
}

@Override
public int getViewTypeCount() {
    return 500;
}

答案 1 :(得分:0)

请尝试以下代码:

public class CustomAdapter extends ArrayAdapter<String> {
  private Context       context;
  private String[]  names;

  static class ViewHolder {
    public TextView text;
    public EditText editText;
  }

  public CustomAdapter(Context context, int textViewResourceId, String[] names) {
    super(context, textViewResourceId, names);
   this.context = context;
    this.names = names;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        rowView = inflater.inflate(R.layout.row_design, parent, null);
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.text = (TextView) rowView.findViewById(R.id.textView1);
        viewHolder.editText = (EditText) rowView.findViewById(R.id.editText1);
        rowView.setTag(viewHolder);         
    }          
        ViewHolder holder = (ViewHolder)rowView.getTag();


    String s = names[position];
    holder.text.setText(s);
    return rowView;
  }
}

有关详细信息,请参阅This link.

希望它会对你有所帮助。

答案 2 :(得分:0)

这是我能够想到的最好的。但试试这个作为解决方法。我同意这个问题可以有一个更好/更清洁的解决方案。

您面临的问题是ListView回收视图以获得更好的效果。

首先,您可以将数据更改为List而不是数组,并进行如下更改。

List<String> names;
List<String> edit;

// In Constructor()
this.names = names;
// Create a list with empty data for the editTexts
int listSize = names.size();
String emptyString = new String("");
List<String> emptyList = new ArrayList<String>(listSize);
for(int i = 0; i < listSize; i ++){
    emptyList.add(emptyString);
}
this.edit = emptyList;

// In getView()
// add watcher to editText and when it is changed, update the value in 'edit'
// Simply set the corresponding values to this row to the editText
holder.text.setText(names.get(position));
holder.editText.setText(edit.get(position));

你能看出这是否能在短期内解决你的问题。

您可以看到如何使用此答案https://stackoverflow.com/a/11181721/592025

中观看的内容

答案 3 :(得分:0)

<强>更新

我的原始解决方案适用于此用例,但更好的解决方案是HailNaRoz所涉及的ViewHolder模式。虽然HailNaRoz没有解释为什么他的解决方案有效,但该解决方案使用ViewHolder来帮助View重用,并且是Google和Android Dev社区采用的首选方法。 ViewHolder保留对ViewsEditTextTextViewImageView等)的引用,并允许您将它们添加回正确的列表行它变得可见。

它还值得研究RecyclerView,这是为了解决其中一些问题而引入的,这些问题迫使这种方法论出现。 RecyclerView可用作支持库,可以在gradle中添加

请参阅View Holder in List ViewCreating Lists and Cards (Recycler View)

<强>原始

您的问题是您的EditText正在被回收。您将保留TextView文字的副本,并在每次加载时重置该文本,但不会为EditText重置。

因此,您需要一种方法将文本存储在EditText字段中,并在getView()方法中重置该文本。

要执行此操作,您需要在TextWatcher中的if / else语句后设置getView()

holder.editText.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence s, int start,
                    int before, int count) {
            }

            public void beforeTextChanged(CharSequence s, int start,
                    int count, int after) {
            }

            public void afterTextChanged(Editable s) {
                  editTextList.put(position,s.toString());
            }
        });

这将值存储在单独维护的HashMap中。 position取自getView()方法中的int参数。你需要做到最后。

HashMap

private HashMap<Integer,String> editTextList =new HashMap<Integer,String>();

然后,当您设置TextView文字时,您还要设置EditText值:

holder.text.setText(s);
holder.editText.setText(editTextList.get(position));

这应该将当前位置editText保留在正确的EditText框中。