WebView组件封装(三)——PkWebView的使用文档

1,960 阅读7分钟

Welcome to the PkWebView wiki!

怎样使用

Step 1. Add the JitPack repository to your build file

Add it in your root build.gradle at the end of repositories:

	allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}

but If it is a new version of Android studio,Add it in your root setting.gradle at the end of repositories:

dependencyResolutionManagement {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency

	dependencies {
	        implementation 'com.github.Peakmain:PkWebView:+'
	}

功能列表

一、Application中初始化WebView参数

class App : Application() {
    override fun onCreate() {
        PkWebViewInit.Builder(this)
            //设置WebViewSetting
            .setWebViewSetting(DefaultInitWebViewSetting())
            //设置WebViewClient
            .setWebViewClient(DefaultWebViewClientCallback())
            //设置WebViewChromeClient
            .setWebViewChromeClient(DefaultWebViewChromeClientCallback())
            //设置LoadingView
            .setLoadingWebViewState(LoadingWebViewState.HorizontalProgressBarLoadingStyle)
            .setLoadingView(ReplaceLoadingConfigImpl())
            //设置没有网络View
            .setNoNetWorkView(com.peakmain.webview.R.layout.webview_no_network, null)
            .setNoNetWorkView(FrameLayout(this), null)
            //设置userAgent
            .setUserAgent(BuildConfig.config.userAgent)
            //设置WebView的数量
            .setWebViewCount(5)
            //设置接收H5通信的协议
            .registerEntities(OnlineServiceHandle::class.java, PageActionHandle::class.java)
            //设置解析url中的params的key
            .setEventParamsKey("param")
            //创建WebView
            .build()
        super.onCreate()
    }
}
1、自定义定制WebViewSetting

你可以根据自己的需求定制 WebView 的设置。我们只需要创建一个继承自 InitWebViewSetting 的类,然后重写其中的 initWebViewSetting() 方法,即可自定义 WebView 的设置。

比如,我们可以创建一个 ReplaceInitWebViewSetting 类,来替换默认的 WebView 设置。在其中,我们可以通过 webView.settings 对象来设置 WebView 的一些属性,如下所示:

public class ReplaceInitWebViewSetting extends InitWebViewSetting {

    @Override
    public void initWebViewSetting(WebView webView, String userAgent) {
        super.initWebViewSetting(webView, userAgent);

        // 设置 WebView 的 UserAgent
        String newUA = "...";
        webView.getSettings().setUserAgentString(newUA);

        // 设置 WebView 支持 JavaScript
        webView.getSettings().setJavaScriptEnabled(true);

        // 设置 WebView 缓存模式
        webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

        // 设置 WebView 允许加载本地文件
        webView.getSettings().setAllowFileAccess(true);

        // 设置 WebView 的字体缩放
        webView.getSettings().setTextZoom(100);
    }
}

在实现自定义设置之后,我们只需要在应用中使用 PkWebViewInit.Builder().setWebViewSetting(ReplaceInitWebViewSetting()) 的方式即可将其载入应用,并实现自定义设置

2、自定义定制WebViewClient

你可以根据自己的需求定制WebViewClient。我们只需要创建一个继承自WebViewClientCallback 的类,然后重写其中的方法,即可自定义 WebViewClient

比如,我们可以创建一个 ReplaceWebViewClient 类,来替换默认的 WebViewClient。在其中,我们可以通过重写 shouldOverrideUrlLoading() 方法来自定义处理 WebView 页面跳转的方式,比如在用户点击链接时,通过自定义方式来处理跳转逻辑。同时,我们还可以重写 onPageStarted() 和 onPageFinished() 方法,来实现 WebView 页面加载时的一些自定义功能,例如自定义加载动画、页面计时等

此外,我们还可以通过重写 onReceivedError() 方法来自定义 WebView 加载错误时的处理方式,以及通过重写 shouldInterceptRequest() 方法来自定义 WebView 加载资源时的请求拦截逻辑等等。

下面是一个 ReplaceWebViewClient 类的示例代码,仅供参考:

class ReplaceWebViewClient : WebViewClientCallback() {
    override fun onPageStarted(view: WebView?, url: String?, fragment: WebViewFragment?) {
        // 自定义页面加载开始时的逻辑
    }

    override fun onPageFinished(view: WebView?, url: String?, fragment: WebViewFragment?) {
        // 自定义页面加载结束时的逻辑
    }

    override fun shouldOverrideUrlLoading(view: WebView?, url: String?, fragment: WebViewFragment?): Boolean {
        // 自定义页面跳转的方式
        // 如果需要自定义处理,可以返回 true 并执行自定义代码
        // 如果不需要自定义处理,则可以返回 false,以使用 WebView 默认的跳转方式
        return false
    }

    override fun onReceivedError(view: WebView?, err: Int, des: String?, url: String?, fragment: WebViewFragment?) {
        // 自定义页面加载错误时的处理方式
    }

    override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
        // 自定义拦截资源请求的逻辑
        // 如果需要拦截请求,则返回自定义的 WebResourceResponse 对象,否则返回 null
        return null
    }
}

在实现自定义WebViewClient之后,我们只需要在应用中使用 PkWebViewInit.Builder().setWebViewClient(ReplaceWebViewClient()) 的方式即可将其载入应用,并实现自定义WebViewClient

3、自定义定制WebViewChromeClient

你可以根据自己的需求定制WebViewChromeClient。我们只需要创建一个继承自WebViewChromeClientCallback的类,然后重写其中的方法,即可自定义 WebViewChromeClient

class ReplaceWebViewChromeClientCallback : WebViewChromeClientCallback() {
    override fun onReceivedTitle(view: WebView?, title: String?, fragment: WebViewFragment?) {
        // 在页面加载完成后,获取页面标题,并对其进行自定义处理
        Log.e("TAG", "收到标题:$title")
    }

    override fun onProgressChanged(view: WebView?, newProgress: Int, fragment: WebViewFragment?) {
        // 在页面加载过程中,获取当前页面的加载进度,并对 UI 进行自定义更新
        Log.e("TAG", "进度条发生变化:$newProgress")
    }

    override fun openFileInput(
        fileUploadCallbackFirst: ValueCallback<Uri>?,
        fileUploadCallbackSecond: ValueCallback<Array<Uri>>?,
        acceptType: String?
    ) {
        // 拦截 WebView 上的文件上传操作,并对上传的文件进行自定义处理
        // 如果您不需要处理文件上传,请直接忽略此方法
    }
}

在实现自定义WebViewChromeClientCallback之后,我们只需要在应用中使用 PkWebViewInit.Builder().setWebViewChromeClientCallback(ReplaceWebViewChromeClientCallback()) 的方式即可将其载入应用,并实现自定义WebViewChromeClientCallback

4、自定义LoadingView

①、setLoadingWebViewState 加载loadingView一共有4种状态

  • NotLoading:不加载loading
  • HorizontalProgressBarLoadingStyle:水平进度条加载loading
  • ProgressBarLoadingStyle:圆圈加载loading
  • CustomLoadingStyle:自定义加载样式
sealed class LoadingWebViewState {
    object NotLoading : LoadingWebViewState()
    object HorizontalProgressBarLoadingStyle : LoadingWebViewState()
    object ProgressBarLoadingStyle : LoadingWebViewState()
    object CustomLoadingStyle : LoadingWebViewState()
}

如果需要使用自定义Loading,setLoadingWebViewState一定要指定为CustomLoadingStyle

PkWebViewInit.Builder(this).setLoadingWebViewState(LoadingWebViewState.CustomLoadingStyle)

②、自定义LoadingView

我们只需要创建一个类,继承LoadingViewConfig,并重写其中的方法即可。 下面是一个自定义loading的例子

class ReplaceLoadingConfigImpl : LoadingViewConfig {
    private lateinit var mAppProgressLoadingView: AppProgressLoadingView
    private var isShowLoading: Boolean = false
    override fun isShowLoading(): Boolean {
        return isShowLoading
    }

    override fun getLoadingView(context: Context): View {
        if (!::mAppProgressLoadingView.isInitialized) {
            mAppProgressLoadingView = AppProgressLoadingView(context)
        }
        isShowLoading = true
        return mAppProgressLoadingView

    }


    override fun hideLoading() {
        isShowLoading = false
        mAppProgressLoadingView.visibility = View.GONE
    }

    override fun showLoading(context: Context?) {
        if (!::mAppProgressLoadingView.isInitialized && context != null) {
            mAppProgressLoadingView = AppProgressLoadingView(context)
        }
        isShowLoading=true
        mAppProgressLoadingView.visibility = View.VISIBLE
    }
}
5、自定义没有网络的View

①、根据id添加没有网络的View

PkWebViewInit.Builder(this).setNoNetWorkView(com.peakmain.webview.R.layout.webview_no_network, null)

②、根据view添加没有网络的View

PkWebViewInit.Builder(this).setNoNetWorkView(FrameLayout(this), null)

第二个参数是是个函数方法,添加View成功之后,可以做些网络错误View的处理

PkWebViewInit.Builder(this)
        .setNoNetWorkView(FrameLayout(this)) { view ->
            view.findViewById<TextView>(R.id.tv_retry).setOnClickListener {
                // 在这里处理点击“重试”按钮后的逻辑
                Toast.makeText(this, "网络错误,请重试", Toast.LENGTH_SHORT).show()
            }
        }
6、设置UserAgent
PkWebViewInit.Builder(this).setUserAgent("android")
7、设置WebView的数量
PkWebViewInit.Builder(this).setWebViewCount(5)
8、设置接收H5通信的协议

您可以使用registerEntities方法来设置接收H5通信的协议。这个方法接收一个参数数组,您可以在其中添加您想要接收的协议

PkWebViewInit.Builder(this).registerEntities(OnlineServiceHandle::class.java, PageActionHandle::class.java)

接下来,让我们来看一下如何设置接收协议所需的类。在这个类上方,我们需要添加一个名为Handler的注解,该注解需要指定scheme和authority这两个参数

@Handler(scheme = BuildConfig.scheme, authority = ["onlineService"])
class OnlineServiceHandle {
    @HandlerMethod(path = BuildConfig.path)
    fun webPolicyAlert(event: WebViewModelEvent): HandleResult {
        // 在这里完成接收协议的逻辑
        return HandleResult.Consumed
    }
}

二、H5Utils启动WebViewActivity

H5Utils()
    .isShowToolBar(false)
    //.setLoadingWebViewState(LoadingWebViewState.ProgressBarLoadingStyle)
    .updateStatusBar { title, activity ->
        if (title.contains("商城")) {
            activity?.updateStateBar(StatusBarState.NoStatusModeState)
        } else {
            activity?.updateStateBar()
        }
    }
    .updateToolBar { title, activity ->
        if (title.contains("商城")) {
            activity?.showToolbar(false)
            activity?.showHeadView(true)
        } else {
            activity?.showToolbar(true)
            activity?.showHeadView(false)
            /*    activity?.setOnClickListener({
                    activity.finish()
                }) {
                    Toast.makeText(it.context, "点击右边", Toast.LENGTH_LONG).show()
                }*/
            activity?.setToolbarStyle { toolbar, ivLeft, tvTitle, tvRight ->
                //toolbar?.setBackgroundColor(Color.TRANSPARENT)
                /*  ivLeft?.setImageResource()
                  tvTitle?.apply {
                      setTextColor(Color.RED)
                  }
                  tvRight?.visibility = View.VISIBLE*/
            }
        }
    }
    .setHeadContentView(R.layout.hotel_list_head) {

    }
    .setHandleUrlParamsCallback(HandlerUrlParamsImpl())
    .startActivityForResult(
        this, launcher,
        WebViewConfigBean(
            BuildConfig.config.url
        )
    )
1、是否有ToolBar

false代表没有ToolBar,true则表示有

H5Utils()
    .isShowToolBar(false)
2、设置加载LoadingView

这里和上面说的自定义LoadingView一样,这里就不阐述

H5Utils()
    .setLoadingWebViewState(LoadingWebViewState.ProgressBarLoadingStyle)
3、设置状态栏颜色

可以根据title设置不同的状态栏颜色

H5Utils().updateStatusBar { title, activity ->
    if (title.contains("商城")) {
        activity?.updateStateBar(StatusBarState.NoStatusModeState)
    } else {
        activity?.updateStateBar()
    }
}

activity的updateStateBar有两个参数 ①、状态栏的状态一共有4种状态,默认是黑色字体

sealed class StatusBarState : Parcelable {
    /**
     * 黑色的字体
     */
    object LightModeState : StatusBarState()

    /**
     * 白色的字体
     */

    object DartModeState : StatusBarState()

    /**
     * 自定义状态栏颜色
     */
    object StatusColorState : StatusBarState()

    /**
     * 隐藏状态栏
     */
    object NoStatusModeState : StatusBarState()
}

②、statusBarColor:设置状态栏的颜色,默认是白色 源码

fun updateStateBar(
    statusBarState: StatusBarState = StatusBarState.LightModeState,
    statusBarColor: Int = Color.WHITE
)
4、设置头部布局
H5Utils().setHeadContentView(R.layout.hotel_list_head) {
      //可以对头部的view做处理,假设有以下TextView
      it.findViewById(R.id.tv_title).setOnClickListener{}
}
5、toolBar的处理,可以根据title是否显示ToolBar,是否显示头部等
H5Utils().updateToolBar { title, activity ->
    if (title.contains("商城")) {
        activity?.showToolbar(false)
        activity?.showHeadView(true)
    } else {
        activity?.showToolbar(true)
        activity?.showHeadView(false)
        /*    activity?.setOnClickListener({
                activity.finish()
            }) {
                Toast.makeText(it.context, "点击右边", Toast.LENGTH_LONG).show()
            }*/
        activity?.setToolbarStyle { toolbar, ivLeft, tvTitle, tvRight ->
            //toolbar?.setBackgroundColor(Color.TRANSPARENT)
            /*  ivLeft?.setImageResource()
              tvTitle?.apply {
                  setTextColor(Color.RED)
              }
              tvRight?.visibility = View.VISIBLE*/
        }
    }
}
6、解析url中参数,封装成不同的对象

首先你需要定义一个实体类,继承WebViewEvent类

data class WebViewModelEvent(
    var webViewModel: WebViewModel? = null,
    var newHybridModel: NewHybridModel? = null
) : WebViewEvent()

data class WebViewModel(
    var status: Int = 1,
    var data: HashMap<String, String>?,
    var callId: String = "" //用于给前端的协议
)

接下来,我们可以自定义一个类,并实现HandleUrlParamsCallback接口的handleUrlParamsCallback方法。在这个方法中,我们可以实现对URL中参数的解析,并将其封装成不同的对象。例如

class HandlerUrlParamsImpl : HandleUrlParamsCallback<WebViewModelEvent> {
    override fun handleUrlParamsCallback(uri: Uri?, path: String?): WebViewModelEvent {
        val params = uri?.getQueryParameter("param")
        val webViewModelEvent = WebViewModelEvent()
        if (!TextUtils.isEmpty(params)) {
            val decodeParam: String =
                EncodeUtils.decode(params!!.replace(" ", "+"))
            LogWebViewUtils.e("PkWebView decodeParam:$decodeParam")
            if (TextUtils.equals("/jumpToWhere", path)) {
                val newHybridModel: NewHybridModel = GsonUtils.fromJson(
                    decodeParam,
                    NewHybridModel::class.java
                )
                webViewModelEvent.newHybridModel = newHybridModel
            } else {
                val webViewModel: WebViewModel =
                    GsonUtils.fromJson(decodeParam, WebViewModel::class.java)
                webViewModelEvent.webViewModel = webViewModel
            }
        }
        return webViewModelEvent
    }

}

关于我