前言
从事Android以来,几乎离不开
WebView
的使用。但是使用WebView
的过程中,总会出一些令人意想不到的问题,故打算写一篇文章专门用来记录开发过程中遇到的问题吧。如果大家有遇到什么奇怪的问题,欢迎补充完善。
WebView多语言如何处理字体反向
通过改变html dir
的属性即可改变文字的方向,比如设置dir="RTL"
则表示文字从右往左;
比如: <html dir=\"rtl\" lang=\"\"><body>" + outhtml + "</body></html>
。
而默认不设置的话,则是从左往右的。
所以如果要对不同的语言进行文字方向适配的话就需要客户端判断当前语言环境下的文字方向了,然后去调整html
的文字方向。
而客户端如何判断当前语言文字的方向呢?我直接把代码放到下面了
if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL){
//代表文字从右往左
}else{
//文字方向从左往右
}
接下来对应调整html
的方向了,但是此时分为两种情况。
- 直接通过
loadDataWithBaseURL
加载html
代码。 - 通过
loadUrl
直接加载前端URL
。
第一种比较好解决,直接客户端判断然后手动注入dir="RTL"
即可,比如:
if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL){
desc.loadDataWithBaseURL(bull, "<html dir=\"rtl\" lang=\"\"><body>" + outhtml + "</body></html>", "text/html", "UTF-8", null);
}else{
desc.loadDataWithBaseURL(bull, outHtml, "UTF-8", null);
}
第二种这里目前本人没有遇到过,但是无非就是需要通知到html
当前文字方向而已,然后他们自己可以根据当前的文字方向去做处理就可以。至于如何通知到html
。这个可以和html
的研发同学约定,通过JavascriptInterface
的方式进行交互即可。这里不再深入展开。
WebView如何适配暗黑模式
这一块再Android10
以上Google
官方有给出解决方案。利用WebSettingsCompat
可以进行设置处理。
怎么使用呢?
首先,引入webkit
库。
implementation "androidx.webkit:webkit:1.4.0"
然后再WebView
初始化的时候放入如下的代码即可
kotlin
版本
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> {
WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_ON)
}
Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_OFF)
}
else -> {}
}
}
java
版本
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
case Configuration.UI_MODE_NIGHT_YES:
WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_ON);
break;
case Configuration.UI_MODE_NIGHT_NO:
case Configuration.UI_MODE_NIGHT_UNDEFINED:
WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_OFF);
break;
}
}
更多的使用方式可以参考:Draken web content.
WebView 预加载、对象缓存实现
我们知道对于WebView
加载优化来说,有一个很重要优化策略就是WebView的预加载以及对象的缓存,因为WebView
过于沉重,导致再构建是耗时比较久。为避免使用时再构建,可以增加预加载以及WebView
对象复用。
下面直接放WebView
预加载以及复用池工具类,可以直接使用。
class WebViewPool {
private val webViewCache: MutableList<WebView> = ArrayList(NUM)
fun prepare(context: Context) {
if (webViewCache.isEmpty()) {
Looper.myQueue().addIdleHandler {
webViewCache.add(create(MutableContextWrapper(context)))
false
}
}
}
fun get(context: Context): WebView {
if (webViewCache.isEmpty()) {
webViewCache.add(create(MutableContextWrapper(context)))
}
return webViewCache.removeFirst().apply {
val contextWrapper = context as MutableContextWrapper
contextWrapper.baseContext = context
clearHistory()
resumeTimers()
}
}
fun recycle(webView: WebView) {
try {
with(webView){
stopLoading()
loadDataWithBaseURL(null, "", "text/html", "utf-8", null)
clearHistory()
pauseTimers()
webChromeClient = null
webViewClient = WebViewClient()
}
val parent = webView.parent
if (parent != null) {
(parent as ViewGroup).removeView(webView)
}
} catch (e: Exception) {
} finally {
if (!webViewCache.contains(webView)) {
webViewCache.add(webView)
}
}
}
fun destroy() {
try {
webViewCache.removeAll {
it.removeAllViews()
it.destroy()
false
}
} catch (e: Exception) {
}
}
private fun create(context: Context) = WebView(context)
companion object{
const val NUM = 1
}
}
WebView如何处理跨域问题
何为跨域?
当一个请求url
的协议、域名、端口三者之间任意一个与当前页面url
不同即为跨域。
怎么处理呢?
设置
webview
的setting
的allowUniversalAccessFromFileURLs
、为true
。settings.allowUniversalAccessFromFileURLs = true
如果上述设置还是跨域,那么是不是本来需要网络请求的资源你缓存到本地加载了呢?如果是,则可以直接做如下的设置:
webResourceResponse.responseHeaders = mapOf( "Access-Control-Allow-Origin" to "*", "Access-Control-Allow-Headers" to "*", "Access-Control-Allow-Credentials" to "true", "Access-Control-Allow-Methods" to "POST, PUT, GET, OPTIONS, DELETE" )
注意:如果设置了可以无限制跨域,从安全层面来说,需要对文件做校验处理,对js
调用做鉴权处理。
持续更新…
🙆♀️。欢迎技术探讨噢!