4

我在每一行都有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 action , Android listview duplicates the item on scroll

4

4 回答 4

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;
}
于 2014-04-16T08:53:11.510 回答
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中看到如何使用被监视的

于 2013-10-24T10:23:02.887 回答
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;
  }
}

有关更多信息,请参阅此链接。

希望它会帮助你。

于 2013-10-24T04:28:33.177 回答
0

更新:

下面我的原始解决方案将适用于这个用例,但更好的解决方案是ViewHolder模式的解决方案,正如 HailNaRoz 所提到的。尽管 HailNaRoz 没有解释他的解决方案为何有效,但该解决方案使用 aViewHolder来帮助View重用,并且是 Google 和 Android 开发社区采用的首选方法。ViewHolder保留对Views( EditText、等)的引用TextViewImageView并允许您在其可见时将它们添加回正确的列表行。

它也值得一看RecyclerView,它已经被引入以减轻其中一些问题,这迫使这种方法论。RecyclerView可作为支持库使用,可以在 gradle 中添加

请参阅列表视图中的视图持有者创建列表和卡片(回收站视图)

原来的:

你的问题是你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单独维护的 a 中。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框中。

于 2013-10-24T10:45:24.827 回答