Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/222.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 双向滚动视图_Android_Scroll_Android Layout - Fatal编程技术网

Android 双向滚动视图

Android 双向滚动视图,android,scroll,android-layout,Android,Scroll,Android Layout,我想有一个线性布局,顶部有一个标题部分,下面有一个网络视图。标题将较短,网络视图可能比屏幕更长、更宽 获得水平和垂直滚动的最佳方式是什么?在水平滚动视图中嵌套滚动视图是个好主意吗 在水平滚动视图中嵌套滚动视图是个好主意吗 是的,也不是 是的,我的理解是,ScrollView和HorizontalScrollView可以嵌套 不,好的,ScrollView和HorizontalScrollView都不能使用WebView 我建议您将网络视图放在屏幕上。我知道您已经接受了您的答案,但这可能会给您一些

我想有一个线性布局,顶部有一个标题部分,下面有一个网络视图。标题将较短,网络视图可能比屏幕更长、更宽

获得水平和垂直滚动的最佳方式是什么?在水平滚动视图中嵌套滚动视图是个好主意吗

在水平滚动视图中嵌套滚动视图是个好主意吗

是的,也不是

是的,我的理解是,
ScrollView
HorizontalScrollView
可以嵌套

不,好的,
ScrollView
HorizontalScrollView
都不能使用
WebView


我建议您将
网络视图
放在屏幕上。

我知道您已经接受了您的答案,但这可能会给您一些想法

<?xml version="1.0" encoding="utf-8"?>

<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<HorizontalScrollView
    android:layout_alignParentBottom="true"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
>
<ImageView

android:src="@drawable/device_wall"
android:scaleType="center"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</HorizontalScrollView>
</RelativeLayout>
</LinearLayout>
</ScrollView>

再过两年,我认为开源社区可能会拯救你:


编辑:链接不再工作,但是

还有另一种方法。修改了水平滚动视图作为滚动视图的包装。正常水平滚动视图当捕捉触摸事件时,不会将它们转发到滚动视图,并且一次只能滚动一个方向。以下是解决方案:

package your.package;

import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.view.MotionEvent;
import android.content.Context;
import android.util.AttributeSet;

public class WScrollView extends HorizontalScrollView
{
    public ScrollView sv;
    public WScrollView(Context context)
    {
        super(context);
    }

    public WScrollView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

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

    @Override public boolean onTouchEvent(MotionEvent event)
    {
        boolean ret = super.onTouchEvent(event);
        ret = ret | sv.onTouchEvent(event);
        return ret;
  }

    @Override public boolean onInterceptTouchEvent(MotionEvent event)
    {
        boolean ret = super.onInterceptTouchEvent(event);
        ret = ret | sv.onInterceptTouchEvent(event);
        return ret;
    }
}
使用:

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

/*BIDIRECTIONAL SCROLLVIEW*/
        ScrollView sv = new ScrollView(this);
        WScrollView hsv = new WScrollView(this);
        hsv.sv = sv;
/*END OF BIDIRECTIONAL SCROLLVIEW*/

        RelativeLayout rl = new RelativeLayout(this);
        rl.setBackgroundColor(0xFF0000FF);
        sv.addView(rl, new LayoutParams(500, 500));
        hsv.addView(sv, new LayoutParams(WRAP_CONTENT, MATCH_PARENT /*or FILL_PARENT if API < 8*/));
        setContentView(hsv);
    }
@创建时重写公共void(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/*双向滚动视图*/
ScrollView sv=新的ScrollView(此);
WScrollView hsv=新的WScrollView(本);
hsv.sv=sv;
/*双向滚动视图结束*/
RelativeLayout rl=新的RelativeLayout(本);
rl.立根基色(0xFF0000FF);
sv.addView(rl,新布局参数(500500));
hsv.addView(sv,新布局参数(包装内容,匹配父项/*或填充父项,如果API<8*/);
setContentView(hsv);
}

有一个简单的解决方法: 在您的活动中,获取对外部滚动视图的引用(我将假设为垂直滚动视图)和对该滚动视图的第一个子视图的引用

Scrollview scrollY = (ScrollView)findViewById(R.id.scrollY);
LinearLayout scrollYChild = (LinearLayout)findViewById(R.id.scrollYChild);

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    scrollYChild.dispatchTouchEvent(event);
    scrollY.onTouchEvent(event);
    return true;
}

有人可能会说这个解决方案有点老套。但它在一些应用程序中对我非常有效

我花了很长时间才找到这条线索。非常接近解决方案,但仍然无法正常工作。下面是它的工作原理(至少对我来说(安卓2.3.7))。我希望,它在任何其他Android版本上也能工作

创建一个名为VScrollView的类:

package your.package.name;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;


public class VScrollView extends ScrollView {
    public HorizontalScrollView sv;

    public VScrollView(Context context) {
        super(context);
    }

    public VScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        sv.dispatchTouchEvent(event);
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        super.onInterceptTouchEvent(event);
        sv.onInterceptTouchEvent(event);
        return true;
    }
}
您的布局应该如下所示:

<your.package.name.VScrollView
    android:id="@+id/scrollVertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <HorizontalScrollView
        android:id="@+id/scrollHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TableLayout
            android:id="@+id/table"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="false"
            android:stretchColumns="*" >
        </TableLayout>
    </HorizontalScrollView>
</your.package.name.VScrollView>

。。。这就是它的工作原理。至少对我来说是这样。

回答晚了,但希望能对某人有所帮助。 你可以退房。这在很大程度上是基于答案的,但我似乎在获取实际内容时遇到了很多麻烦。因此,我从&to-create中获取了最新的源代码。还有一些
todo的
,我还没来得及完成,但它足以让内容同时水平和垂直滚动

我尝试了和两种解决方案,我不得不调整它们,因为有一个警告日志:
HorizontalScrollView:onTouchEvent中的无效指针ID=-1
,而且我不喜欢创建两个滚动视图

这是我的课:

public class ScrollView2D extends ScrollView {

    private HorizontalScrollView innerScrollView;

    public ScrollView2D(Context context) {
        super(context);

        addInnerScrollView(context);
    }

    public ScrollView2D(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        if (getChildCount() == 1) {
            View subView = getChildAt(0);
            removeViewAt(0);
            addInnerScrollView(getContext());
            this.innerScrollView.addView(subView);
        } else {
            addInnerScrollView(getContext());
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean handled = super.onTouchEvent(event);
        handled |= this.innerScrollView.dispatchTouchEvent(event);
        return handled;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        super.onInterceptTouchEvent(event);
        return true;
    }


    public void setContent(View content) {
        if (content != null) {
            this.innerScrollView.addView(content);
        }
    }


    private void addInnerScrollView(Context context) {
        this.innerScrollView = new HorizontalScrollView(context);
        this.innerScrollView.setHorizontalScrollBarEnabled(false);
        addView(this.innerScrollView);
    }

}
在XML中使用它时,如果在此处设置此滚动视图的内容,则无需执行任何操作。否则,您只需要调用方法
setContent(View content)
,让这个
ScrollView2D
知道它的内容是什么

例如:

// Get or create a ScrollView2D.
ScrollView2D scrollView2D = new ScrollView2D(getContext());
scrollView2D.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(scrollView2D);

// Set the content of scrollView2D.
RelativeLayout testView = new RelativeLayout(getContext());
testView.setBackgroundColor(0xff0000ff);
testView.setLayoutParams(new ViewGroup.LayoutParams(2000, 2000));
scrollView2D.setContent(testView);

一段时间以来,我一直在尝试解决方案,但效果最好的解决方案仍然有一个问题:它吞噬了所有事件,没有一个能够穿透滚动条中的元素

所以我有。。。另一个答案,在Github中,并且至少满怀希望地发表了评论:

与所有解决方案一样,它是嵌套的HorizontalScrollview(外部)+ScrollView(内部),外部从Android接收触摸事件,内部仅从外部视图内部接收触摸事件

然而,我依靠ScrollView来决定触摸事件是否有趣,在他们接受它之前,不要让触摸(即点击打开链接等)仍然可以到达子元素

(该视图还支持我所需的收缩到缩放。)

在外部滚动条中:

@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
    if (super.onInterceptTouchEvent(event) || vscroll.onInterceptTouchEventInt(event)) {
        onTouchEvent(event);
        return true;
    }
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
    super.onTouchEvent(event);
    /* Beware: One ugliness of passing on events like this is that normally a ScrollView will
       do transformation of the event coordinates which we're not doing here, mostly because
       things work well enough without doing that.
       For events that we pass through to the child view, transformation *will* happen (because
       we're completely ignoring those and let the (H)ScrollView do the transformation for us).
     */
    vscroll.onTouchEventInt(event);
    return true;
}
vscroll这里是“InnerScroller”,它是ScrollView的子类,对事件处理做了一些更改:我做了一些可怕的事情,以确保直接从Android传入的触摸事件被丢弃,相反,它将只从外部类获取它们,然后才将它们传递到超类:

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        /* All touch events should come in via the outer horizontal scroller (using the Int
           functions below). If Android tries to send them here directly, reject. */
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /* It will still try to send them anyway if it can't find any interested child elements.
           Reject it harder (but pretend that we took it). */
        return true;
    }

    public boolean onInterceptTouchEventInt(MotionEvent event) {
        return super.onInterceptTouchEvent(event);
    }

    public boolean onTouchEventInt(MotionEvent event) {
        super.onTouchEvent(event);
    }

我可以肯定地说,ScrollView和HorizontalScrollView可以像我所做的那样嵌套,但是用户体验很差,因为很难让它向你想要的方向滚动,而且没有对角线解释——你要么垂直移动,要么水平移动。“让你的WebView适合屏幕。”不幸的是,我没有办法做到这一点:(@Blumer我注意到了。这对我来说是可以接受的,但不是最优的。@GeorgeBailey:“不幸的是,我没有办法做到这一点。”--什么阻止了您?页面是用户生成的,如果包含一条长划线或图像,则页面太宽,如果内容太多,则页面太长。看起来与“嵌套在水平滚动视图中的滚动视图”相反。有什么我遗漏的吗?是的,在这个解决方案中,LinearLayout和RelativeLayout到底在做什么?除非它们有某种无法解释的用途,否则应该删除它们以保持视图层次结构尽可能平坦。我可以确认这是可行的!在我的版本中,我有一个包含嵌套X和Y滚动条的视图。I o跳过视图的
onTouchEvent
onInterceptTouchEvent
并将MotionEvent对象转发到两个滚动视图,如本答案中所述。Smoot
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        /* All touch events should come in via the outer horizontal scroller (using the Int
           functions below). If Android tries to send them here directly, reject. */
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /* It will still try to send them anyway if it can't find any interested child elements.
           Reject it harder (but pretend that we took it). */
        return true;
    }

    public boolean onInterceptTouchEventInt(MotionEvent event) {
        return super.onInterceptTouchEvent(event);
    }

    public boolean onTouchEventInt(MotionEvent event) {
        super.onTouchEvent(event);
    }