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

时间:2016-07-28 12:39:50

标签: android listview arraylist

我有一个带有自定义适配器的ListView,每行包含一个用户可以设置的搜索栏。每个搜索栏都有一个在适配器中设置的seekBarChangeListener,当用户更改ListView中搜索栏的值时,适配器的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;
}

因此,当用户更改搜索条的值时,ChangeListener将从ArrayList获取对象并设置其新的sliderLevel值。但是,如果我在ListView中设置一个新值然后再向上滚动,那么再次调用getView,即使我更改了arrayList中的值,搜索栏也会返回其初始值。

有人可以帮我看看我在哪里出错吗?感谢

2 个答案:

答案 0 :(得分:1)

每次用户更改onProgressChanged()值时,都会调用方法SeekBar。但它也将被称为“by system”(我认为这是因为SeekBar作为convertView的一部分被回收)。这就是为什么有必要检查fromUser是否为真:

@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然后显示你的数据。

另一个想法(性能原因):考虑只在用户停止操作滑块时才更改promptList.get(position)的进度值。为此,您可以覆盖onStopTrackingTouch()而不是onProgressChanged()并写入

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

答案 1 :(得分:0)

所以我设法通过将promptList.get(position).setSliderLevel(progress)onProgressChanged()移到搜索栏的onStopTrackingTouch()中的OnSeekBarChangeListener()来解决问题,并且还从{更改ListView的高度{1}}到wrap_content。这两件事都导致了不良行为。

出于某种原因onProgressChanged()在运行时被调用,根本没有触及搜索条,即使在使用arrayList中的值初始化搜索条后设置了changeListener。

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