我有一个用于测试目的的网页(https://storage.googleapis.com/htmltestingbucket/nested_scroll_helper.html),只打印html在固定标题中捕获的滚动事件的计数器
当Android WebView是片段中唯一可滚动的元素时,一切都很好,WebView将滚动事件发送到页面
如果我想在WebView的上方和下方添加原生元素,那么事情会变得复杂得多。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="SOMETHING ABOVE THE WEBVIEW" />
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="SOMETHING BELOW THE WEBVIEW" />
</LinearLayout>
</ScrollView>
我知道在ScrollView中使用WebView并不好,但我必须在html文档中提供混合内容和正确滚动事件的单一滚动体验。 我发现了很多关于此事的问题,但我能够创建一个完整的端到端解决方案
另外,我知道lint对此进行了官方检查:
NestedScrolling ---------------摘要:嵌套滚动小部件
优先级:7/10严重性:警告类别:正确性
滚动窗口小部件(如ScrollView)不应包含任何嵌套 滚动小部件,因为它有各种可用性问题
然而,我无法在原生中实现Web视图内容,因此我需要另一种方法来实现
答案 0 :(得分:1)
要将Webview保留在scrollview中,您需要测量webview的高度并将其设置为布局参数。
在这里,我试图为可滚动的webview提供答案。
<ScrollView
android:layout_width="fill_parent" android:background="#FF744931"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="WebViewLayout">
<TextView
android:id="@+id/txtVoiceSeachQuery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF0000"
android:textSize="26sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="SOMETHING ABOVE THE WEBVIEW" />
<com.example.ScrollableWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:isWebViewInsideScroll="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="SOMETHING BELOW THE WEBVIEW" />
</LinearLayout>
</ScrollView>
<强> RES /值/ attrs.xml 强>
添加自定义控件的属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ScrollableWebView">
<attr name="isWebViewInsideScroll" format="boolean"></attr>
</declare-styleable>
</resources>
<强> ScrollableWebView 强>
public class ScrollableWebView extends WebView {
private boolean webViewInsideScroll = true;
public static final String RESOURCE_NAMESPACE = "http://schemas.android.com/apk/res-auto";
public ScrollableWebView(Context context) {
super(context);
}
public ScrollableWebView(Context context, AttributeSet attrs) {
super(context, attrs);
setWebViewInsideScroll(attrs.getAttributeBooleanValue
(RESOURCE_NAMESPACE, "isWebViewInsideScroll", true));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isWebViewInsideScroll()) {
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
setLayoutParams(params);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public boolean isWebViewInsideScroll() {
return webViewInsideScroll;
}
public void setWebViewInsideScroll(boolean webViewInsideScroll) {
this.webViewInsideScroll = webViewInsideScroll;
}
}
要获取属性值,您也可以使用Stylable,但这里我没有使用它。
ScrollableWebView webview = (ScrollableWebView) findViewById(R.id.webview);
webview.loadUrl("https://storage.googleapis.com/htmltestingbucket/nested_scroll_helper.html");
以下是输出链接
如果您不想创建属性文件&amp;在res / values / attrs.xml中添加自定义属性,而不是忽略该文件&amp;检查this pastebin这里我没有任何自定义属性,如isWebViewInsideScroll
。你也可以从xml布局中删除它。
如果有的话,请告诉我。
答案 1 :(得分:0)
如果您将webview放在scrollview中,则不会获得html滚动效果,因为您的webview内容不会滚动(它将在scrollview内部完全延长。)
要满足您在上方和下方放置元素的需要,您可以收听webview滚动并使用DragViewHelper
或nineoldandroids
移动header
和footer
,以便用户认为,他们是单个元素(你不需要scrollview)。
webView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
ViewHelper.setTranslationY(headerTextView, -event.getY());
}
});
public class ObservableWebView extends WebView {
private OnScrollChangeListener onScrollChangeListener;
public ObservableWebView(Context context) {
super(context);
}
public ObservableWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ObservableWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (onScrollChangeListener != null) {
onScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
}
}
public void setOnScrollChangeListener(OnScrollChangeListener onScrollChangeListener) {
this.onScrollChangeListener = onScrollChangeListener;
}
public OnScrollChangeListener getOnScrollChangeListener() {
return onScrollChangeListener;
}
public interface OnScrollChangeListener {
/**
* Called when the scroll position of a view changes.
*
* @param v The view whose scroll position has changed.
* @param scrollX Current horizontal scroll origin.
* @param scrollY Current vertical scroll origin.
* @param oldScrollX Previous horizontal scroll origin.
* @param oldScrollY Previous vertical scroll origin.
*/
void onScrollChange(WebView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
}
}
此示例可帮助您隐藏header
,我使用nineoldandroid
答案 2 :(得分:0)
实际上将可滚动视图放入另一个视图并不是那么好。试着用这个:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
并且
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
答案 3 :(得分:0)
我能找到处理这个问题的最优雅方式如下: - 收听SrollView滚动:您可以使用ObservableScrollView或从API级别23调用setOnScrollChangeListener() - 以像素为单位计算滚动Y偏移量 - 调用WebView.evaluateJavascript() - 传递滚动事件的所有细节 所以一般概念是通过: “(文档)$ .trigger( '滚动');”作为第一个param evaluateJavascript
我仍在测试细节并解决问题,但它似乎是更好的方法,我将尝试编辑这个答案,我解决这个问题的更多信息
如果有更好的解决方案,我希望听到它
答案 4 :(得分:0)
我最近遇到同样的问题,我在这里找到了你的帖子:)
我有一个WebView
嵌套在ScrollVIew
中。我加载到WebView
的页面在滚动到结尾时需要调用JS函数,但在滚动视图中,网页的window.onscroll = functionXXX() {}
永远不会被调用。
最后,我必须将OnScrollListener
设置为ScrollView
,并通过以下代码手动调用我的JS函数
@Override
public void onScroll(int scrollY) {
if (!scrollView.canScrollVertically(scrollY)) {
mWebView.loadUrl("javascript:functionXXX();");
}
}
也许我们的情况不同,但我希望它会给你一些灵感:)