我真的很累寻找一个垂直和水平滚动视图的解决方案。
我读到在框架中没有任何视图/布局来实现这个特性,但是我需要这样的东西:
我需要定义一个布局在其他,子布局必须实现滚动垂直/水平移动。
最初实现了一个按像素移动布局像素的代码,但我认为这不是正确的方法。 我用 ScrollView 和水平 ScrollView 尝试过,但是没有什么能像我想要的那样工作,因为它只实现了垂直或水平滚动。
Canvas 不是我的解决方案,因为我需要在别人的子元素中附加侦听器。
我能做什么?
选项 # 1: 您可以想出一个新的 UI 设计,不需要同时进行水平和垂直滚动。
选项 # 2: 您可以获得 ScrollView和 HorizontalScrollView的源代码,了解核心 Android 团队是如何实现这些代码的,并创建自己的 BiDirectionalScrollView实现。
ScrollView
HorizontalScrollView
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);
解决方案: 将第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>
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>