該解決方案其實很簡單,但很痛苦。我不得不在我最近做的一個計劃中實現這一點。有幾個棘手的事情你必須避開。必須注意的是,不同的操作系統版本有不同的體驗。需要某些專業知識或者圍繞這項工作,因爲繪圖有時會受到這種方法的不利影響。雖然我有一個工作拷貝,我提供的代碼並不適合每一個人,並受到任何已經在你的代碼已經做了修改或自定義。
- 設置
android:layout_width
到wrap_content
- 設置
android:layout_height
到wrap_content
- 在您的代碼:
- 確定多少行,你都會有。通過行數項
- 鴻溝號。
- 添加GridView控件。
setStretchMode(NO_STRETCH);
- 添加GridView控件。
setNumColumns(
數列);
- 的添加GridView控件。
setColumnWidth(
像素);
- 一個明確的寬度要滾動:
- 您可以簡單地使用GridView控件。
scrollBy()
在onTouchEvent()
這些步驟。所有這些都是必需的,才能使其發揮作用。關鍵是具有特定寬度的明確列數的NO_STRETCH。如果您需要澄清,可以提供更多細節。你甚至可以使用VelocityTracker或onFling來處理投擲。我在我的snappingToPage啓用。使用此解決方案,甚至不需要覆蓋onDraw()
或onLayout()
。這三行代碼擺脫了對WebView或任何其他嵌入或嵌套的需求。
雙向滾動也很容易實現。這是一個簡單的代碼解決方案:
首先,你的班級開始跟蹤X和Y位置,通過製作兩個班級成員。還要添加狀態跟蹤;
// Holds the last position of the touch event (including movement)
int myLastX;
int myLastY;
// Tracks the state of the Touch handling
final static private int TOUCH_STATE_REST = 0;
final static private int TOUCH_STATE_SCROLLING = 1;
int myState = TOUCH_STATE_REST;
其次,一定要檢查滾動,這樣你仍然可以點擊或長按圖片自己。
@Override public boolean onInterceptTouchEvent(final MotionEvent ev)
{//User is already scrolling something. If we haven't interrupted this already,
// then something else is handling its own scrolling and we should let this be.
// Once we return TRUE, this event no longer fires and instead all goes to
// onTouch() until the next TouchEvent begins (often beginning with ACTION_DOWN).
if ((ev.getAction() == MotionEvent.ACTION_MOVE)
&& (myState != TOUCH_STATE_REST))
return false;
// Grab the X and Y positions of the MotionEvent
final float _x = ev.getX();
final float _y = ev.getY();
switch (ev.getAction())
{ case MotionEvent.ACTION_MOVE:
final int _diffX = (int) Math.abs(_x - myLastX);
final int _diffY = (int) Math.abs(_y - myLastY);
final boolean xMoved = _diffX > 0;
final boolean yMoved = _diffY > 0;
if (xMoved || yMoved)
myState = TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_DOWN:
// Remember location of down touch
myLastX = _x;
myLastY = _y;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (myState == TOUCH_STATE_SCROLLING)
// Release the drag
myState = TOUCH_STATE_REST;
}
//If we are not At Rest, start handling in our own onTouch()
return myState != TOUCH_STATE_REST;
}
後在GridView知道您正在滾動,它會發送所有觸摸事件onTouch。在這裏做你的滾動。
@Override public boolean onTouchEvent(final MotionEvent ev)
{
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
final View child;
switch (action)
{
case MotionEvent.ACTION_DOWN:
//Supplemental code, if needed
break;
case MotionEvent.ACTION_MOVE:
// This handles Scrolling only.
if (myState == TOUCH_STATE_SCROLLING)
{
// Scroll to follow the motion event
// This will update the vars as long as your finger is down.
final int deltaX = (int) (myLastX - x);
final int deltaY = (int) (myLastY - y);
myLastX = x;
myLastY = y;
scrollBy(deltaX, deltaY);
}
break;
case MotionEvent.ACTION_UP:
// If Scrolling, stop the scroll so we can scroll later.
if (myState == TOUCH_STATE_SCROLLING)
myState = TOUCH_STATE_REST;
break
case MotionEvent.ACTION_CANCEL:
// This is just a failsafe. I don't even know how to cancel a touch event
myState = TOUCH_STATE_REST;
}
return true;
}
如果當然,這個解決方案在移動X和Y同時。如果您想一次只移動一個方向,則可以通過檢查X和Y差異中的較大差異輕鬆進行區分。 (即Math.abs(deltaX) > Math.abs(deltaY)
)以下是一個方向滾動的部分示例,但可以在X或Y方向之間切換。
3b。如果你想在同一時間處理一個方向你OnTouch()
更改此:
case MotionEvent.ACTION_MOVE:
if (myState == TOUCH_STATE_SCROLLING)
{
//This will update the vars as long as your finger is down.
final int deltaX = (int) (myLastX - x);
final int deltaY = (int) (myLastY - y);
myLastX = x;
myLastY = y;
// Check which direction is the bigger of the two
if (Math.abs(deltaX) > Math.abs(deltaY))
scrollBy(deltaX, 0);
else if (Math.abs(deltaY) > Math.abs(deltaX))
scrollBy(0, deltaY);
// We do nothing if they are equal.
}
break;
FuzzicalLogic
我會提供一個完整的示例,但這些是唯一的3行是重要的他們可能被放置在任何地方。我有三個這樣的GridView,每個放置在不同的地方(一個在初始聲明中,一個在CursorAdapter中,另一個在一個單獨的方法中,從多個地方調用。 – 2011-10-11 22:52:19
並且...作爲一個附註,我一個星期的戳和刺激找到,我很高興,當我這樣做。 – 2011-10-11 22:53:26
mScroller在這種情況下提到什麼?如果你詳細說明一點點,我會獎勵你的賞金 – 2011-10-12 06:29:29