当前位置:  开发笔记 > 编程语言 > 正文

希望实现一个离墙屏幕并且用户可以触摸以移动它的墙(GridView?)

如何解决《希望实现一个离墙屏幕并且用户可以触摸以移动它的墙(GridView?)》经验,为你挑选了2个好方法。

期望的效果 我有一堆小图像,我想在"墙"上显示,然后让用户在任何方向投掷这个墙并选择一个图像.

最初的想法 作为一种可能的实现我在想一个比屏幕更大的GridView可以显示 - 但是使用这个小部件的所有例子都表明Gallery没有扩展到超出屏幕的大小.

问题 用于实现所需效果的最佳小部件是什么?代码示例将特别有益.

编辑... 如果有人的示例代码可以让我在"墙上"放置约30张图片(表格会很好),那么我会接受这个作为答案.请注意,"墙"看起来应该超出显示器的边缘,并允许用户使用手指将"墙"向上拖动到左下方.拖动应该处于"自由格式"模式.单击图像就可以选择它,并且可以检测到回调.我为这个解决方案创造了一笔赏金.



1> Fuzzical Log..:

解决方案实际上很简单,但很痛苦.我必须在我最近做的一个程序中实现这一点.虽然你有一些棘手的事情需要解决.必须注意的是,不同的OS版本具有不同的体验.由于这种方法有时会对绘图产生不利影响,因此需要某些专业知识或用于解决这些问题.虽然有一个工作副本,但我提供的代码并不适合所有人,并且受到代码中进行的任何其他更改或自定义的影响.

设置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或任何其他嵌入或嵌套的需求.

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

    首先,在你的班级中,通过制作两个班级成员来开始跟踪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



2> Joseph Earl..:

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

问题:用于实现所需效果的最佳小部件是什么?
没有实现2D滚动的默认小部件(至少在3.0之前).它们都只实现1D(单向滚动).可悲的是,你的问题的解决方案并不那么容易.

你可以:

放置一个TableLayout自定义ScrollView类,并自己处理触摸事件.这将允许您进行适当的2D平移,但对于大型数据集不会那么好,因为没有视图回收

GridView如果可能,修改以启用水平滚动功能(如果可以的话,可能是最好的解决方案)

尝试将一个TableLayout放入一个ScrollView(带layout_width="wrap_content)放入其中HorizontalScrollView- 虽然这可能有效,但它不是最佳解决方案

使用OpenGL执行某些操作并直接绘制到画布 - 这是默认的Gallery 3D应用程序执行它的"图片墙"的方式

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有