用滚动按钮的画廊 [英] Scrolling a Gallery with buttons

查看:126
本文介绍了用滚动按钮的画廊的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个画廊,其适配器创建多个的LinearLayout实例。这些线性布局实例有按钮,但是,当有人点击按钮,就不能拖库。

I have a Gallery whose Adapter creates several LinearLayout instances. Those linear layout instances have buttons, however, and when someone clicks the buttons, they can't drag the gallery.

我的想法是具有使得用户可以滚动的菜单。这种事情通常会用滚动型做,而是因为我希望滚动视图'捕捉'到当前按钮的页面,画廊效果更好。

My idea is having a menu that the user can scroll through. The kind of thing that would normally be done with a ScrollView, but because I want the scrolled view to 'Snap' to the current button pages, a Gallery works better.

这个问题是类似于此:LinearLayouts的 Android的画廊

This question is similar to this one: Android gallery of LinearLayouts

不过,虽然我已经解决了按钮会出现在点击'拖的问题时,我似乎无法使其工作就像一个滚动型呢,通过让按钮工作作为拖动区域的一部分。

However, while I've fixed the 'buttons appear clicked' when dragging issue, I can't seem to make it work like a ScrollView does, by having the buttons work as part of the dragging area.

任何提示?

不知道,如果code是相关的,但在这里它是。

Not sure if the code is relevant, but here it is.

布局包含画廊:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

        <Gallery
            android:id="@+id/gallery"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" android:fadingEdge="none"
            android:spacing="0dp"/>

</FrameLayout>

测试的活动,填充画廊:

The test activity that populates the gallery:

import com.zehfernando.display.widgets.ZGallery;

public class ScrollTestActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.scrolltest);

        Gallery gallery = (Gallery) findViewById(R.id.gallery);
        gallery.setAdapter(new LayoutAdapter(this));
    }

    public class LayoutAdapter extends BaseAdapter {
        private Context mContext;

        public LayoutAdapter(Context c) {
            mContext = c;
        }

        public int getCount() {
            return 3;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View v = vi.inflate(R.layout.scrolllayout, null);
            v.setMinimumWidth(getWindowManager().getDefaultDisplay().getWidth());
            return v;
        }
    }
}

对于去画廊内的框架布局:

The layout for the frames that go inside the gallery:

<?xml version="1.0" encoding="utf-8"?>
<com.zehfernando.display.widgets.ScrollableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/buttonRegister"
        android:layout_width="200dp"
        android:layout_height="72dp"
        android:text="REGISTER"/>

    <Button
        android:id="@+id/buttonUnregister"
        android:layout_width="match_parent"
        android:layout_height="72dp"
        android:text="UNREGISTER" />

</com.zehfernando.display.widgets.ScrollableLinearLayout>

ScrollableLinearLayout只是我的类,它扩展的LinearLayout覆盖在pressed。

"ScrollableLinearLayout" is just my class that extends LinearLayout to override onPressed.

推荐答案

好吧,我想我得到了它,所以这里是万一有人运行到这个在未来。

Ok, I think I got it, so here it is in case anyone runs into this in the future.

我不很清楚事件是如何接触传播下来的显示列表,所以这花了很多的试验和错误比我想承认,但基本上是:可以拦截触摸事件的父母,而不是让它传播给孩子,基本上翻按钮没用(允许用户点击并拖动它,将事件发送到家​​长的的onTouchEvent 代替)。这样做是与 onInterceptTouchEvent 方法。

I didn't know very well how touch events propagated down the display list, so this took a lot more trial and error than I'd like to admit, but basically: one can intercept touch events on a parent and not let it propagate to children, basically turning buttons useless (allowing users to click and drag it, sending the events to the parent's onTouchEvent instead). This is done with the onInterceptTouchEvent method.

因此​​,而不是有一个图库,我已经扩展它(称其为 ZGallery 现在)。这足以使包含按钮无用的:

So instead of having a Gallery, I've extended it (calling it a ZGallery for now). This is enough to make the contained buttons useless:

@Override
public boolean onInterceptTouchEvent(MotionEvent __e) {
    return true;
}

不过,当然,我希望确保这些按钮的工作(他们是点击),同时也让拖累。

But of course, I wanted to make sure the buttons worked (that they were clickable), while also allowing drag.

有可能是一个更聪明的方式来做到这一点,但我做的是拦截我的新画廊的触摸事件(如上面),但是的允许的是要经过(返回),直到用户移动的光标由一个给定的阈值 - 然后我跨preT它作为拖意向,正常启动拦截触摸事件。这会导致触摸事件被发送到我自己的画廊,如预期工作。

There's probably a more clever way to do this, but what I do is intercept the touch event on my new Gallery (like above), but allowing it to go through (returning false) until the user has moved the 'cursor' by a given threshold - then I interpret it as a dragging intention, start properly intercepting the touch event. This causes touch events to be sent to my own gallery, working as intended.

您可以修改它,使其垂直工作或横向拖动止也。

You can modify it to make it work for vertical or horizontal drags only too.

所以无论如何,这是一个图库类,允许拖动任何元素在它里面的一个简化版本:

So anyway, this is a simplified version of a Gallery class that allows dragging on any element inside of it:

public class ZGallery extends Gallery {

    // Constants
    protected static final float DRAG_THRESHOLD = 10; // If dragging for more than this amount of pixels, means it's a scroll

    // Properties
    protected boolean isPressed;
    protected float startPressX;
    protected float startPressY;
    protected boolean isDragging;

    // ================================================================================================================
    // CONSTRUCTOR ----------------------------------------------------------------------------------------------------

    public ZGallery(Context context) {
        this(context, null);
    }

    public ZGallery(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.galleryStyle);
    }

    public ZGallery(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    // ================================================================================================================
    // EVENT INTERFACE ------------------------------------------------------------------------------------------------

    @Override
    public boolean onInterceptTouchEvent(MotionEvent __e) {
        // Intercepts all touch screen motion events.  This allows you to watch events as they are dispatched to your children, and take ownership of the current gesture at any point.
        // Return true to steal motion events from the children and have them dispatched to this ViewGroup through onTouchEvent().
        // The current target will receive an ACTION_CANCEL event, and no further messages will be delivered here.

        //return super.onInterceptTouchEvent(__e); // super always returns false

        // If this function returns TRUE, NO children get dragging events. This only happens
        // the first interception (mouse down); if true is returned, nothing is intercepted anymore, and
        // events are passed to onTouchEvent directly.
        // If FALSE is returned, this may be called again, but only if there's a children receiving the
        // events instead of this.
        // In sum, once onTouchEvent is called here, onInterceptTouchEvent is not called anymore.

        // Interprets drag data
        return evaluateTouchEvent(__e);

    }

    @Override
    public boolean onTouchEvent(MotionEvent __e) {
        // Interprets drag data
        evaluateTouchEvent(__e);

        // Properly lets superclass interpret touch events (for dragging, fling, etc)
        return super.onTouchEvent(__e);
    }

    protected boolean evaluateTouchEvent(MotionEvent __e) {
        // Interprets motion to see if the user is dragging the View
        // This will run in parallel with the children events
        float dragDeltaX;
        float dragDeltaY;

        switch (__e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // Pressing...
                isPressed = true;
                startPressX = __e.getX();
                startPressY = __e.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                // Moving...
                if (isPressed && !isDragging) {
                    dragDeltaX = __e.getX() - startPressX;
                    dragDeltaY = __e.getY() - startPressY;

                    if (Math.abs(dragDeltaX) > DRAG_THRESHOLD || Math.abs(dragDeltaY) > DRAG_THRESHOLD) {
                        // Moved too far, means it's dragging!

                        // Inject click from correct position so superclass code knows where to drag from
                        MotionEvent me = MotionEvent.obtain(__e);
                        me.setAction(MotionEvent.ACTION_DOWN);
                        me.setLocation(__e.getX() - dragDeltaX, __e.getY() - dragDeltaY);
                        super.onTouchEvent(me);

                        isDragging = true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                // Releasing...
                if (isPressed) {
                    isPressed = false;
                    // Let go while pressed
                    if (isDragging) {
                        // Was dragging, so just go back
                        isDragging = false;
                    } else {
                        // Was not dragging, this will trigger a click
                    }
                }
                break;
        }


        // If not dragging, event should be passed on
        // If dragging, the event should be intercepted and interpreted by this gallery's onTouchEvent instead
        return isDragging;
    }
}

这似乎运作良好。希望这会有所帮助别人!

It seems to work well. Hopefully it'll be helpful to someone else!

这篇关于用滚动按钮的画廊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆