android中的垂直和水平滚动视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2044775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scrollview vertical and horizontal in android
提问by Kronos
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 和 Horizontal ScrollView 尝试过,但没有任何效果像我想要的那样,因为它只实现了垂直或水平滚动。
Canvas is not my solution because I need to attach listeners in someones child elements.
Canvas 不是我的解决方案,因为我需要在某人的子元素中附加侦听器。
What can I do?
我能做什么?
回答by Mahdi Hijazi
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>
回答by Cachapa
Since this seems to be the first search result in Google for "Android vertical+horizontal ScrollView", I thought I should add this here. Matt Clark has built a custom view based on the Android source, and it seems to work perfectly: Two Dimensional ScrollView
由于这似乎是“Android vertical+horizontal ScrollView”在 Google 中的第一个搜索结果,我想我应该在这里添加它。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:
final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);
解决方案:将第 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.
编辑:该链接不再有效,但这里有一个指向旧版博文的链接。
回答by Kronos
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.
如果要加载其他布局或控件,结构相同。
回答by Redax
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
回答by Yan.Yurkin
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,而是放置要在两个方向上滚动的布局/视图。
回答by androidseb
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 可能无法为该组件正常工作。
回答by MBMJ
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>
回答by CommonsWare
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:您可以获取源代码,ScrollView
并且HorizontalScrollView
,学习核心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:如果您偶然发现一个似乎实现了您所寻求的开源应用程序,请查看他们是如何做到的。
回答by Ravi Pandit
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. I wanted a view like a webview, so modified ScrollView and it worked well for me. But this may not suit your needs.
我有你的问题的解决方案。您可以检查 ScrollView 代码,它只处理垂直滚动并忽略水平滚动并修改它。我想要一个像 webview 这样的视图,所以修改了 ScrollView 并且它对我来说效果很好。但这可能不适合您的需求。
Let me know what kind of UI you are targeting for.
让我知道你的目标是什么类型的用户界面。
Regards,
问候,
Ravi Pandit
拉维·潘迪特
回答by Eriatolc
Playing with the code, you can put an HorizontalScrollView into an ScrollView. Thereby, you can have the two scroll method in the same view.
使用代码,您可以将 HorizontalScrollView 放入 ScrollView。因此,您可以在同一个视图中使用两个滚动方法。
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.
我希望这可以帮助你。