2011-05-07 37 views
19

预期的效果 我有一堆小图片,我想展现一个“墙”然后让用户向任何方向扔这个墙并选择一个图像。寻找实现墙(GridView的?)那熄灭屏幕和用户可以通过触摸来移动它

初步设想 作为一个可能的实现我在想一个GridView比屏幕可以显示大 - 但使用这个小部件的所有实例表明,该画廊没有超出屏幕的大小。

问题 什么是最好的部件来实现所需的效果?代码示例将特别有益。

编辑... 如果有人有示例代码,这将让我把大约30图像上的“墙”(表将是一件好事),那么我会接受的答案。请注意,“墙”应该看起来像它超出了显示器的边缘,并允许用户使用手指将“墙”向左下拖动。拖动应该处于“自由形式”模式。在图像上点击一下即可选中它,并且可以检测到回调。我为这个解决方案创造了一个奖励。

回答

11

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

  • 设置android:layout_widthwrap_content
  • 设置android:layout_heightwrap_content
  • 在您的代码:
    • 确定多少行,你都会有。通过行数项
    • 鸿沟号。
    • 添加GridView控件。 setStretchMode(NO_STRETCH);
    • 添加GridView控件。 setNumColumns(数列);
    • 的添加GridView控件。 setColumnWidth(像素);
  • 一个明确的宽度要滚动:
    • 您可以简单地使用GridView控件。 scrollBy()onTouchEvent()

这些步骤。所有这些都是必需的,才能使其发挥作用。关键是具有特定宽度的明确列数的NO_STRETCH。如果您需要澄清,可以提供更多细节。你甚至可以使用VelocityTracker或onFling来处理投掷。我在我的snappingToPage启用。使用此解决方案,甚至不需要覆盖onDraw()onLayout()。这三行代码摆脱了对WebView或任何其他嵌入或嵌套的需求。

双向滚动也很容易实现。这是一个简单的代码解决方案:

  1. 首先,你的班级开始跟踪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; 
    
  2. 其次,一定要检查滚动,这样你仍然可以点击或长按图片自己。

    @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; 
    } 
    
  3. 后在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

+0

我会提供一个完整的示例,但这些是唯一的3行是重要的他们可能被放置在任何地方。我有三个这样的GridView,每个放置在不同的地方(一个在初始声明中,一个在CursorAdapter中,另一个在一个单独的方法中,从多个地方调用。 – 2011-10-11 22:52:19

+1

并且...作为一个附注,我一个星期的戳和刺激找到,我很高兴,当我这样做。 – 2011-10-11 22:53:26

+0

mScroller在这种情况下提到什么?如果你详细说明一点点,我会奖励你的赏金 – 2011-10-12 06:29:29

5

A GridView可以具有超出屏幕大小的内容,但仅限于垂直方向。

问:什么是最好的部件来实现所需的效果?
没有实现2D滚动的默认小部件(至少在3.0之前)。他们都只实现一维(向一个方向滚动)。可悲的是,解决您的问题并不容易。

,你可以:

  • 放置一个TableLayout定制ScrollView类里面,自己处理触摸事件。这将允许您进行适当的2D平移,但对于大型数据集不太适合,因为没有视图可回收
  • 如果可能,修改GridView以启用水平滚动功能(如果可以的话可能是最好的解决方案)
  • 尝试把一个TableLayout一个ScrollView内(含layout_width="wrap_content),你把里面HorizontalScrollView - 尽管这可能工作,它不会是最佳的解决方案
  • 做一些与OpenGL和直画到画布 - 这是如何将默认Gallery 3D app做成“图片墙”
+0

我已经开始了具体的解决方案 – 2011-05-11 19:38:42

+0

你总是可以看看Gallery3D源代码赏金 - http://android.git.kernel.org/?p=platform/packages/apps/Gallery3D .git; a =摘要 - 直到有人回答。 – 2011-05-11 22:41:24

+1

我有一个想法,它可以很容易地完成,我会在这个周末做一个演示,看看它是否有效。 – 2011-05-19 00:47:50

0

我认为,唯一的Android本地解决方案是拥有一个嵌入式WebView,您可以在其中使用该二维滚动(并且顺便说一下,这是唯一具备此功能的东西)。

按下图像,您可以通过从JavaScript到JAva的回调来控制行为。

这不是很“漂亮”,但是......它是唯一可行的方式来做你想要的“开箱即用”。

+0

webview是一个有趣的想法。我可能会用这个想法作为最后的手段。到目前为止,我仍然处于研究模式,我发现的最好的“样本”在这里:http://stackoverflow.com/questions/3058164/android-scrolling-an-imageview – 2011-05-12 16:49:12

+0

另一个研究样本,也许我可以调整一个图像的墙壁:http://blog.sephiroth.it/2011/04/04/imageview-zoom-and-scroll/ – 2011-05-12 16:54:53

0

我实现了一个GridView,它覆盖onInterceptTouchEvent方法。我按照Fuzzical Logic的说明设置了OnTouchListener。我的问题是设置一个自定义的OnTouchListener,我的gridView的对象不再可点击。那是因为GridView的默认OnTouchListener调用onItemClickListener吗?

我想有一个2方向滚动GridView,但仍然可以cliackable对象。我是否应该实施自己的方法来检查触摸是否与项目匹配,或者是否有更简单的方法来实现此目的?

Grodak

相关问题