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

来源:互联网 发布:c语言表白情书作品 编辑:程序博客网 时间:2024/05/17 08:08

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

阅读全文
0 0
原创粉丝点击