2016-07-28 44 views
1

我有一個自定義適配器的ListView,每行包含一個用戶可以設置的seekbar。每個seekbar都有一個在適配器中設置的seekBarChangeListener,並且當用戶更改ListView中的seekbar的值時,適配器的數組列表將被更新。這是我在適配器的getView()已經有了:如何停止滾動後重置值的Android ListView?

@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,seekbar將返回到其初始值,即使我已更改arrayList中的值。

有人可以幫助告訴我我要去哪裏嗎?謝謝

+0

你應該創建一個單獨的列表,以節省每一個搜索條的價值,並設置在getView方法的相應值。 ListView回收視圖 – Chol

+0

ListView回收視圖,但適配器始終保持相同的ArrayList。當視圖被回收時,再次調用getView(),它訪問相同的ArrayList。所以如果我改變ArrayList,一旦getView()被再次調用,它應該顯示新的值。 – Highway62

+0

是啊你是對的,這很奇怪 – Chol

回答

1

每次用戶更改SeekBar值時,都會調用方法onProgressChanged()。但它也將被稱爲「按系統」(我認爲這是因爲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()); 
+0

很好的解釋,謝謝。我用大致相同的解決方案回答了我自己的問題,但我會接受這個答案,因爲這是造成我的ListView大部分問題的原因。謝謝。 – Highway62

0

所以我設法從onProgressChanged()在搜索條的OnSeekBarChangeListener()移動promptList.get(position).setSliderLevel(progress)onStopTrackingTouch(),也從wrap_content改變的ListView的高度來解決問題到match_parent。這兩件事都造成了不良行爲。

由於某種原因onProgressChanged()在運行時被調用,根本不觸及seekbar,即使在使用arrayList中的值初始化seekbar之後設置了changeListener。

編輯:0X0nosugar的答案解釋這種行爲

+0

你能告訴我什麼是serSliderLevel()正在做什麼以及放置在哪裏? – 2017-11-13 16:42:11