我想有一個線性佈局,頂部的標題部分和下面的web視圖。標題會很短,並且網頁視圖可能比屏幕更長更寬。兩個方向滾動視圖
什麼是獲得水平和垂直滾動的最佳方式是什麼?一個ScrollView嵌套在HorizontalScrollView裏面是個好主意嗎?
我想有一個線性佈局,頂部的標題部分和下面的web視圖。標題會很短,並且網頁視圖可能比屏幕更長更寬。兩個方向滾動視圖
什麼是獲得水平和垂直滾動的最佳方式是什麼?一個ScrollView嵌套在HorizontalScrollView裏面是個好主意嗎?
ScrollView嵌套在HorizontalScrollView裏面是個好主意嗎?
是的,沒有。
是的,我的理解是ScrollView
和HorizontalScrollView
可以嵌套。
不,AFAIK,既不ScrollView
也不HorizontalScrollView
與WebView
一起工作。
我建議你的WebView
適合在屏幕上。
我知道你已經接受了你的答案,但可能是這可能會給你一些想法。
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<HorizontalScrollView
android:layout_alignParentBottom="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView
android:src="@drawable/device_wall"
android:scaleType="center"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</HorizontalScrollView>
</RelativeLayout>
</LinearLayout>
</ScrollView>
看起來像*「ScrollView嵌套在裏面一個HorizontalScrollView「*。有什麼我失蹤? – 2010-12-28 17:11:13
是的,在這個解決方案中LinearLayout和RelativeLayout在做什麼?除非他們提供某種不明原因的目的,否則應該刪除它們以保持視圖層次儘可能平坦。 – SilithCrowe 2012-02-28 15:55:26
兩年進一步向下行,我認爲開源社區可能必須拯救你: 2D Scroll View。
編輯:該鏈接不再工作,但here is a link to an old version of the blogpost;
還有另一種方法。 moddified HorizontalScrollView作爲包裝ScrollView。正常HorizontalScrollView當捕捉觸摸事件不轉發他們到ScrollView,你只能在一次滾動的方式。這裏是解決方案:
package your.package;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.view.MotionEvent;
import android.content.Context;
import android.util.AttributeSet;
public class WScrollView extends HorizontalScrollView
{
public ScrollView sv;
public WScrollView(Context context)
{
super(context);
}
public WScrollView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public WScrollView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override public boolean onTouchEvent(MotionEvent event)
{
boolean ret = super.onTouchEvent(event);
ret = ret | sv.onTouchEvent(event);
return ret;
}
@Override public boolean onInterceptTouchEvent(MotionEvent event)
{
boolean ret = super.onInterceptTouchEvent(event);
ret = ret | sv.onInterceptTouchEvent(event);
return ret;
}
}
使用:
@Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/*BIDIRECTIONAL SCROLLVIEW*/
ScrollView sv = new ScrollView(this);
WScrollView hsv = new WScrollView(this);
hsv.sv = sv;
/*END OF BIDIRECTIONAL SCROLLVIEW*/
RelativeLayout rl = new RelativeLayout(this);
rl.setBackgroundColor(0xFF0000FF);
sv.addView(rl, new LayoutParams(500, 500));
hsv.addView(sv, new LayoutParams(WRAP_CONTENT, MATCH_PARENT /*or FILL_PARENT if API < 8*/));
setContentView(hsv);
}
有趣的是,垂直滾動不再起作用。 – 2011-12-30 16:01:05
我可以確認這個工作正常!在我的版本中,我有一個包含嵌套的X和Y滾動的視圖。我重寫視圖的'onTouchEvent'和'onInterceptTouchEvent'並將MotionEvent對象轉發到兩個滾動視圖,就像本答案中所述。順利的體驗,雙向。 – sulai 2012-11-21 12:11:57
爲了使它工作,我必須調整onTouchEvent以始終調用sv.onTouchEvent,並將返回值修改爲true。還要注意,你必須擴展外部視圖。在我的情況下,我有一個horizontalScrollView嵌套在(垂直)ScrollView中,所以我不得不延長垂直的。 – jeroent 2013-04-23 14:59:09
有一個簡單的解決方法: 在你的活動得到外部滾動視圖的引用(我要去承擔一個垂直滾動型)和引用該滾動視圖的第一個孩子。
Scrollview scrollY = (ScrollView)findViewById(R.id.scrollY);
LinearLayout scrollYChild = (LinearLayout)findViewById(R.id.scrollYChild);
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
scrollYChild.dispatchTouchEvent(event);
scrollY.onTouchEvent(event);
return true;
}
有人可能會爭辯說,這個解決方案有點怪異。但它在多個應用程序中對我非常有用!
我搜索真的很長,使這項工作,並最終在這裏找到這個線程。 wasikuss' answer與解決方案非常接近,但仍無法正常工作。這是它的工作原理(至少對我來說(Android 2.3.7))。我希望,它也適用於任何其他Android版本。
創建一個名爲VScrollView類:
package your.package.name;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
public class VScrollView extends ScrollView {
public HorizontalScrollView sv;
public VScrollView(Context context) {
super(context);
}
public VScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
sv.dispatchTouchEvent(event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
super.onInterceptTouchEvent(event);
sv.onInterceptTouchEvent(event);
return true;
}
}
您的佈局應是這樣的:
<your.package.name.VScrollView
android:id="@+id/scrollVertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<HorizontalScrollView
android:id="@+id/scrollHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TableLayout
android:id="@+id/table"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:stretchColumns="*" >
</TableLayout>
</HorizontalScrollView>
</your.package.name.VScrollView>
在你的活動,你應該這樣做:
hScroll = (HorizontalScrollView) findViewById(R.id.scrollHorizontal);
vScroll = (VScrollView) findViewById(R.id.scrollVertical);
vScroll.sv = hScroll;
。 ..這就是它的工作原理。至少對於我來說。
這是否支持對角線滾動? – 2014-03-29 01:36:23
遲到回答,但希望對某人有所幫助。 您可以檢出droid-uiscrollview。這很大程度上取決於@MrCeeJ's的答案,但我似乎在獲取實際內容的過程中遇到了很多麻煩。因此,我從HorizontalScrollView & ScrollView中抽取最新來源以創建droid-uiscrollview。有幾個todo's
左我還沒有得到解決,以完成,但它確實在同一時間
我已經嘗試兩個wasikuss和user1684030解決方案和我垂直足以讓內容滾動兩個水平&必須修改它們,因爲有一個警告日誌:HorizontalScrollView: Invalid pointerId=-1 in onTouchEvent
,因爲我不喜歡創建2個滾動視圖的需要。
因此,這裏是我的課:
public class ScrollView2D extends ScrollView {
private HorizontalScrollView innerScrollView;
public ScrollView2D(Context context) {
super(context);
addInnerScrollView(context);
}
public ScrollView2D(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() == 1) {
View subView = getChildAt(0);
removeViewAt(0);
addInnerScrollView(getContext());
this.innerScrollView.addView(subView);
} else {
addInnerScrollView(getContext());
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean handled = super.onTouchEvent(event);
handled |= this.innerScrollView.dispatchTouchEvent(event);
return handled;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
super.onInterceptTouchEvent(event);
return true;
}
public void setContent(View content) {
if (content != null) {
this.innerScrollView.addView(content);
}
}
private void addInnerScrollView(Context context) {
this.innerScrollView = new HorizontalScrollView(context);
this.innerScrollView.setHorizontalScrollBarEnabled(false);
addView(this.innerScrollView);
}
}
而且在XML使用它時,你什麼都沒有,如果這個滾動視圖的內容設置在這裏做。否則,您只需調用方法setContent(View content)
即可讓此ScrollView2D
知道其內容。
例如:
// Get or create a ScrollView2D.
ScrollView2D scrollView2D = new ScrollView2D(getContext());
scrollView2D.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(scrollView2D);
// Set the content of scrollView2D.
RelativeLayout testView = new RelativeLayout(getContext());
testView.setBackgroundColor(0xff0000ff);
testView.setLayoutParams(new ViewGroup.LayoutParams(2000, 2000));
scrollView2D.setContent(testView);
有一段時間我一直在試圖從這裏的解決方案,但效果最好仍是一個有一個問題:它吃的所有事件中,沒有內使它通過對元素滾輪。
所以我有......另一個答案,在Github上和良好註釋至少希望:https://github.com/Wilm0r/giggity/blob/master/app/src/main/java/net/gaast/giggity/NestedScroller.java
像所有的解決方案,這是一個嵌套的HorizontalScrollview(外)+滾動型(內),與來自Android的外部接收觸摸事件,並且內部僅從外部視圖內部接收它們。
然而,我依靠ScrollViews來決定觸摸事件是否有趣,直到他們接受它,不做任何事情,因此觸摸(即點擊打開鏈接/等)仍然可以使它成爲子元素。
(此視圖支持捏縮放我需要的。)
在外卷軸:這裏
@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
if (super.onInterceptTouchEvent(event) || vscroll.onInterceptTouchEventInt(event)) {
onTouchEvent(event);
return true;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
super.onTouchEvent(event);
/* Beware: One ugliness of passing on events like this is that normally a ScrollView will
do transformation of the event coordinates which we're not doing here, mostly because
things work well enough without doing that.
For events that we pass through to the child view, transformation *will* happen (because
we're completely ignoring those and let the (H)ScrollView do the transformation for us).
*/
vscroll.onTouchEventInt(event);
return true;
}
VSCROLL是「InnerScroller」,從滾動型的子類,具有事件處理的幾個變化:我已經做了一些可怕的事情,直接確保收到的觸摸事件在Android被丟棄,而是隻需要把他們從外部類 - 然後才傳給那些對超:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
/* All touch events should come in via the outer horizontal scroller (using the Int
functions below). If Android tries to send them here directly, reject. */
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
/* It will still try to send them anyway if it can't find any interested child elements.
Reject it harder (but pretend that we took it). */
return true;
}
public boolean onInterceptTouchEventInt(MotionEvent event) {
return super.onInterceptTouchEvent(event);
}
public boolean onTouchEventInt(MotionEvent event) {
super.onTouchEvent(event);
}
請在這裏將您的github的一些相關代碼添加到您的答案中。 – 2016-07-09 19:58:13
我可以肯定地說,一個滾動型和HorizontalScrollView可以,因爲我已經被嵌套完成它,但用戶體驗很差,因爲它可能是困難的很難讓它向您想要的方向滾動,並且沒有對角線解釋 - 您可以獲得所有垂直或全部水平移動。 – Blumer 2010-10-05 19:21:37
「讓您的WebView適合屏幕。」不幸的是,我沒有辦法做到這一點:( – 2010-10-05 19:26:24
@Blumer我注意到了。這對我來說是可以接受的,但並不是最佳的。 – 2010-10-05 19:27:38