您的位置:首页 > 移动开发

Android WebView上滑隐藏头部,下滑显示头部

2017-11-24 15:55 483 查看
UC浏览器屏幕截图



如何实现这种webView上下滑显示隐藏头部,相信很多会想到CoordinatorLayout+Toolbar,那我们先用这种方案来实现一下。

添加依赖 compile ‘com.android.support:design:24.0.0-alpha1’

该方案主要实现来自布局,而Activity中只是将WebView加载出来

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:background="@color/colorAccent"
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetEnd="0dp"
app:contentInsetLeft="0dp"
app:contentInsetRight="0dp"
app:contentInsetStart="0dp"
app:layout_scrollFlags="scroll|enterAlways">

<include layout="@layout/include_title"/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>


Activity:

package com.titlewebview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import butterknife.Bind;
import butterknife.ButterKnife;
public class ToolBarWebActivity extends AppCompatActivity {
@Bind(R.id.webview)
WebView webView;
String url="http://m.sohu.com/ch/8?pvid=000115_3w_c";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar_web);
ButterKnife.bind(this);
initWebView();
}
/**
* 初始化WebView的配置
*
*/
private void initWebView() {
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
webView.loadUrl(url);
}
}


运行后效果:



不看仔细的话,差点都以为自己实现了有木有QAQ !!!

于是我们发现了各种各样的bug,比如在这个链接里,

1,用浏览器打开,发现webView里自带的头部是固定不动,而不是跟着页面滑动一起滑动。

2,在设置支持缩放的情况下,斜向(左上右下,左下右上)拉伸,页面几乎没变化,要水平左右拉开收拢,才能明显看到页面放大缩小

3,在一些原本就有滑到底部翻页效果的webView中,到了底部刷不出下一页



综上,我们很容易分析得出,嵌套过程中,webView本身的滑动事件被取缔了。

我的解决方案是,不要用带滑动的控件去嵌套webView,鬼知道这个webview里做了哪些手势操作,我们需要把所有的手势都让给webview。

于是乎,我百度监听webView滑动,搜到这样一篇文章

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0716/3192.html

摸出一个带滑动监听回调的webView(其实只是重写//重写onScrollChanged)

import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;

/**
* Created by KID on 2017/11/14.
* 带滑动监听回调的WebView
*/

public class ScollListenWebView extends WebView  {

private OnScrollChangedCallback mOnScrollChangedCallback;

public ScollListenWebView(final Context context) {
super(context);
}

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

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

//重写onScrollChanged
@Override
protected void onScrollChanged(final int l, final int t, final int oldl,
final int oldt) {
super.onScrollChanged(l, t, oldl, oldt);

if (mOnScrollChangedCallback != null) {
mOnScrollChangedCallback.onScroll(l - oldl, t - oldt);
}
}

public OnScrollChangedCallback getOnScrollChangedCallback() {
return mOnScrollChangedCallback;
}

public void setOnScrollChangedCallback(
final OnScrollChangedCallback onScrollChangedCallback) {
mOnScrollChangedCallback = onScrollChangedCallback;
}
/**
* Impliment in the activity/fragment/view that you want to listen to the webview
*/
public static interface OnScrollChangedCallback {
public void onScroll(int dx, int dy);
}
}


然后在监听到webView上滑,下滑的过程中,让头部去上下滑动就可以了。

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.OverScroller;

public class WebLayout extends LinearLayout {
private View mTop;
private LinearLayout ll_dynamic_web;
private int mTopViewHeight;
private OverScroller mScroller;
public WebLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);
mScroller = new OverScroller(context);
}

@Override
protected void onFinishInflate()
{
super.onFinishInflate();
//这个id必须能找到
mTop = findViewById(R.id.rl_web_head);
ll_dynamic_web = findViewById(R.id.ll_dynamic_web);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//不限制顶部的高度
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
ViewGroup.LayoutParams params = ll_dynamic_web.getLayoutParams();
params.height = getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight()+ ll_dynamic_web.getMeasuredHeight());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mTopViewHeight = mTop.getMeasuredHeight();
}
@Override
public void scrollTo(int x, int y)
{
if (y < 0)
{
y = 0;
}
if (y > mTopViewHeight)
{
y = mTopViewHeight;
}
if (y != getScrollY())
{
super.scrollTo(x, y);
}
}
@Override
public void computeScroll()
{
if (mScroller.computeScrollOffset())
{
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}
}


布局

<?xml version="1.0" encoding="utf-8"?>
<com.titlewebview.WebLayout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/weblayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include layout="@layout/include_title"/>
<LinearLayout
android:id="@+id/ll_dynamic_web"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<com.titlewebview.ScollListenWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</LinearLayout>
</com.titlewebview.WebLayout>


Activity

package com.titlewebview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import butterknife.Bind;
import butterknife.ButterKnife;

public class ScrollListenActivity extends AppCompatActivity {

@Bind(R.id.weblayout)
WebLayout weblayout;
@Bind(R.id.webview)
ScollListenWebView webView;

String url="http://m.sohu.com/ch/8?pvid=000115_3w_c";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scroll_listen);
ButterKnife.bind(this);

setScollListener();
initWebView();

}
private void setScollListener() {
webView.setOnScrollChangedCallback(new ScollListenWebView.OnScrollChangedCallback() {
@Override
public void onScroll(int dx, int dy) {
weblayout.scrollBy(0,dy);
}
});
}
/**
* 初始化WebView的配置
*
*/
private void initWebView() {
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//处理重定向
return false;
}
});
//调用loadView方法为WebView加入链接
webView.loadUrl(url);
}
}


我们在webView的滑动监听回调里,让title的父view自己去滚动相对应的距离。

webView.setOnScrollChangedCallback(new ScollListenWebView.OnScrollChangedCallback() {
@Override
public void onScroll(int dx, int dy) {
weblayout.scrollBy(0,dy);
}
});


实现效果:



在打印webview的偏移量的时候dy的时候,我发现缓慢滑动过程,虽然我的意志是向下滑动的,dy应该是正数,可是打印结果还是夹杂了一些负数。脑子里想要,行为上还是要反抗一下的- -!……..所有在缓慢隐藏或者显示头部的过程中,头部会有抖动的感觉。

默念了一下女神,我做了如下骚操作

List<Integer> dys=new ArrayList<>();
webView.setOnScrollChangedCallback(new ScollListenWebView.OnScrollChangedCallback() {
@Override
public void onScroll(int dx, int dy) {
//处理屏幕滑动过程中,dy正负抖动问题
if(dys.size()>2){
if((dys.get(dys.size()-1)>0&&dys.get(dys.size()-2)>0&&dy>0)||(dys.get(dys.size()-1)<0&&dys.get(dys.size()-2)<0&&dy<0)){
weblayout.scrollBy(0,dy);
}
}
}
});


在下滑动过程中,onScroll会被调用很多次,哪怕你有那么一两下反抗变负数,大方向上你还是想下滑的。取前两次操作,如果前两次跟当前的目的一致,才去执行头部滚动。

如果你有其他骚操作,可以联系我 -_-☻!

代码地址http://download.csdn.net/download/qq_31390699/10131520
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  webview android