公司年底赶一个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就可以了。