ViewPager内部的水平滚动视图

8

我有类似于安卓市场(ViewPager)的横向滚动页面。

我的问题是,我想在其中添加一些图片的横向滚动视图。这可能吗?

目前,我的视图只能进行少量滚动,然后整个页面就会滚动。

感谢您的时间!


请查看此答案 [https://dev59.com/iGsz5IYBdhLWcg3wmpP0]。但是,您需要扩展您的HorizontalScrollingView而不是使用该答案中的自定义WebView。 - grine4ka
3个回答

20

您需要扩展HorizontalScrollView并拦截触摸事件。对我而言有效的示例如下:

public class MyScrollView extends HorizontalScrollView {

    public MyScrollView(Context p_context, AttributeSet p_attrs)
    {
        super(p_context, p_attrs);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent p_event)
    {
        if (p_event.getAction() == MotionEvent.ACTION_MOVE && getParent() != null)
        {
            getParent().requestDisallowInterceptTouchEvent(true);
        }

        return super.onTouchEvent(p_event);
    }
}

那么,你需要在布局XML中使用此自定义视图,而不是使用HorizontalScrollView

帮助我找到这个解决方案的是这篇文章


它对我有效,其他解决方案不行!但似乎它会禁用自定义滚动视图内部按钮的点击处理。有什么想法吗? - user1365836
@user1365836 是啊...有时候会有点混乱...我所做的是使用getHitRect查找确切按下的按钮,然后调用它的onClick函数。 - Muzikant
7
如果您只想允许滚动但仍然可以让用户点击元素,您只需从onInterceptTouchEvent()内部控制所有内容即可。 https://gist.github.com/brandondenney/b8ddd655664eb295129d - Brandon
我在ViewPager中有几个片段,允许左右滑动。问题在于其中一个片段中,我有一个自定义图表视图,它使用触摸事件来确定绘制垂直线的位置(该线沿图表的x轴作为“光标”)。水平拖动光标会导致ViewPager将其拦截为页面滑动。因此,我重写了图表的onInterceptTouchEvent()方法(请参见@Brandon的评论),这完美地解决了问题:在图表内部的触摸拖动光标,而在图表外部的触摸仍然像应该一样滑动页面。谢谢Brandon! - The Awnry Bear
@Muzikant,你能给我一个 onClick() 的例子吗? - Ali

1
我对解决方案进行了重构,最终发现了一个非常简单的实现方式,与GMail上的方式完全相同:水平滚动视图将滚动,直到到达其边缘。然后在下一次滚动时,整个页面将进行滚动。
这只需要覆盖HorizontalScrollView以检查滚动方向与边缘,并确保内容实际可以滚动。
@Override
public boolean onTouchEvent(MotionEvent ev) 
{
    if (no_scrolling)
        return false;

    //  Standard behavior
    //
    return super.onTouchEvent(ev);
}

boolean no_scrolling = false;
float old_x, old_y;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    int action = ev.getActionMasked();
    Log.d(at_data.TAG, "HSV scroll intercept: " + String.format("0x%08x", action));

    if (action == MotionEvent.ACTION_DOWN)
    {
        old_x = ev.getX();
        old_y = ev.getY();
        no_scrolling = false;

    }
    else if (action == MotionEvent.ACTION_MOVE)
    {
        float dx = ev.getX() - old_x;
        float dy = ev.getY() - old_y;

        if (Math.abs(dx) > Math.abs(dy) && dx != 0)
        {
            View hsvChild = getChildAt(0);
            int childW = hsvChild.getWidth();
            int W = getWidth();

            Log.d(at_data.TAG, "HSV " + childW + " > " + W + " ? dx = " + dx + " dy = " + dy);
            if (childW > W)
            {
                int scrollx = getScrollX();
                if ( (dx < 0 && scrollx + W >= childW) || (dx > 0 && scrollx <= 0))
                {
                    Log.d(at_data.TAG, "HSV Wider: on edge already");
                    no_scrolling = true;
                    return false;
                }
                else
                {
                    Log.d(at_data.TAG, "HSV Wider: can scroll");
                    no_scrolling = false;
                }
            }
            else
            {
                Log.d(at_data.TAG, "HSV cannot scroll in desired direction");
                no_scrolling = true;
            }
        }
    }

    //  Standard behavior
    //
    return super.onInterceptTouchEvent(ev);
}

0
<Linearlayout>
    <linearlayout>
        <scrollView>
           <ImageView1></ImageView>
           <ImageView2></....>
        </scrollView>
    </Linearlayout>
    <EditText>
</Linearlayout>

在上述情况中,scrollVIew仅适用于两个图像,而不适用于edittext。
在其他情况下:
 <Linearlayout>
    <linearlayout>
        <scrollView>
            here listVIew with Images using listView adapter
        </scrollView>
    </Linearlayout>
    <EditText>
</Linearlayout>

这里的scrollView仅适用于listView。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接