该解决方案其实很简单,但很痛苦。我不得不在我最近做的一个计划中实现这一点。有几个棘手的事情你必须避开。必须注意的是,不同的操作系统版本有不同的体验。需要某些专业知识或者围绕这项工作,因为绘图有时会受到这种方法的不利影响。虽然我有一个工作拷贝,我提供的代码并不适合每一个人,并受到任何已经在你的代码已经做了修改或自定义。
- 设置
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