Android WebView inside ScrollView仅滚动scrollview

iqjalb3h  于 2023-06-04  发布在  Android
关注(0)|答案(8)|浏览(158)

在我的应用程序中,我有一个ScrollView,其中包含一些线性视图,一些文本视图和一个Webview,然后是其他线性布局等。问题是WebView不滚动。Scroll仅侦听ScrollView。有什么建议吗??

<ScrollView >
    <TextView />
    <WebView />              <-- this does not scroll
    <TextView />
</ScrollView >
vnjpjtjt

vnjpjtjt1#

这是解决方案。在网上找到的。我已经子类化了WebView,并使用requestDisallowInterceptTouchEvent(true);方法来允许我的Webview处理滚动事件。
TouchyWebView.java

package com.mypackage.common.custom.android.widgets

public class TouchyWebView extends WebView {

    public TouchyWebView(Context context) {
        super(context);
    }

    public TouchyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(event);
    }          
}

在layout.xml中

<com.mypackage.common.custom.android.widgets.TouchyWebView 
                android:id="@+id/description_web"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 />
1rhkuytd

1rhkuytd2#

@panos提供的解决方案可以工作,但在与ScrollView一起使用时仍然存在问题。下面的增强版本克服了这个问题。

public class TouchyWebView extends WebView {

    public TouchyWebView(Context context) {
        super(context);
    }

    public TouchyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

     @Override
     public boolean onTouchEvent(MotionEvent event) {
         //Check is required to prevent crash
         if (MotionEventCompat.findPointerIndex(event, 0) == -1) {
         return super.onTouchEvent(event);
         }

         if (event.getPointerCount() >= 2) {
             requestDisallowInterceptTouchEvent(true);
         } else {
             requestDisallowInterceptTouchEvent(false);
         }

         return super.onTouchEvent(event);
    }

    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
        requestDisallowInterceptTouchEvent(true);
    }

}

此外,您可能希望为TouchyWebView设置以下设置。

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
5anewei6

5anewei63#

Panos解决方案对我来说已经足够了,只有一个例外...我的固定高度(200 dp)WebView可能是空的,或者可能已经加载了很多内容。因此,它可能是或可能不是可滚动的“本身”。Panos解决方案总是消耗MotionEvent s,所以当WebView为空,用户触摸WebView并尝试滚动时,WebView将不会滚动(因为没有内容),并且可滚动的父级也会导致WebView“吞下”MotionEvent-所以什么都不会发生。我为预期行为添加了一个小的if语句:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(computeVerticalScrollRange() > getMeasuredHeight())
        requestDisallowInterceptTouchEvent(true);
    return super.onTouchEvent(event);
}
  • WebView为空且不可垂直滚动时,则computeVerticalScrollRange() == getMeasuredHeight()
  • WebView的内容长于其高度(可滚动)时,则computeVerticalScrollRange() > getMeasuredHeight()
nxagd54h

nxagd54h4#

使用@Panos和@Dipendra的解决方案,我仍然对滚动视图中的mapview有一些问题。它不会一致地垂直滚动,这些方法被弃用,所以我想出了这个技巧,我在scrollviews内部使用mapview,效果很好。我希望这可以帮助你们中的一些人。

public class TouchyWebView extends WebView {
ViewParent mViewParent;

public TouchyWebView(Context context) {
    super(context);
}

public TouchyWebView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
    mViewParent = viewParent;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_UP:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(false);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(false);
            }
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    requestDisallowInterceptTouchEvent(true);

}

}
我还遵循了@Dipendra关于设置控件的建议。

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
70gysomp

70gysomp5#

只需在类文件中添加一行即可

mWebview.setNestedScrollingEnabled(true);

或者在XML中添加Webview标签

android:nestedScrollingEnabled="true"

警告:仅适用于API 21和21+

pes8fvy9

pes8fvy97#

我觉得这样更舒服。

public class NestedWebView extends WebView implements NestedScrollingChild {
private final String TAG = getClass().getSimpleName();
private NestedScrollingChildHelper mChildHeper;

public NestedWebView(@NonNull Context context) {
    super(context);
    mChildHeper=new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}
public NestedWebView(@NonNull Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    mChildHeper=new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}
public NestedWebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mChildHeper=new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}
public NestedWebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    mChildHeper=new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
    return super.onTouchEvent(event);
}
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    stopNestedScroll();
}
@Override
public void stopNestedScroll() {
    super.stopNestedScroll();
}
@Override
public boolean startNestedScroll(int axes) {
    return super.startNestedScroll(axes);
}
@Override
public void setNestedScrollingEnabled(boolean enabled) {
    super.setNestedScrollingEnabled(enabled);
}

}

fcy6dtqo

fcy6dtqo8#

您可以更改为3种布局:
1.第一个TextView -标题

  1. WebView -主布局
  2. Second TextView - footer
WebView web = (WebView) findViewById(R.id.webView);
View header = getLayoutInflater().inflate(R.layout.header_layout, null);
View footer = getLayoutInflater().inflate(R.layout.foorer_layout, null);
web.addHeaderView(headerComment);
web.addFooterView(footerComment);

相关问题