android - 使用按钮滚动图库

标签 android button android-layout gallery android-linearlayout

我有一个 Gallery,其 Adapter 创建了多个 LinearLayout 实例。然而,那些线性布局实例有按钮,当有人点击按钮时,他们不能拖动画廊。

我的想法是拥有一个用户可以滚动浏览的菜单。这种事情通常会用 ScrollView 完成,但因为我希望 ScrollView “捕捉”到当前按钮页面,所以 Gallery 效果更好。

这个问题与这个问题类似:Android gallery of LinearLayouts

但是,虽然我已经解决了拖动问题时“按钮显示为已单击”的问题,但我似乎无法通过将按钮作为拖动区域的一部分来使其像 ScrollView 那样工作。

有什么提示吗?

不确定代码是否相关,但在这里。

包含图库的布局:

<?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>

填充图库的测试 Activity :

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;
        }
    }
}

画廊内部框架的布局:

<?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 以覆盖 onPressed 的类。

最佳答案

好的,我想我明白了,所以把它放在这里以防将来有人遇到这个问题。

我不太清楚触摸事件是如何在显示列表中传播的,所以这比我承认的要多得多,但基本上:可以拦截父级上的触摸事件而不让它传播给 child ,基本上使按钮变得无用(允许用户单击并拖动它,而是将事件发送到 parent 的 onTouchEvent)。这是通过 onInterceptTouchEvent 方法完成的。

因此,我没有使用 Gallery,而是对其进行了扩展(暂时将其称为 ZGallery)。这足以使包含的按钮无用:

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

但当然,我想确保按钮有效(它们是可点击的),同时还允许拖动。

可能有更聪明的方法来做到这一点,但我所做的是在我的新图库(如上)上拦截触摸事件,但允许它通过(返回 false ) 直到用户将“光标”移动了给定的阈值 - 然后我将其解释为拖动 Intent ,开始正确拦截触摸事件。这会导致触摸事件发送到我自己的画廊,按预期工作。

您可以对其进行修改,使其也仅适用于垂直或水平拖动。

所以无论如何,这是一个简化版本的 Gallery 类,允许在其中拖动任何元素:

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;
    }
}

看起来效果不错。希望它会对其他人有所帮助!

关于android - 使用按钮滚动图库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8127828/

相关文章:

android - notifyDataSetChanged 不起作用

java - 使用 BufferedWriter 将相同数据写入多个文件

android - 具有与 gridview 相同行为的布局?

Android TableLayout 标题行

android - 相对布局内的 ListView 不占据整个屏幕高度

android - 我无法在 macOS Sierra 上安装英特尔 HAXM

android - 如何获取其他 fragment 的 ViewModel

javascript - 如何制作一个每次单击时显示加 1 的按钮?

javascript - X 单击后如何禁用按钮?

java - 按下按钮时重复任务(从适配器)