@@ -2,15 +2,13 @@ package com.zj.play.article
2
2
3
3
import android.annotation.SuppressLint
4
4
import android.content.Context
5
- import android.content.Intent
6
5
import android.content.res.Configuration
7
- import android.net.Uri
6
+ import android.os.Build
8
7
import android.text.TextUtils
9
8
import android.util.AttributeSet
10
9
import android.util.Log
11
10
import android.view.KeyEvent
12
11
import android.view.MotionEvent
13
- import android.view.View
14
12
import android.view.ViewGroup
15
13
import android.view.ViewGroup.LayoutParams
16
14
import android.webkit.*
@@ -20,6 +18,7 @@ import androidx.core.content.res.ResourcesCompat
20
18
import androidx.core.view.isVisible
21
19
import com.zj.play.R
22
20
21
+
23
22
/* *
24
23
* [setShowProgress]
25
24
*/
@@ -44,39 +43,48 @@ class X5WebView @JvmOverloads constructor(
44
43
progressBar?.progressDrawable =
45
44
ResourcesCompat .getDrawable(resources, R .drawable.color_progressbar, null )
46
45
addView(progressBar, LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , 6 ))
47
- initWebViewSettings ()
46
+ setDefaultWebSettings ()
48
47
}
49
48
50
- // 基本的WebViewSetting
51
- @SuppressLint(" ClickableViewAccessibility" , " SetJavaScriptEnabled" )
52
- private fun initWebViewSettings () {
53
- setBackgroundColor(resources.getColor(R .color.article_share_bg, null ))
54
- webViewClient = client
49
+ private fun setDefaultWebSettings () {
55
50
webChromeClient = chromeClient
56
- setDownloadListener(downloadListener)
57
- isClickable = true
58
- setOnTouchListener { _: View ? , _: MotionEvent ? -> false }
59
- val webSetting = settings
60
- webSetting.builtInZoomControls = true
61
- webSetting.javaScriptCanOpenWindowsAutomatically = true
62
- webSetting.domStorageEnabled = true
63
- webSetting.allowFileAccess = true
64
- webSetting.setSupportZoom(true )
65
- webSetting.useWideViewPort = true
66
- webSetting.setSupportMultipleWindows(true )
67
- webSetting.setAppCacheEnabled(true )
68
- webSetting.setGeolocationEnabled(true )
69
-
51
+ val webSettings = settings
52
+ // 5.0以上开启混合模式加载
53
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
54
+ webSettings.mixedContentMode = WebSettings .MIXED_CONTENT_ALWAYS_ALLOW
55
+ }
56
+ webSettings.loadWithOverviewMode = true
57
+ webSettings.useWideViewPort = true
58
+ // 允许js代码
59
+ webSettings.javaScriptEnabled = true
60
+ // 允许SessionStorage/LocalStorage存储
61
+ webSettings.domStorageEnabled = true
62
+ // 禁用放缩
63
+ webSettings.displayZoomControls = false
64
+ webSettings.builtInZoomControls = false
65
+ // 禁用文字缩放
66
+ webSettings.textZoom = 100
67
+ // 10M缓存,api 18后,系统自动管理。
68
+ webSettings.setAppCacheMaxSize((10 * 1024 * 1024 ).toLong())
69
+ // 允许缓存,设置缓存位置
70
+ webSettings.setAppCacheEnabled(true )
71
+ webSettings.setAppCachePath(context.getDir(" appcache" , 0 ).path)
72
+ // 允许WebView使用File协议
73
+ webSettings.allowFileAccess = true
74
+ // 不保存密码
75
+ webSettings.savePassword = false
76
+ // 设置UA
77
+ webSettings.userAgentString = webSettings.userAgentString + " playAndroid"
78
+ // 自动加载图片
79
+ webSettings.loadsImagesAutomatically = true
70
80
if (resources.configuration.uiMode and Configuration .UI_MODE_NIGHT_MASK == Configuration .UI_MODE_NIGHT_YES ) { // 判断如果系统是深色主题
71
- webSetting .forceDark = WebSettings .FORCE_DARK_ON // 强制开启webview深色主题模式
81
+ webSettings .forceDark = WebSettings .FORCE_DARK_ON // 强制开启webview深色主题模式
72
82
} else {
73
- webSetting .forceDark = FORCE_DARK_OFF
83
+ webSettings .forceDark = FORCE_DARK_OFF
74
84
}
75
-
76
- // 需要支持多窗体还需要重写WebChromeClient.onCreateWindow
77
- webSetting.setSupportMultipleWindows(false )
78
85
}
79
86
87
+
80
88
override fun onKeyDown (keyCode : Int , event : KeyEvent ): Boolean {
81
89
if (keyCode == KeyEvent .KEYCODE_BACK && canGoBack()) {
82
90
goBack() // goBack()表示返回WebView的上一页面
@@ -104,30 +112,112 @@ class X5WebView @JvmOverloads constructor(
104
112
}
105
113
}
106
114
}
107
- private val client: WebViewClient = object : WebViewClient () {
108
- // 当页面加载完成的时候
109
- override fun onPageFinished (webView : WebView , url : String ) {
110
- val cookieManager = CookieManager .getInstance()
111
- cookieManager.setAcceptCookie(true )
112
- val endCookie = cookieManager.getCookie(url)
113
- Log .i(" TAG" , " onPageFinished: endCookie : $endCookie " )
114
- CookieManager .getInstance().flush()
115
- super .onPageFinished(webView, url)
116
- }
117
115
118
- override fun shouldOverrideUrlLoading (
119
- view : WebView ? ,
120
- request : WebResourceRequest ?
121
- ): Boolean {
122
- return true
116
+ private var mTouchByUser = false
117
+
118
+ override fun loadUrl (url : String , additionalHttpHeaders : Map <String ?, String ?>) {
119
+ super .loadUrl(url, additionalHttpHeaders)
120
+ resetAllStateInternal(url)
121
+ }
122
+
123
+ override fun loadUrl (url : String ) {
124
+ super .loadUrl(url)
125
+ resetAllStateInternal(url)
126
+ }
127
+
128
+ override fun postUrl (url : String , postData : ByteArray ) {
129
+ super .postUrl(url, postData)
130
+ resetAllStateInternal(url)
131
+ }
132
+
133
+ override fun loadData (data : String , mimeType : String? , encoding : String? ) {
134
+ super .loadData(data, mimeType, encoding)
135
+ resetAllStateInternal(url)
136
+ }
137
+
138
+ override fun loadDataWithBaseURL (
139
+ baseUrl : String? ,
140
+ data : String ,
141
+ mimeType : String? ,
142
+ encoding : String? ,
143
+ historyUrl : String?
144
+ ) {
145
+ super .loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl)
146
+ resetAllStateInternal(url)
147
+ }
148
+
149
+ override fun reload () {
150
+ super .reload()
151
+ resetAllStateInternal(url)
152
+ }
153
+
154
+ fun isTouchByUser (): Boolean {
155
+ return mTouchByUser
156
+ }
157
+
158
+ private fun resetAllStateInternal (url : String? ) {
159
+ Log .w(TAG , " resetAllStateInternal: url:$url " )
160
+ if (url != null && ! TextUtils .isEmpty(url) && url.startsWith(" javascript:" )) {
161
+ return
123
162
}
163
+ resetAllState()
164
+ }
124
165
166
+ // 加载url时重置touch状态
167
+ private fun resetAllState () {
168
+ mTouchByUser = false
125
169
}
126
170
127
- private val downloadListener =
128
- DownloadListener { url : String? , _ : String? , _ : String? , _ : String? , _ : Long ->
129
- val uri = Uri .parse(url)
130
- val intent = Intent ( Intent . ACTION_VIEW , uri)
131
- context.startActivity(intent)
171
+ @SuppressLint( " ClickableViewAccessibility " )
172
+ override fun onTouchEvent ( event : MotionEvent ): Boolean {
173
+ when (event.action) {
174
+ MotionEvent . ACTION_DOWN -> // 用户按下到下一个链接加载之前,置为true
175
+ mTouchByUser = true
132
176
}
177
+ return super .onTouchEvent(event)
178
+ }
179
+
180
+ override fun setWebViewClient (client : WebViewClient ) {
181
+ Log .w(TAG , " setWebViewClient: $client " )
182
+ super .setWebViewClient(object : WebViewClient () {
183
+
184
+
185
+ @Deprecated(" Deprecated in Java" )
186
+ override fun shouldOverrideUrlLoading (view : WebView , url : String ): Boolean {
187
+ val handleByChild = client.shouldOverrideUrlLoading(view, url)
188
+ return if (handleByChild) {
189
+ // 开放client接口给上层业务调用,如果返回true,表示业务已处理。
190
+ true
191
+ } else if (! isTouchByUser()) {
192
+ // 如果业务没有处理,并且在加载过程中用户没有再次触摸屏幕,认为是301/302事件,直接交由系统处理。
193
+ super .shouldOverrideUrlLoading(view, url)
194
+ } else {
195
+ // 否则,属于二次加载某个链接的情况,为了解决拼接参数丢失问题,重新调用loadUrl方法添加固有参数。
196
+ loadUrl(url)
197
+ true
198
+ }
199
+ }
200
+
201
+ override fun shouldOverrideUrlLoading (
202
+ view : WebView ? ,
203
+ request : WebResourceRequest
204
+ ): Boolean {
205
+ Log .w(TAG , " shouldOverrideUrlLoading: ${request.url} " )
206
+ val handleByChild = client.shouldOverrideUrlLoading(view, request)
207
+ return if (handleByChild) {
208
+ true
209
+ } else if (! isTouchByUser()) {
210
+ return true
211
+ } else {
212
+ loadUrl(request.url.toString())
213
+ true
214
+ }
215
+ }
216
+ })
217
+ }
218
+
219
+ companion object {
220
+ private const val TAG = " X5WebView"
221
+ }
222
+
133
223
}
0 commit comments