Closed KinaZhen closed 6 years ago
swipeback 过程,上层fragment 空白 我是上层fragment 是不可swipe
听起来是矛盾的: 滑动过程中 上层Fragment空白,说明滑动的是上层Fragment,但是上层Fragment又是不可滑动的.... 不理解
如果想禁止滑动,有2个方式:
1、setSwipeBackEnable(false)
2、不继承SwipeBackFragment/Activity
可能我表达的有问题,现在我的activity 里 有个根fragment1 , 根fragment 上start(fragment2) , 那么fragment2 swipeback 时 ,偶尔出现空白; 现在我把start(fragment2) 改成 extraTransaction().startDontHideSelf(fragment2) 则不会出现
出现空白的化,应该是在滑动开始时,上一个Fragment的View没有setVisibility(View.VISIBLE);
, 之前没有收到过相关反馈, 建议你断点调试下,是否没有调用setVisibility(View.VISIBLE);
相关代码在这里
@YoKeyword 如果是Fragment里面嵌套的webview,就不支持类似webView.goBack(),就是说在嵌套一层判断 哈哈,要求是不是有点离谱了,不过现在混合开发也蛮多的,关注中,谢谢
@Jiiiiiin 在Fragment的onBackPressedSupport()
中 判断是否webview可goBack,然后选择处理并拦截
@YoKeyword 做了,这个问题其实不是fragmentions 或者说fragment的锅,其实是安卓webview自身的锅,看知乎那个评论,大家都遇到了,而且我测了一下各大行,jbridge类型app,都存在,平安银行直接被我测挂了(白屏之后,所有webview都白),最后我写成这样了:
package cn.jiiiiiin.vplus.core.webview.util;
import android.webkit.WebView;
import com.blankj.utilcode.util.KeyboardUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.blankj.utilcode.util.ToastUtils;
import java.util.Objects;
import cn.jiiiiiin.vplus.core.app.ViewPlus;
import cn.jiiiiiin.vplus.core.util.log.LoggerProxy;
import cn.jiiiiiin.vplus.core.webview.AbstractWebViewDelegate;
import cn.jiiiiiin.vplus.core.webview.AbstractWebViewWrapperDelegate;
import cn.jiiiiiin.vplus.core.webview.WebViewDelegateImpl;
/**
* 处理webview的返回
* 处理webview容器fragment的返回
*
* @author jiiiiiin
* @version 1.0
*/
public class BackPressedHandler {
public static boolean onBack(AbstractWebViewWrapperDelegate wrapperDelegate, AbstractWebViewDelegate.ILifeCycleListener lifeCycleListener) {
LoggerProxy.d("BackPressedHandler 通用返回方法被调用");
final WebViewDelegateImpl webDelegate = wrapperDelegate.getWebDelegate();
WebView webView = null;
// webview已经“加载完毕”,这个时候才能让用户返回
try {
webView = webDelegate.getWebView();
} catch (Exception e) {
LoggerProxy.e(e, "获取webview出错");
return false;
}
if (webView != null && wrapperDelegate.isWebViewIsLoading()) {
if (webView.canGoBack()) {
LoggerProxy.d("没有初始化网页完毕,webview还可以返回,先返回看看");
webView.goBack();
} else {
ViewPlus.getHandler().postDelayed(() -> {
LoggerProxy.d("没有初始化网页完毕,但是webview已经实例化了,直接pop wrapperDelegate");
wrapperDelegate.pop();
}, 500);
}
} else if (wrapperDelegate.isShowErrorLocalPage()) {
// 如果加载的是错误页面,那么就直接弹掉页面
wrapperDelegate.setShowErrorLocalPage(false);
wrapperDelegate.pop();
// !如果是isShowErrorLocalPage那就说明是渲染了本地的错误页面,那么不需要判断webview是否可以goback
} else {
boolean lifeCycleListenerHandlerFlag = false;
if (lifeCycleListener != null) {
// 不同的webvidew dalegate可以做不同的拦截处理
lifeCycleListenerHandlerFlag = lifeCycleListener.onWebViewDelegateBackPressedSupport();
LoggerProxy.d("检查mLifeCycleListener的处理结果 %s", lifeCycleListenerHandlerFlag);
}
if (!lifeCycleListenerHandlerFlag) {
// ! 因为确认这个方法不会使用view参数
// wrapperDelegate.onClickBackBtn.onClick(null);
AbstractWebViewWrapperDelegate.ITitleBarEventListener titleBarEventListener = wrapperDelegate.getTitleBarEventListener();
// 隐藏键盘
KeyboardUtils.hideSoftInput(Objects.requireNonNull(wrapperDelegate.getActivity()));
// 隐藏所有密码键盘
wrapperDelegate.hideProgressBar();
boolean isNotidy = false;
if (titleBarEventListener != null) {
// 目前只有加载我们自身的wrapperDelegate具有该listener
// 交给前端去处理
// 标识是否通知前端【ON_HEADER_BAR_TAP_BCK_LISTENER】去处理返回点击事件
isNotidy = titleBarEventListener.onBackBtnClick();
}
if (!isNotidy) {
if (webView != null && webView.canGoBack()) {
webView.goBack();
} else {
wrapperDelegate.pop();
}
}
} else {
LoggerProxy.d("mLifeCycleListener 已经自己处理了返回事件");
}
}
return true;
}
}
代码可能看起来很丑,但是我们的返回确实有太多东西需要处理,关键的代码就是:
public static boolean onBack(AbstractWebViewWrapperDelegate wrapperDelegate, AbstractWebViewDelegate.ILifeCycleListener lifeCycleListener) {
LoggerProxy.d("BackPressedHandler 通用返回方法被调用");
final WebViewDelegateImpl webDelegate = wrapperDelegate.getWebDelegate();
WebView webView = null;
// webview已经“加载完毕”,这个时候才能让用户返回
try {
webView = webDelegate.getWebView();
} catch (Exception e) {
LoggerProxy.e(e, "获取webview出错");
return false;
}
if (webView != null && wrapperDelegate.isWebViewIsLoading()) {
// 这里检测webview还没有【跑完,这里就有多种情况,其中最关键的就是WebViewClient:onPageStarted开始标记,WebChromeClient:onProgressChanged的prosgess第一次,注意是第一次到100,则标记完成,这个标记就是wrapperDelegate.isWebViewIsLoading,当然还有很多比如WebChromeClient中的错误、协议拦截等等标记为完成】,如果在没有完成的时候,用户强行返回,那个webview的bug就来了,百发百中,即只要一白全白,只能杀掉进程,我的处理是postDelayed延缓一下,当然这里就要看前端页面的响应速度了,也就是,问题的关键只能去优化前端,其实最后我观察:招商银行、微众银行....都是这样处理,平安仗着自己前端快很难点出来,一出来也是一个鸟样。
if (webView.canGoBack()) {
LoggerProxy.d("没有初始化网页完毕,webview还可以返回,先返回看看");
webView.goBack();
} else {
ViewPlus.getHandler().postDelayed(() -> {
LoggerProxy.d("没有初始化网页完毕,但是webview已经实例化了,直接pop wrapperDelegate");
wrapperDelegate.pop();
}, 500);
}
} else
@YoKeyword 我们前端用的是vue所以webview的canback对我们无效,只能通过协议去通知前端【用户需要返回了】,前端在自己处理自身的路由,如果路由到底了,那么就反向通知我们popwebview:
isNotidy = titleBarEventListener.onBackBtnClick();
// jump-->
@Override
public boolean onBackBtnClick() {
LoggerProxy.d("h5通用头部返回按钮的监听事件被调用 %s", ON_HEADER_BAR_TAP_BCK_LISTENER);
if (!StringUtils.isEmpty(ON_HEADER_BAR_TAP_BCK_LISTENER)) {
JsBridgeCommHandler.callJs(getWebViewOrNullllll(), ON_HEADER_BAR_TAP_BCK_LISTENER);
return true;
} else {
// 第三方webview会走这里
//_onPopWebViewDelegate();
return false;
}
}
而且也存在友商的不是SPA的应用所以也需要做if (webView.canGoBack()) {
判断。所以上面的代码看起来很屎就是这个原因。
@YoKeyword 不知道有没有兴趣研究一下这个webview的神坑,哈哈,我觉得就算换了x5也怕是一个鸟样。
但是我刚才玩了一下微信,【急速返回】,好像没有导致这个问题,的确有点牛逼,等项目稳定了我换一个试试。
如题,这个是有一定很大概率会出现这个问题,请问是什么原因? 我是上层fragment 是不可swipe 所以没有 new SwipeBackFragmentDelegate ,没有嵌入 swipelayout.