期望的效果 我有一堆小图像,我想在"墙"上显示,然后让用户在任何方向投掷这个墙并选择一个图像.
最初的想法 作为一种可能的实现我在想一个比屏幕更大的GridView可以显示 - 但是使用这个小部件的所有例子都表明Gallery没有扩展到超出屏幕的大小.
问题 用于实现所需效果的最佳小部件是什么?代码示例将特别有益.
编辑... 如果有人的示例代码可以让我在"墙上"放置约30张图片(表格会很好),那么我会接受这个作为答案.请注意,"墙"看起来应该超出显示器的边缘,并允许用户使用手指将"墙"向上拖动到左下方.拖动应该处于"自由格式"模式.单击图像就可以选择它,并且可以检测到回调.我为这个解决方案创造了一笔赏金.
解决方案实际上很简单,但很痛苦.我必须在我最近做的一个程序中实现这一点.虽然你有一些棘手的事情需要解决.必须注意的是,不同的OS版本具有不同的体验.由于这种方法有时会对绘图产生不利影响,因此需要某些专业知识或用于解决这些问题.虽然我有一个工作副本,但我提供的代码并不适合所有人,并且受到代码中进行的任何其他更改或自定义的影响.
设置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
A GridView
可以具有超出屏幕大小的内容,但仅限于垂直方向.
问题:用于实现所需效果的最佳小部件是什么?
没有实现2D滚动的默认小部件(至少在3.0之前).它们都只实现1D(单向滚动).可悲的是,你的问题的解决方案并不那么容易.
你可以:
放置一个TableLayout
自定义ScrollView
类,并自己处理触摸事件.这将允许您进行适当的2D平移,但对于大型数据集不会那么好,因为没有视图回收
GridView
如果可能,修改以启用水平滚动功能(如果可以的话,可能是最好的解决方案)
尝试将一个TableLayout
放入一个ScrollView
(带layout_width="wrap_content
)放入其中HorizontalScrollView
- 虽然这可能有效,但它不是最佳解决方案
使用OpenGL执行某些操作并直接绘制到画布 - 这是默认的Gallery 3D应用程序执行它的"图片墙"的方式