android webview+fragment下拉刷新框架推荐

        公司年底赶一个APP,五个tab,每个tab都放一个h5链接,于是用了viewpager+tablayout+fragment+webview,又要求首页有下拉刷新,以为很简单,就用常用的下拉刷新框架试了试,见了鬼了,放入一般网上的h5链接是正常的,一放入公司的h5就是一片空白,马上换一个框架再试,还是一样,懵逼了,这是怎么回事。本着能用别人的绝不自己写的原则,又找了一圈,终于找到了,顺便说下,这个框架的webview下拉刷新没看到scrollview的影子,不像其他框架都用了scrollview,直接用的是viewgroup,我感觉这是它能奏效的原因。这就是android-Ultra-Pull-To-Refresh

        使用方法:

1、根build.gradle:

mavenCentral()
maven {
    url 'https://oss.sonatype.org/content/repositories/snapshots'
}

2、app模块build.gradle:

implementation 'in.srain.cube:ultra-ptr:1.0.11'

3、布局文件fragment_home.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <in.srain.cube.views.ptr.PtrClassicFrameLayout
        android:id="@+id/rotate_header_web_view_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#f1f1f1"
        app:ptr_duration_to_close="200"
        app:ptr_duration_to_close_header="1000"
        app:ptr_keep_header_when_refresh="true"
        app:ptr_pull_to_fresh="false"
        app:ptr_ratio_of_header_height_to_refresh="1.2"
        app:ptr_resistance="1.7">

        <WebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </in.srain.cube.views.ptr.PtrClassicFrameLayout>

</LinearLayout>

4、fragment代码:

    private View view;
    private PtrClassicFrameLayout mPtrFrame;
    private WebView webView;
    private boolean mCanRefresh = true;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (view == null) {
            view = inflater.inflate(R.layout.fragment_home, container, false);
            webView = view.findViewById(R.id.webview);
            initWebView();
            mPtrFrame = view.findViewById(R.id.rotate_header_web_view_frame);

            LoadingHeader header = new LoadingHeader(getContext());
            mPtrFrame.setHeaderView(header);
            mPtrFrame.addPtrUIHandler(header);

            mPtrFrame.setPtrHandler(new PtrHandler() {
                @Override
                public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                    return PtrDefaultHandler.checkContentCanBePulledDown(frame, webView, header) && mCanRefresh;
                }

                @Override
                public void onRefreshBegin(PtrFrameLayout frame) {
                    webView.loadUrl("file:///android_asset/web/index.html");
                }
            });
            mPtrFrame.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mPtrFrame.autoRefresh();
                }
            }, 100);
        }
        return view;
    }

    protected void initWebView() {
        webView.getSettings().setJavaScriptEnabled(true);
//        webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        //优先使用网络
        webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        //将图片调整到适合webview的大小
        webView.getSettings().setUseWideViewPort(true);
        //支持内容重新布局
        webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        //支持自动加载图片
        webView.getSettings().setLoadsImagesAutomatically(true);
        //当webview调用requestFocus时为webview设置节点
        webView.getSettings().setNeedInitialFocus(true);
        //自适应屏幕
        webView.getSettings().setUseWideViewPort(true);
        webView.getSettings().setLoadWithOverviewMode(true);
        //开启DOM storage API功能(HTML5 提供的一种标准的接口,主要将键值对存储在本地,在页面加载完毕后可以通过 javascript 来操作这些数据。)
        webView.getSettings().setDomStorageEnabled(true);
        //支持缩放
        webView.getSettings().setBuiltInZoomControls(true);
        webView.getSettings().setSupportZoom(true);

        //允许webview对文件的操作
        webView.getSettings().setAllowFileAccess(true);
        webView.getSettings().setAllowFileAccessFromFileURLs(true);
        webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

        webView.requestFocusFromTouch();
        webView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { // 表示按返回键时的操作
                        webView.goBack(); // 后退
                        // webview.goForward();//前进
                        return true; // 已处理
                    } else if (keyCode == KeyEvent.KEYCODE_BACK) {
                        getActivity().moveTaskToBack(true);
                    }
                }
                return false;
            }
        });
        webView.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                webView.loadUrl(url);
                return true;
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                if (url.equals("file:///android_asset/web/index.html#/")) {
                    mCanRefresh = true;
                } else {
                    mCanRefresh = false;
                }
                mPtrFrame.refreshComplete();
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }
        });
    }

代码虽然有点长,不过还好理解,简单说明一下,LoadingHeader是自定义的刷新头,如果不需要自定义,这里就不用加入,下面都是webview的基本设置就没什么好讲的了。下面继续贴自定义刷新头的代码:

5、自定义刷新头:


import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.bumptech.glide.Glide;

import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrUIHandler;
import in.srain.cube.views.ptr.indicator.PtrIndicator;

public class LoadingHeader extends FrameLayout implements PtrUIHandler {

    private ImageView imageView;
    private View view;

    public LoadingHeader(@NonNull Context context) {
        this(context, null);
    }

    public LoadingHeader(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoadingHeader(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        view = LayoutInflater.from(getContext()).inflate(R.layout.layout_header_refresh, this, false);
        addView(view);
        imageView = view.findViewById(R.id.iv_refresh);
        Glide.with(getContext()).load(R.drawable.homegif).asGif().into(imageView);
    }

    @Override
    public void onUIReset(PtrFrameLayout frame) {
        //重置
    }

    @Override
    public void onUIRefreshPrepare(PtrFrameLayout frame) {
        //准备刷新
    }

    @Override
    public void onUIRefreshBegin(PtrFrameLayout frame) {
        //开始刷新 显示刷新进度跟文本
    }

    @Override
    public void onUIRefreshComplete(PtrFrameLayout frame) {
        //刷新完成
    }

    @Override
    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {
        final int mOffsetToRefresh = frame.getOffsetToRefresh();
        final int currentPos = ptrIndicator.getCurrentPosY();
        final int lastPos = ptrIndicator.getLastPosY();

        if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) {
            //未到达刷新线
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {

            }
        } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) {
            //到达或超过刷新线
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {

            }
        }
    }
}

这里用到了glide,需要自己另外导入框架:

implementation 'com.github.bumptech.glide:glide:3.7.0'

6、刷新头布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    android:background="#f1f1f1">

    <ImageView
        android:id="@+id/iv_refresh"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerInParent="true" />
</RelativeLayout>

这个刷新头,我只在初始化的时候加载了一张gif图片,其他回调方法都没加入任何方法,这样下拉刷新的时候就是全程一直播放一张gif图片了,不管是下拉的时候还是刷新的时候。

PS:后续发现一个问题,部分h5页面在webview往下滑动后再往上滑,滑不动了,一滑就直接露出刷新头,网上找到一篇文章https://www.2cto.com/kf/201803/734502.html解决了这个问题:

重写WebView:

public class MyWebView extends WebView {
    public MyWebView(Context context) {
        super(context);
    }

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

    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (this.getScrollY() <= 0)
                    this.scrollTo(0, 1);
                break;
            case MotionEvent.ACTION_UP:
                //                if(this.getScrollY() == 0)
                //                this.scrollTo(0,-1);
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean canScrollVertically(int direction) {
        return direction < 0 ? getScrollY() > 0 : getScrollY() < getMeasuredHeight();
    }
}

把系统WebView替换成这个MyWebView就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值