[android] 안드로이드에서 스크롤보기 수직 및 수평

세로 및 가로 스크롤보기 솔루션을 찾는 데 정말 피곤합니다.

이 기능을 구현하는 프레임 워크에는 뷰 / 레이아웃이 없지만 다음과 같은 것이 필요하다는 것을 읽었습니다.

다른 레이아웃 내에서 레이아웃을 정의해야합니다. 자식 레이아웃은 이동을 위해 수직 / 수평 스크롤을 구현해야합니다.

처음에는 레이아웃을 픽셀 단위로 이동시키는 코드를 구현했지만 올바른 방법은 아니라고 생각합니다. ScrollView 및 Horizontal ScrollView로 시도했지만 세로 또는 가로 스크롤 만 구현하기 때문에 원하는대로 작동하지 않습니다.

Canvas는 누군가의 자식 요소에 리스너를 연결해야하기 때문에 내 솔루션이 아닙니다.

어떡해?



답변

위의 제안 중 일부를 혼합하여 좋은 해결책을 얻을 수있었습니다.

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

사용자 정의 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;
    }
}

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>


답변

이것이 “Android vertical + horizontal ScrollView”에 대한 Google의 첫 번째 검색 결과 인 것 같으므로 여기에 추가해야한다고 생각했습니다. Matt Clark은 Android 소스를 기반으로 사용자 정의보기를 작성했으며 완벽하게 작동하는 것 같습니다 : Two Dimensional ScrollView

해당 페이지의 클래스에는 뷰의 가로 너비를 계산하는 버그가 있습니다. Manuel Hilty의 수정 사항은 다음과 같습니다.

솔루션 : 808 행의 명령문을 다음으로 바꾸십시오.

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

편집 : 링크가 더 이상 작동하지 않지만 여기에 이전 버전의 블로그 게시물에 대한 링크가 있습니다.


답변

더 나은 해결책을 찾았습니다.

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>

자바 코드 :

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

작동합니다 !!!

다른 레이아웃이나 컨트롤을로드하려면 구조가 동일합니다.


답변

나는 그것을 사용하고 잘 작동합니다.

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


답변

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 대신 두 방향으로 스크롤하려는 레이아웃 /보기를 넣습니다.


답변

옵션 # 1 : 수평 및 수직 스크롤을 동시에 필요로하지 않는 새로운 UI 디자인을 제안 할 수 있습니다.

옵션 # 2 : ScrollView및에 소스 코드를 가져 와서 HorizontalScrollView핵심 Android 팀이이를 구현 한 방법을 배우고 고유 한 BiDirectionalScrollView구현을 만들 수 있습니다 .

옵션 # 3 : 위젯 시스템을 사용하고 Canvas로 곧바로 그려야하는 종속성을 제거 할 수 있습니다.

옵션 # 4 : 원하는 것을 구현하는 오픈 소스 응용 프로그램을 우연히 발견 한 경우 어떻게했는지 살펴보십시오.


답변

이 시도

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