之前寫過ListView和ScrollView嵌套滑動衝突問題,最近剛好遇到ListView的子View包含可以獲取焦點的情況,這種情況下只是單純的給ListView設置onTouchListener會經常失效,也就是滑動衝突重新出現了。
經過同事提點,我自己也測試了一下,解決滑動衝突的成功率果然提高了很多,話不多說,趕緊分享一下。
最開始解決衝突的方式:
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//關鍵是這一句
scrollView.requestDisallowInterceptTouchEvent(true);
return false;
}
});
這是最簡單的,要做ListView和ScrollView滑動能力自動切換可以看一下我之前的一篇分享。下面直接說這次的重點,ListView的ItemView裏包含了Button,CheckBox,EditText(尤其是這個)等會獲取焦點的控件,解決衝突的方式其實和之前的差不多,我們在自定義的adapter裏增加onTouchListener的對象,在構造函數或者另外提供一個set方法,將用於解決衝突的onTouchListener傳進ItemView裏。
下面是代碼
TestAdapter testAdapter = new TestAdapter(this, Arrays.asList(testArray), new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//判斷是否爲滑動,是滑動則讓scrollView不可滑動
//這裏只判斷了滑動,可根據需要判斷主要滑動方向(要用到ACTION_DOWN 和ACTION_UP),
//我這對解決衝突的精度沒有特別高要求,就單純判斷滑動就完事了
if(event.getAction() == MotionEvent.ACTION_MOVE){
scrollView.requestDisallowInterceptTouchEvent(true);
}
return false;
}
});
然後在會獲取焦點的控件裏,給它設置傳進去的onTouchListener
@Override
public View getView(int position, View convertView, ViewGroup parentView){
ViewHolder holder;
if(convertView == null){
convertView = View.inflate(mContext, R.layout.test_item, null);
holder = new ViewHolder();
holder.tvLabel = (TextView) convertView.findViewById(R.id.tvLabel);
holder.etValue = (EditText) convertView.findViewById(R.id.etValue);
//這個控件會獲得焦點,直接給它設置onTouchListener
holder.etValue.setOnTouchListener(onTouchListener);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tvLabel.setText(dataList.get(position));
holder.etValue.setText(dataList.get(position));
return convertView;
}
衝突問題到這就基本解決了。
其實最開始我還嘗試使用過
android:descendantFocusability="blocksDescendants"
但是基本上沒效果。最後才用這麼麻煩的方法。注意這個方法裏沒有對ListView包含EditText會導致的數據紊亂,光標異常這些問題進行處理,所以說如果用到TextWatcher這些還是需要自己再處理一下的,記錄好位置就好了,有空也分享一下這個,但這個網上也有很多,找一下就好了。