机器人中的垂直和水平滚动视图

我真的很累寻找一个垂直和水平滚动视图的解决方案。

我读到在框架中没有任何视图/布局来实现这个特性,但是我需要这样的东西:

我需要定义一个布局在其他,子布局必须实现滚动垂直/水平移动。

最初实现了一个按像素移动布局像素的代码,但我认为这不是正确的方法。 我用 ScrollView 和水平 ScrollView 尝试过,但是没有什么能像我想要的那样工作,因为它只实现了垂直或水平滚动。

Canvas 不是我的解决方案,因为我需要在别人的子元素中附加侦听器。

我能做什么?

209407 次浏览

选项 # 1: 您可以想出一个新的 UI 设计,不需要同时进行水平和垂直滚动。

选项 # 2: 您可以获得 ScrollViewHorizontalScrollView的源代码,了解核心 Android 团队是如何实现这些代码的,并创建自己的 BiDirectionalScrollView实现。

选项 # 3: 您可以摆脱需要使用小部件系统的依赖关系,直接绘制到 Canvas。

选项 # 4: 如果您偶然发现一个开源应用程序,它似乎实现了您所寻求的,看看他们是如何做到的。

我找到了更好的解决办法。

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

这是工作! ! !

如果要加载其他布局或控件,则结构是相同的。

由于这似乎是谷歌搜索“ Android 垂直 + 水平 ScrollView”的第一个结果,我想我应该在这里添加这个。Matt Clark 已经构建了一个基于 Android 源代码的自定义视图,它似乎工作得很完美: 二维滚动视图

请注意,该页中的类有一个计算视图水平宽度的 bug。曼努埃尔•希尔蒂(Manuel Hilty)在评论中提出了一个解决方案:

解决方案: 将第808行的语句替换为以下内容:

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


编辑: 除了 这里有一个旧版博客的链接,链接已经不工作了。

通过使用代码,可以将 HorizontalScrollView 放入 ScrollView 中。因此,您可以在同一视图中使用两个捲动方法。

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

我希望这能帮到你。

我有办法解决你的问题。您可以检查 ScrollView 代码,它只处理垂直滚动,忽略水平滚动并修改它。我想要一个像 webview 一样的视图,所以修改了 ScrollView,它对我很有用。但这可能不适合你的需要。

让我知道你的目标是什么样的用户界面。

问候,

拉维・潘迪特

我使用它并且工作得很好:

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

源链接在这里: 安卓水疗

将上面的一些建议混合起来,得到了一个很好的解决方案:

自定义 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;
}
}

活动:

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>

试试这个

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

我的解决方案基于 Mahdi Hijazi 回答,但没有任何自定义的观点:

布局:

<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,而是你想要双向滚动的布局/视图。

因为二维滚动视图链接已经死了,所以我无法得到它,所以我创建了自己的组件。它处理投掷和工程适合我。 唯一的限制是,wrash _ content 可能无法正常工作于该组件。

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

用这种方式 我试过了,我修好了

把所有的 XML 布局放在里面

<android.support.v4.widget.NestedScrollView

我在这个链接中解释了这一点 垂直回收视图和水平回收视图一起滚动

如果你想垂直和水平滚动,这是一个例子:

水平滚动在垂直滚动和两者的作品:

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