拖了不短時間才寫,完全是被坑爹的soc課設害的。今天剛到家,想起來就補上吧。
還是之前播放器的一個問題。
播放器的播放清單一般都會實現反白現正播放曲目的功能,這確實是一個比較必要的功能。
之前我是這樣實現的。
首先用一個變數curPos儲存一個現正播放的曲目所對應item
在listview的setOnItemClickListener裡面擷取了別點擊的item的position,然後以curPos為參數調用listview的childAt(擷取特定位置的view(這裡是一個TextView))方法獲得一個item來取消之前的高亮,然後再把curPos賦值為剛剛點擊的那個position的值,在讓setOnItemClickListener的onItemClick方法的參數中的view(即為被click的view)高亮顯示。
在listView沒有滾動的時候這個方法沒有異常,但是每當listview滾動過後,就會出現bug,發現取消高亮的操作失效了,其他的正常。為什麼呢?
首先究其原因發現listview的childAt方法擷取的是以當先顯示的listview的items為標準的。
舉得例子,原本沒有滾動前,listview顯示了第0-7一共8個textview,滾動之後,顯現了第2-9個textview,那麼這個時候調用childAt(2)的得到的其實是第4個textview,而不是預料中的第2個listview。
解決辦法呢?
第一個不完美的方法是這樣的。
第一個方法利用了這個listview所使用的一個baseAdapter的getView方法。
之前一直不知道getView方法具體作用是什麼。其實這個方法就是讓一個個textview顯示在listview中。
例如listview大小隻夠顯示8個textview,那麼在listview顯示的時候getView方法會被調用7次,getView方法的7次調用中的position參數的值分別就是0-7。
當你拖動螢幕往下滑動顯示了第8個textview的時候,getview方法會被再次調用一次,position參數值為8。這個時候第0個textview被滾出螢幕,就會被銷毀,如果你再往上滑動再次顯示了第0個textview,那麼getview方法會被再次調用一次,position參數值為0,第8個textview被滾出螢幕,就會被銷毀。個人推測這個應該是基於節省記憶體的考慮,只構造出被顯示的部分。否則,假如listview的item太多,一開始就全部都被構造出來,但是只有一小部分被顯示在螢幕上,這樣就太浪費了。
那麼其實我就通過getview的調用得到當前真正顯示的textview在整個listview中的真正的position。
例如我知道當前顯示的是第3-10個textview,onItemClick方法的參數中的position值為5,那麼實際就應該對childAt(5-5)所得的view進行操作。
但是理想是美好的,而現實則往往是殘酷的。這個方法就是典型的例子。
假如我滾動螢幕,第0個textview沒有被完全滾出螢幕,第8個textview也沒有被完全顯示,但確實顯示了一部分,也就是說以position為8個getview方法肯定也已經被調用之後,這個方法則認為這個listview顯示的就是第1-8個textview。但其實這個listview當前顯示的應該是0-8,然後接下來由於參照標準的錯誤,必然也會存在取消高亮的bug。事實上也是這樣的。。。
於是有了第二個方法。
baseadapter有一個notifyDataSetChanged方法,只要這樣重載一下。
@Override
public void notifyDataSetChanged() {
// TODO Auto-generated method stub
super.notifyDataSetChanged();
}
這個方法的作用是什麼呢?
這個作用的方法就是提示listview當前顯示的內容發生了變化,listview會把當前顯示的items全部都重新調用getview重新整理一遍。
那麼接下來的事情就簡單了,只要在onitemclick裡面直接對所點擊的內容高亮就行了,而getview裡面就不需要什麼操作。這樣,當listview重新整理的時候,原來高亮的item重新由於getview的調用恢複正常顯示了,新的item則在onitemclick被高亮,這樣就沒bug了。
搞了這麼久最後居然這麼輕易就解決了,其實主要就是對adapter的理解太片面,不知道adapter的很多功能以及用法,更不要說深入理解了。