本文共 8808 字,大约阅读时间需要 29 分钟。
公司年底赶一个APP,五个tab,每个tab都放一个h5链接,于是用了viewpager+tablayout+fragment+webview,又要求首页有下拉刷新,以为很简单,就用常用的下拉刷新框架试了试,见了鬼了,放入一般网上的h5链接是正常的,一放入公司的h5就是一片空白,马上换一个框架再试,还是一样,懵逼了,这是怎么回事。本着能用别人的绝不自己写的原则,又找了一圈,终于找到了,顺便说下,这个框架的webview下拉刷新没看到scrollview的影子,不像其他框架都用了scrollview,直接用的是viewgroup,我感觉这是它能奏效的原因。这就是。
使用方法:
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:
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、刷新头布局文件:
这个刷新头,我只在初始化的时候加载了一张gif图片,其他回调方法都没加入任何方法,这样下拉刷新的时候就是全程一直播放一张gif图片了,不管是下拉的时候还是刷新的时候。
PS:后续发现一个问题,部分h5页面在webview往下滑动后再往上滑,滑不动了,一滑就直接露出刷新头,网上找到一篇文章解决了这个问题:
重写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就可以了。
转载地址:http://nlrki.baihongyu.com/