与DialogX一起完结全屏WebView对话框和沉溺式适配
开发中咱们往往会遇到一种需求,需求临时弹出一个 Web 层展现 H5 页面,iOS 端供给了一种原界面下沉的全屏打开 WebView 能够很便利的完结,用户也能够通过下滑操作封闭 Web 页面的阅读返回原界面。
要在 Android 渠道完结类似的作用,能够尝试运用 DialogX 的 FullScreenDialog 调配 WebView 完结沉溺式的全屏阅读器出现,同样的,也支撑滑动到 Web 页面顶端时继续向下滑动封闭对话框的操作,别的也支撑沉溺式哦,跟随我一起来看看我是怎么完结这样炫酷的功用吧!
首要介绍一下 DialogX
DialogX 是一款简单易用的对话框组件,相比原生对话框运用体验更佳,可自定义程度更高,扩展性更强,轻松完结各种对话框、菜单和提示作用,更有iOS、MIUI、Material You等主题扩展可选。
能够移步之前的文章查看详细介绍:运用 DialogX 快速构建 Android App 对话框 – ()
先来一起创建一个全屏 WebView 对话框吧!
如上图所示,是一个从屏幕下方打开的全屏对话框,它根据 DialogX 的 FullScreenDialog 完结,只需求自定义一个 WebView 布局即可,要完结滑动承继,需求自定义 WebView 并完结一个 DialogX 的接口,范例代码如下所示:
public class CustomWebView extends WebView implements ScrollController {
public CustomWebView(@NonNull Context context) {
super(context);
}
public CustomWebView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomWebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
@Deprecated
public boolean isLockScroll() {
return lockScroll;
}
boolean lockScroll;
@Override
public void lockScroll(boolean lockScroll) {
this.lockScroll = lockScroll;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (lockScroll) return false;
return super.onTouchEvent(event);
}
@Override
public int getScrollDistance() {
return getScrollY();
}
boolean canScroll = true;
public CustomWebView setCanScroll(boolean canScroll) {
this.canScroll = canScroll;
return this;
}
@Override
public boolean isCanScroll() {
return canScroll;
}
}
按照上述固定写法即可。
将 CustomWebView 增加一份布局,放上封闭按钮即可完结界面布局的搭建作业。为便利后续操作,暂时将布局命名为 layout_dialog_webview
参考布局代码如下,请注意设置 tag 为 ScrollController
以便利 FullScreenDialog 绑定滑动承继组件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<TextView
android:id="@+id/btn_close"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="封闭"
android:textColor="@color/dialogxIOSBlue"
android:textSize="18dp" />
</LinearLayout>
<com.kongzue.dialogxdemo.CustomWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="ScrollController" />
</LinearLayout>
接下来编写 FullScreenDialog 的完结代码
FullScreenDialog.show(new OnBindView<FullScreenDialog>(R.layout.layout_dialog_webview) {
private TextView btnClose;
private CustomWebView webView;
@Override
public void onBind(FullScreenDialog dialog, View v) {
btnClose = v.findViewById(R.id.btn_close);
webView = v.findViewById(R.id.webView);
//Set WebView Settings...
webView.loadUrl("https://www.example.com");
}
});
即可发动一个全屏展现的 WebView 对话框并加载一个页面。
那么该怎么完结沉溺式适配呢?FullScreenDialog 默认情况下已经做好了一些沉溺式作业,例如对话框的内容一定会在沉溺式的“安全区”范围内,对话框顶部只会上移到手机状态栏以下,而对话框内容底部也会在导航栏以上,但这间隔咱们想要的页面内容“下沉”到导航栏以下的需求不符,此刻只需求一个开关即可完结:
.setBottomNonSafetyAreaBySelf(true)
此设置是 FullScreenDialog 的设置,假如没有请更新至最新测试版别的 DialogX,开启后内容布局将被答应下沉到底部导航栏以后显示,此刻 Web 页面将能够沉溺的显示在导航栏后了,那么接下来的问题就是怎么为页面内容设置一个 paddingBottom,使其内容不分能够在用户可操作的屏幕安全区内,沉溺,但不影响正常运用。
设置页面内容到安全范围内
常见的计划大致是对内容直接设置一个导航栏高度的 paddingBottom,使其背景不受躲藏但内容在安全范围内,
我之前 有一篇文章 有说过沉溺式的基本逻辑在于正确的对安全区和非安全区的处理,准则即:将背景下沉,将操作区域和主要内容区域放在安全区内:
要完结这点,咱们需求获取底部导航栏的高度,再对 WebView 的页面内容进行 paddingBottom 的设置,前者其实 DialogX 已经帮你处理好了,只需求一句代码即可获取:
int bottomUnsafeAreaHeight = dialog.getDialogImpl().boxRoot.getUnsafePlace().bottom;
但实践上,不主张这样粗犷的获取,由于非安全区位置或许由于横竖屏切换,以及不分设备上能够躲藏导航栏导致高度发生变化,更主张的计划是动态回调的方式获取,这样愈加安全可靠:
dialog.getDialogImpl().boxRoot.setOnSafeInsetsChangeListener(new OnSafeInsetsChangeListener() {
@Override
public void onChange(Rect unsafeRect) {
int bottomUnsafeAreaHeight = unsafeRect.bottom;
}
});
bottomUnsafeAreaHeight 的值就是底部非安全区的高度啦,单位是像素。
但此刻你又会遇到一个严重问题,那就是 WebView 不吃 setPadding
这套,对 WebView 设置 padding 是无效的,咱们需求使页面内容 paddingBottom = bottomUnsafeAreaHeight 的间隔以保证当 WebView 滑动到底部后为导航栏空出一段间隔。
那么此刻就得用到 WebView 的 Client,在其中 onPageFinished
方法设置一段 js 来为页面的 body 设置一段底部 padding 来达到需求的作用,不废话直接上代码:
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
if (unsafeRect != null) {
webView.loadUrl("javascript:document.body.style.paddingBottom="" + px2dip(bottomUnsafeAreaHeight) + "px"; void 0");
}
super.onPageFinished(view, url);
}
}
其中,px2dip
是一个像素对 dp 的转化东西,由于适配移动端的 H5 在 WebView 出现时默认会习惯屏幕的像素密度,因而关于网页内容中的 px 实践上等同于 dp 的值,因而此处需求将底部非安全区的高度转化为 dp 当做 px 设置给页面。
上述代码为页面的 body 增加了 paddingBottom 的设置,但这需求 H5 页面支撑,假如你需求显示的 H5 页面不收效,请依据实践需求查看内部元素适当的调整上述 js 以适配实践需求。
至此,根据 DialogX 的 FullScreenDialog 完结全屏 WebView 和沉溺式适配作业也就基本完结了,让咱们在 App 悉数沉溺式的道路上更进一步吧!