如何阻止Android ListView在滚动后重置值?

如何阻止Android ListView在滚动后重置值?,android,listview,arraylist,Android,Listview,Arraylist,我有一个带有自定义适配器的ListView,每行包含一个用户可以设置的seekbar。每个seekbar都有一个seekbarchaneglistener,它在适配器中设置,当用户在ListView中更改seekbar的值时,适配器的arraylist会更新。这是我在适配器的getView()中得到的: @Override public View getView(final int position, View convertView, final ViewGroup parent) {

我有一个带有自定义适配器的ListView,每行包含一个用户可以设置的seekbar。每个seekbar都有一个seekbarchaneglistener,它在适配器中设置,当用户在ListView中更改seekbar的值时,适配器的arraylist会更新。这是我在适配器的
getView()
中得到的:

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

    final ViewHolder viewHolder;

    View v = convertView;
    if(v == null){
        v = inflater.inflate(R.layout.row, null);
        viewHolder = new ViewHolder();
        viewHolder.contentView = (TextView) v.findViewById(R.id.pref_content);
        viewHolder.sliderView = (SeekBar) v.findViewById(R.id.pref_slider);
        v.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) v.getTag();
    }

    // Get initial values
    Prompt p = promptList.get(position);
    String content = p.getContent();
    int sliderLevel = p.sliderLevel();

    // Set views with initial values
    viewHolder.contentView.setText(content);
    viewHolder.sliderView.setMax(noOfLevels);
    viewHolder.sliderView.setProgress(sliderLevel);

    // Set Change Listener for Seekbar
    viewHolder.sliderView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            // Set new level of the Slider in the Array List
            promptList.get(position).setSliderLevel(progress);
        }
    });

    return v;
}
因此,当用户更改seekbar的值时,ChangeListener从ArrayList获取对象并设置其新的sliderLevel值。但是,如果我在ListView中设置了一个新值,然后再次向下滚动,以便再次调用getView,则seekbar将返回其初始值,即使我在arrayList中更改了该值


有人能告诉我哪里出了问题吗?谢谢

每当用户更改
SeekBar
值时,都会调用方法
onProgressChanged()
。但它也将被称为“按系统”(我认为这是因为
SeekBar
作为convertView的一部分被回收)。这就是为什么需要检查来自用户的
是否为真:

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    if (!fromUser) return;

    // Set new level of the Slider in the Array List
    promptList.get(position).setSliderLevel(progress);
}
在您的情况下,您不必调用
notifyDatasetChanged()
,因为只要仍显示一个特定的
SeekBar
,只有用户会更改其进度。一旦它被隐藏(因为用户滚动)并且以后必须再次显示此位置的数据,将调用
getView()
,并将正确的值设置为convertView中的
SeekBar
,此时正好显示您的数据

另一种思想(性能原因):只考虑改变代码的进度值>提示列表。一旦用户停止操作滑块,就得到(位置)< /代码>。为此,您可以覆盖

onStopTrackingTouch()
而不是
onProgressChanged()
并写入

 promptList.get(position).setSliderLevel(seekBar.getProgress());

因此,我通过将seekbarchengelistener()中的
onProgressChanged()
移动到
onStopTrackingTouch()
,成功地解决了这个问题,还可以将列表视图的高度从
wrap\u content
更改为
match\u parent
。这两件事都导致了不受欢迎的行为

出于某种原因,在运行时调用onProgressChanged(),但根本不涉及seekbar,即使在使用arrayList中的值初始化seekbar之后设置了changeListener


编辑:0X0nosugar的答案解释了这种行为

您应该创建一个单独的列表来保存每个seekbar的值,并在getView方法中设置为相应的值。Listview回收视图Listview回收视图,但适配器始终保持相同的ArrayList。回收视图时,会再次调用getView(),它将访问同一个ArrayList。因此,如果我更改ArrayList,一旦再次调用getView(),它应该会显示新的值。是的,你是对的,这很奇怪,我会尝试添加对
viewHolder.sliderView.setMax(…)
的调用非常好的解释,谢谢。我用大致相同的解决方案回答了自己的问题,但我接受这个答案,因为这是导致我的ListView出现大多数问题的原因。谢谢。你能告诉我serSliderLevel()在做什么以及放在哪里吗?