web-dev-qa-db-ja.com

androidの垂直および水平スクロールビュー

垂直および水平のScrollviewのソリューションを探しているのは本当にうんざりです。

この機能を実装するフレームワークにはビュー/レイアウトはないことを読みましたが、次のようなものが必要です。

他のレイアウトを定義する必要があります。子レイアウトは、移動のために垂直/水平スクロールを実装する必要があります。

レイアウトをピクセルごとに移動するコードを最初に実装しましたが、それは正しい方法ではないと思います。 ScrollViewとHorizo​​ntal ScrollViewで試しましたが、垂直または水平スクロールのみを実装しているため、思い通りに動作しません。

誰かの子要素にリスナーをアタッチする必要があるため、Canvasは私のソリューションではありません。

私に何ができる?

144
Kronos

上記のいくつかの提案を混ぜると、良い解決策を得ることができました:

カスタム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;
    }
}

カスタムHorizo​​ntalScrollView:

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

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

}

レイアウト:

<?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>
87
Mahdi Hijazi

これは、Googleでの「Android vertical + horizo​​ntal ScrollView」の最初の検索結果であると思われるため、ここに追加する必要があると考えました。マットクラークはAndroidソースに基づいてカスタムビューを作成しましたが、完全に機能しているようです: Two Dimensional ScrollView

そのページのクラスには、ビューの水平幅を計算するバグがあることに注意してください。 Manuel Hiltyによる修正はコメントにあります:

解決策:808行目のステートメントを次のように置き換えます。

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


編集:リンクはもう機能しませんが、 ブログ投稿の古いバージョンへのリンクです =。

41
Cachapa

より良い解決策を見つけました。

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コード:

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

動作します!!!

他のレイアウトまたはコントロールをロードする場合、構造は同じです。

28
Kronos

私はそれを使用して正常に動作します:

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

ソースリンクは次のとおりです。 Android-spa

25
Redax

Mahdi Hijazi answer に基づいた私のソリューションですが、カスタムビューはありません:

レイアウト:

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

コード(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;
        }
    });

スクロールビューの順序を変更できます。レイアウトとコードの順序を変更するだけです。そして明らかに、WateverViewYouWantの代わりに、両方向にスクロールするレイアウト/ビューを配置します。

16
Yan.Yurkin

これを試して

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

オプション#1:水平および垂直の同時スクロールを必要としない新しいUIデザインを思いつくことができます。

オプション#2:ScrollViewおよびHorizontalScrollViewのソースコードを取得し、コアAndroidチームがそれらをどのように実装したかを学習し、独自のBiDirectionalScrollView実装を作成できます。

オプション#3:ウィジェットシステムを使用してCanvasに直接描画する必要がある依存関係を取り除くことができます。

オプション#4:探しているものを実装していると思われるオープンソースアプリケーションを見つけた場合は、どのように実行したかを確認してください。

6
CommonsWare

two Dimensional Scrollviewリンクが無効になっているため、取得できなかったため、独自のコンポーネントを作成しました。それは投げ飛ばしを処理し、私のために適切に動作します。唯一の制限は、wrap_contentがそのコンポーネントに対して適切に機能しない可能性があることです。

https://Gist.github.com/androidseb/990209

5
androidseb

あなたの問題の解決策があります。垂直スクロールのみを処理し、水平スクロールを無視してこれを変更するScrollViewコードを確認できます。 WebViewのようなビューが欲しかったので、ScrollViewを修正しました。しかし、これはあなたのニーズに合わないかもしれません。

どのようなUIをターゲットにしているのか教えてください。

よろしく、

ラビ・パンディット

2
Ravi Pandit

コードで遊んで、Horizo​​ntalScrollViewをScrollViewに入れることができます。これにより、同じビューで2つのスクロールメソッドを使用できます。

ソース: http://androiddevblog.blogspot.com/2009/12/creating-two-dimensions-scroll-view.html

これがお役に立てば幸いです。

1
Eriatolc

私はこれを試して、私はそれを修正したこの方法を使用します

すべてのXMLレイアウトを内部に配置する

<Android.support.v4.widget.NestedScrollView 

このリンクでこれを説明しました 垂直recyclerViewと水平recyclerviewが一緒にスクロールする

0
Sirwan Rahimi