简体   繁体   English

在android中垂直和水平滚动视图

[英]Scrollview vertical and horizontal in android

I'm really tired looking for a solution for vertical and horizontal Scrollview.我真的很厌倦寻找垂直和水平滚动视图的解决方案。

I read that there are not any views/layouts in the framework which implement this feature, but I need something like this:我读到框架中没有实现此功能的任何视图/布局,但我需要这样的东西:

I need to define a layout within other, the child layout must implement scrolling vertical/horizontal for moving.我需要在其他中定义一个布局,子布局必须实现垂直/水平滚动才能移动。

Initially implemented a code that moved the layout pixel by pixel, but I think that is not the right way.最初实现了一个逐像素移动布局的代码,但我认为这不是正确的方法。 I tried it with ScrollView and Horizontal ScrollView but nothing works like I want it to, because it only implements vertical or horizontal scrolling.我用 ScrollView 和 Horizo​​ntal ScrollView 进行了尝试,但没有像我想要的那样工作,因为它只实现垂直或水平滚动。

Canvas is not my solution because I need to attach listeners in someones child elements. Canvas 不是我的解决方案,因为我需要在某人的子元素中附加侦听器。

What can I do?我能做什么?

Mixing some of the suggestions above, and was able to get a good solution:混合上面的一些建议,并能够得到一个很好的解决方案:

Custom ScrollView:自定义滚动视图:

package com.scrollable.view;

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

public class VScroll extends ScrollView {

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

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

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }
}

Custom HorizontalScrollView:自定义水平滚动视图:

package com.scrollable.view;

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

public class HScroll extends HorizontalScrollView {

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

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

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }
}

the ScrollableImageActivity:滚动图像活动:

package com.scrollable.view;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;

public class ScrollableImageActivity extends Activity {

    private float mx, my;
    private float curX, curY;

    private ScrollView vScroll;
    private HorizontalScrollView hScroll;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        vScroll = (ScrollView) findViewById(R.id.vScroll);
        hScroll = (HorizontalScrollView) findViewById(R.id.hScroll);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float curX, curY;

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                mx = event.getX();
                my = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                curX = event.getX();
                curY = event.getY();
                vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                mx = curX;
                my = curY;
                break;
            case MotionEvent.ACTION_UP:
                curX = event.getX();
                curY = event.getY();
                vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                break;
        }

        return true;
    }

}

the layout:布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <com.scrollable.view.VScroll android:layout_height="fill_parent"
        android:layout_width="fill_parent" android:id="@+id/vScroll">
        <com.scrollable.view.HScroll android:id="@+id/hScroll"
            android:layout_width="fill_parent" android:layout_height="fill_parent">
            <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/bg"></ImageView>
        </com.scrollable.view.HScroll>
    </com.scrollable.view.VScroll>

</LinearLayout>

Since this seems to be the first search result in Google for "Android vertical+horizontal ScrollView", I thought I should add this here.由于这似乎是“Android vertical+horizo​​ntal ScrollView”在 Google 中的第一个搜索结果,我想我应该在这里添加它。 Matt Clark has built a custom view based on the Android source, and it seems to work perfectly: Two Dimensional ScrollView Matt Clark 已经基于 Android 源代码构建了一个自定义视图,它似乎完美地工作: 二维 ScrollView

Beware that the class in that page has a bug calculating the view's horizonal width.请注意,该页面中的类在计算视图的水平宽度时存在错误。 A fix by Manuel Hilty is in the comments: Manuel Hilty 的修复在评论中:

Solution: Replace the statement on line 808 by the following:解决方案:将第 808 行的语句替换为以下内容:

 final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);


Edit: The Link doesn't work anymore but here is a link to an old version of the blogpost .编辑:该链接不再有效,但这里有一个指向旧版博文的链接

I found a better solution.我找到了更好的解决方案。

XML: (design.xml) XML: (design.xml)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <FrameLayout android:layout_width="90px" android:layout_height="90px">
    <RelativeLayout android:id="@+id/container" android:layout_width="fill_parent" android:layout_height="fill_parent">        
    </RelativeLayout>
</FrameLayout>
</FrameLayout>

Java Code: Java代码:

public class Example extends Activity {
  private RelativeLayout container;
  private int currentX;
  private int currentY;

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.design);

    container = (RelativeLayout)findViewById(R.id.container);

    int top = 0;
    int left = 0;

    ImageView image1 = ...
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image1, layoutParams);

    ImageView image2 = ...
    left+= 100;
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image2, layoutParams);

    ImageView image3 = ...
    left= 0;
    top+= 100;
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image3, layoutParams);

    ImageView image4 = ...
    left+= 100;     
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image4, layoutParams);
  }     

  @Override 
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            currentX = (int) event.getRawX();
            currentY = (int) event.getRawY();
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            int x2 = (int) event.getRawX();
            int y2 = (int) event.getRawY();
            container.scrollBy(currentX - x2 , currentY - y2);
            currentX = x2;
            currentY = y2;
            break;
        }   
        case MotionEvent.ACTION_UP: {
            break;
        }
    }
      return true; 
  }
}

That's works!!!那是有效的!!!

If you want to load other layout or control, the structure is the same.如果要加载其他布局或控件,结构相同。

I use it and works fine:我使用它并且工作正常:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:id="@+id/ScrollView02" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView android:id="@+id/HorizontalScrollView01" 
                      android:layout_width="wrap_content" 
                      android:layout_height="wrap_content">
<ImageView android:id="@+id/ImageView01"
           android:src="@drawable/pic" 
           android:isScrollContainer="true" 
           android:layout_height="fill_parent" 
           android:layout_width="fill_parent" 
           android:adjustViewBounds="true">
</ImageView>
</HorizontalScrollView>
</ScrollView>

The source link is here: Android-spa源码链接在这里: Android-spa

My solution based on Mahdi Hijazi answer , but without any custom views:我的解决方案基于Mahdi Hijazi answer ,但没有任何自定义视图:

Layout:布局:

<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/scrollHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ScrollView 
        android:id="@+id/scrollVertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >

        <WateverViewYouWant/>

    </ScrollView>
</HorizontalScrollView>

Code (onCreate/onCreateView):代码(onCreate/onCreateView):

    final HorizontalScrollView hScroll = (HorizontalScrollView) value.findViewById(R.id.scrollHorizontal);
    final ScrollView vScroll = (ScrollView) value.findViewById(R.id.scrollVertical);
    vScroll.setOnTouchListener(new View.OnTouchListener() { //inner scroll listener         
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return false;
        }
    });
    hScroll.setOnTouchListener(new View.OnTouchListener() { //outer scroll listener         
        private float mx, my, curX, curY;
        private boolean started = false;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            curX = event.getX();
            curY = event.getY();
            int dx = (int) (mx - curX);
            int dy = (int) (my - curY);
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    if (started) {
                        vScroll.scrollBy(0, dy);
                        hScroll.scrollBy(dx, 0);
                    } else {
                        started = true;
                    }
                    mx = curX;
                    my = curY;
                    break;
                case MotionEvent.ACTION_UP: 
                    vScroll.scrollBy(0, dy);
                    hScroll.scrollBy(dx, 0);
                    started = false;
                    break;
            }
            return true;
        }
    });

You can change the order of the scrollviews.您可以更改滚动视图的顺序。 Just change their order in layout and in the code.只需在布局和代码中更改它们的顺序即可。 And obviously instead of WateverViewYouWant you put the layout/views you want to scroll both directions.显然,不是 WateverViewYouWant,而是放置要在两个方向上滚动的布局/视图。

Try this试试这个

<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:id="@+id/Sview" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView 
   android:id="@+id/hview" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
<ImageView .......
 [here xml code for image]
</ImageView>
</HorizontalScrollView>
</ScrollView>

Option #1: You can come up with a new UI design that does not require simultaneous horizontal and vertical scrolling.选项#1:你可以想出一个不需要同时水平和垂直滚动的新 UI 设计。

Option #2: You can obtain the source code to ScrollView and HorizontalScrollView , learn how the core Android team implemented those, and create your own BiDirectionalScrollView implementation.选项#2:您可以获取ScrollViewHorizontalScrollView的源代码,了解核心 Android 团队如何实现这些,并创建您自己的BiDirectionalScrollView实现。

Option #3: You can get rid of the dependencies that are requiring you to use the widget system and draw straight to the Canvas.选项#3:您可以摆脱需要使用小部件系统并直接绘制到画布的依赖项。

Option #4: If you stumble upon an open source application that seems to implement what you seek, look to see how they did it.选项#4:如果您偶然发现一个似乎实现了您所寻求的开源应用程序,请查看他们是如何做到的。

since the Two Dimensional Scrollview link is dead I could not get it so I created my own component.由于二维滚动视图链接已失效,我无法获取它,因此我创建了自己的组件。 It handles flinging and works properly for me.它可以处理投掷并为我正常工作。 The only restriction is that wrap_content might not work properly for that component.唯一的限制是 wrap_content 可能无法为该组件正常工作。

https://gist.github.com/androidseb/9902093 https://gist.github.com/androidseb/9902093

I have a solution for your problem.我有你的问题的解决方案。 You can check the ScrollView code it handles only vertical scrolling and ignores the horizontal one and modify this.您可以检查 ScrollView 代码,它只处理垂直滚动并忽略水平滚动并修改它。 I wanted a view like a webview, so modified ScrollView and it worked well for me.我想要一个像 webview 这样的视图,所以修改了 ScrollView 并且它对我来说效果很好。 But this may not suit your needs.但这可能不适合您的需求。

Let me know what kind of UI you are targeting for.让我知道你的目标是什么类型的用户界面。

Regards,问候,

Ravi Pandit拉维·潘迪特

Playing with the code, you can put an HorizontalScrollView into an ScrollView.使用代码,您可以将 Horizo​​ntalScrollView 放入 ScrollView。 Thereby, you can have the two scroll method in the same view.因此,您可以在同一个视图中使用两个滚动方法。

Source : http://androiddevblog.blogspot.com/2009/12/creating-two-dimensions-scroll-view.html来源: http : //androiddevblog.blogspot.com/2009/12/creating-two-dimensions-scroll-view.html

I hope this could help you.我希望这可以帮助你。

use this way I tried this I fixed it用这种方式我试过了我修好了

Put All your XML layout inside把你所有的 XML 布局放在里面

<android.support.v4.widget.NestedScrollView 

I explained this in this link vertical recyclerView and Horizontal recyclerview scrolling together我在这个链接Vertical recyclerView and Horizo​​ntal recyclerview scrolling together 中解释了这一点

If you want to scroll vertically and horizontally this is an example:如果要垂直和水平滚动,这是一个示例:

Horizontal scroll inside vertical scroll and both works:垂直滚动内的水平滚动,两者都有效:

<ScrollView
        android:id="@+id/verticalScroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

...
     <HorizontalScrollView
            android:id="@+id/horizontalScroll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            *android:overScrollMode="never"*>
...
     </HorizontalScrollView>
...
</ScrollView>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM