http://m.blog.csdn.net/blog/yusewuhen/43706169
轉載請注明出處:
http://blog.csdn.net/androiddevelop/article/details/38815493
希望得到的效果是ListView不能滾動,但是最大的問題在與ListView Item還必有點擊事件,如果不需要點擊事件那就簡單了,直接設置ListView.setEnable(false);
如果還需要點擊事件,滾動與點擊都是在ListView Touch處理機制管理。
ListView點擊事件是復用ViewGroup的處理邏輯,當用戶點擊視圖並且按下與抬起手指之間移動距離很小,滿足點擊事件的時間長度限制,就會觸發點擊事件。
ListView滾動事件是自己處理,有兩個判斷條件,當用戶觸發move事件並且滑動超過touch slop距離 或者 滑動速度超過閥值都會判定為滾動事件。
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;
public class ScrollDisabledListView extends ListView {
private int mPosition;
public ScrollDisabledListView(Context context) {
super(context);
}
public ScrollDisabledListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollDisabledListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
if (actionMasked == MotionEvent.ACTION_DOWN) {
// 記錄手指按下時的位置
mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
return super.dispatchTouchEvent(ev);
}
if (actionMasked == MotionEvent.ACTION_MOVE) {
// 最關鍵的地方,忽略MOVE 事件
// ListView onTouch獲取不到MOVE事件所以不會發生滾動處理
return true;
}
// 手指抬起時
if (actionMasked == MotionEvent.ACTION_UP
|| actionMasked == MotionEvent.ACTION_CANCEL) {
// 手指按下與抬起都在同一個視圖內,交給父控件處理,這是一個點擊事件
if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
super.dispatchTouchEvent(ev);
} else {
// 如果手指已經移出按下時的Item,說明是滾動行為,清理Item pressed狀態
setPressed(false);
invalidate();
return true;
}
}
return super.dispatchTouchEvent(ev);
}
}
此方法使用與listview 不在ScrollView中,當我把listview放到ScrollView中使用 該方法時,發現是不能夠正常使用的,此類問題的解決方法請往下看
Android中ScrollView中嵌套ListView解決listview滾動問題
這 幾天項目需要在ScrollView中放入ListView,一開始還以為很輕松的,就是一個xml的布局問題。但是實際操作才發現問題,會發現 ListView會顯示不完全,它的高度始終有問題。網上同樣有很多人遇到這樣的問題,大多數人不推薦這樣的設計,因為默認情況下Android是禁止在 ScrollView中放入另外的ScrollView的,它的高度是無法計算的。
但 是既然已經有這樣的需求,就要實現。StackOverFlow真是個好東西,發現已經有牛人解決了這個問題,經過試驗是可以解決這個問題的,它的思路就 是在設置完ListView的Adapter后,根據ListView的子項目重新計算ListView的高度,然后把高度再作為 LayoutParams設置給ListView,這樣它的高度就正確了,以下是源碼:
public class UIHelper {
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
}
只要在設置ListView的Adapter后調用此靜態方法即可讓ListView正確的顯示在其父ListView的ListItem中。但是要注意 的是,子ListView的每個Item必須是LinearLayout,不能是其他的,因為其他的Layout(如RelativeLayout)沒有 重寫onMeasure(),所以會在onMeasure()時拋出異常。
在ScrollView中嵌套ListView(或者ScrollView)的另外一個問題就是,子ScrollView中無法滑動的(如果它沒有顯示完 全的話),因為滑動事件會被父ScrollView吃掉,如果想要讓子ScrollView也可以滑動,只能強行截取滑動事件,有牛人在論壇中發過代碼說 可以。雖然我沒有親自試過,但估計是可行的。
雖然在ScrollView中顯示ScrollView在技術上的難題可以攻破,但是這樣的設計卻是非常差的用戶體驗因為用戶會不容易看到和操作子 ScrollView中的內容。比如好的設計是,父ListView的每個Item只顯示概括性的描述,然后點擊其Item會進入另外一個頁面來詳細描述 和展示以及對這個Item的操作。
