垂直および水平のScrollviewのソリューションを探しているのは本当にうんざりです。
この機能を実装するフレームワークにはビュー/レイアウトはないことを読みましたが、次のようなものが必要です。
他のレイアウトを定義する必要があります。子レイアウトは、移動のために垂直/水平スクロールを実装する必要があります。
レイアウトをピクセルごとに移動するコードを最初に実装しましたが、それは正しい方法ではないと思います。 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>
これは、Googleでの「Android vertical + horizontal ScrollView」の最初の検索結果であると思われるため、ここに追加する必要があると考えました。マットクラークは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>
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;
}
}
動作します!!!
他のレイアウトまたはコントロールをロードする場合、構造は同じです。
私はそれを使用して正常に動作します:
<?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>
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の代わりに、両方向にスクロールするレイアウト/ビューを配置します。
これを試して
<?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>
オプション#1:水平および垂直の同時スクロールを必要としない新しいUIデザインを思いつくことができます。
オプション#2:ScrollView
およびHorizontalScrollView
のソースコードを取得し、コアAndroidチームがそれらをどのように実装したかを学習し、独自のBiDirectionalScrollView
実装を作成できます。
オプション#3:ウィジェットシステムを使用してCanvasに直接描画する必要がある依存関係を取り除くことができます。
オプション#4:探しているものを実装していると思われるオープンソースアプリケーションを見つけた場合は、どのように実行したかを確認してください。
two Dimensional Scrollviewリンクが無効になっているため、取得できなかったため、独自のコンポーネントを作成しました。それは投げ飛ばしを処理し、私のために適切に動作します。唯一の制限は、wrap_contentがそのコンポーネントに対して適切に機能しない可能性があることです。
あなたの問題の解決策があります。垂直スクロールのみを処理し、水平スクロールを無視してこれを変更するScrollViewコードを確認できます。 WebViewのようなビューが欲しかったので、ScrollViewを修正しました。しかし、これはあなたのニーズに合わないかもしれません。
どのようなUIをターゲットにしているのか教えてください。
よろしく、
ラビ・パンディット
コードで遊んで、HorizontalScrollViewをScrollViewに入れることができます。これにより、同じビューで2つのスクロールメソッドを使用できます。
ソース: http://androiddevblog.blogspot.com/2009/12/creating-two-dimensions-scroll-view.html
これがお役に立てば幸いです。
私はこれを試して、私はそれを修正したこの方法を使用します
すべてのXMLレイアウトを内部に配置する
<Android.support.v4.widget.NestedScrollView
このリンクでこれを説明しました 垂直recyclerViewと水平recyclerviewが一緒にスクロールする