找到了。 ListView子類中的以下內容將完成此技巧。我在Android 4.2.1上測試過它,但它應該適用於任何4.x.
聲明:此代碼依賴於ListView的實現細節,並使用反射修改私有變量。我不能誇大這是多麼邪惡。你不應該在生產代碼中使用它!
我將此作爲概念驗證並滿足我的好奇心。如果你想使用這樣的代碼(不幸的是它有時需要獲得特定的效果),在它周圍放置版本衛士,如下所示。只能在您嘗試使用的版本上運行並檢查了源代碼。在其他情況下,您應該只使用默認行爲,例如return super.onTouchEvent(ev)
。
此代碼允許您通過最後一項下面的空白部分來滾動短列表(不成功嘗試)。點擊並拖動空白處,您應該看到過度滾動發光。如果您已經實施了像超頻滾動橡皮條效果的iPhone,這特別酷。
它是如何工作的?看看AbsListView.OnTouchEvent。在行3397中,motionPosition是當前選擇的項目索引。如果它是-1(沒有項目),if
幾行後面是錯誤的,並且mTouchMode
沒有設置。在這種情況下,我將ListView手動設置爲滾動模式。
static final int TOUCH_MODE_DOWN = 0;
static final int TOUCH_MODE_SCROLL = 3;
static final int TOUCH_MODE_FLING = 4;
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN ||
Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
final int x = (int) ev.getX();
final int y = (int) ev.getY();
int motionPosition = pointToPosition(x, y);
int action = (ev.getAction() & MotionEvent.ACTION_MASK);
if (action == MotionEvent.ACTION_DOWN) {
if (motionPosition == -1) {
setFieldInt("mActivePointerId", ev.getPointerId(0));
if (!getAdapterViewFieldBool("mDataChanged")) {
if ((getFieldInt("mTouchMode") != TOUCH_MODE_FLING)) {
setFieldInt("mTouchMode", TOUCH_MODE_DOWN);
}
}
setFieldInt("mMotionViewOriginalTop", 0);
setFieldInt("mMotionX", x);
setFieldInt("mMotionY", y);
setFieldInt("mMotionPosition", motionPosition);
setFieldInt("mLastY", Integer.MIN_VALUE);
}
}
}
return super.onTouchEvent(ev);
}
private void setFieldInt(String fieldName, int value) {
try {
Field field = AbsListView.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.setInt(this, value);
}
catch (NoSuchFieldException e) { Log.v(TAG, "exception", e); }
catch (IllegalAccessException e) { Log.v(TAG, "exception", e); }
}
private int getFieldInt(String fieldName) {
try {
Field field = AbsListView.class.getDeclaredField(fieldName);
field.setAccessible(true);
return field.getInt(this);
}
catch (NoSuchFieldException e) { Log.v(TAG, "exception", e); }
catch (IllegalAccessException e) { Log.v(TAG, "exception", e); }
return 0;
}
private boolean getAdapterViewFieldBool(String fieldName) {
try {
Field field = AdapterView.class.getDeclaredField(fieldName);
field.setAccessible(true);
return field.getBoolean(this);
}
catch (NoSuchFieldException e) { Log.v(TAG, "exception", e); }
catch (IllegalAccessException e) { Log.v(TAG, "exception", e); }
return false;
}
來源
2013-02-12 22:06:33
jdm
這是什麼動機?看到一個不佔用整個屏幕的列表應該足以說明用戶他們正在看到列表的末尾。 – Karakuri 2013-02-12 15:43:37
問題不在於用戶不知道他們是否在最後。在開發應用程序時,我以不同的觀點大肆渲染。我只看到了一個項目,當我試圖滾動時,我沒有視覺反饋(但是我在5個項目的短列表中有過反饋)。問題是,我以爲我崩潰了應用程序!我重新啓動了它幾次,甚至試圖調試它,然後才意識到我剛剛在一個死角區域進行了攻擊。 – jdm 2013-02-12 15:51:11
好吧,如果你的應用程序沒有崩潰,並且普通的Android用戶不會覺得奇怪(因爲它是標準的平臺行爲),那麼我不確定需要在這裏修復什麼。如果你真的想,也許你可以繼承ListView的子類,並自動添加頁腳視圖與剩餘空間的高度,但我真的認爲這是沒有必要的(可能比聽起來更復雜)。 – Karakuri 2013-02-12 18:37:32