Add linear progress bar and refactor WebViewCallback
This commit is contained in:
parent
4ebe674620
commit
49037036b4
|
|
@ -2,6 +2,11 @@ package ru.touchin.extensions
|
|||
|
||||
import android.content.res.TypedArray
|
||||
import androidx.annotation.StyleableRes
|
||||
import androidx.core.content.res.getResourceIdOrThrow
|
||||
|
||||
fun TypedArray.getResourceIdOrNull(@StyleableRes index: Int) = runCatching { getResourceIdOrThrow(index) }.getOrNull()
|
||||
private const val DEFAULT_VALUE = -1
|
||||
|
||||
fun TypedArray.getResourceIdOrNull(@StyleableRes index: Int) = getResourceId(index, DEFAULT_VALUE)
|
||||
.takeIf { it != DEFAULT_VALUE }
|
||||
|
||||
fun TypedArray.getColorOrNull(@StyleableRes index: Int) = getColor(index, DEFAULT_VALUE)
|
||||
.takeIf { it != DEFAULT_VALUE }
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ dependencies {
|
|||
implementation "com.google.android.material:material"
|
||||
implementation "androidx.constraintlayout:constraintlayout"
|
||||
implementation "androidx.core:core-ktx"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout"
|
||||
|
||||
constraints {
|
||||
implementation("com.google.android.material:material") {
|
||||
|
|
@ -36,6 +37,11 @@ dependencies {
|
|||
require '1.3.0'
|
||||
}
|
||||
}
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout") {
|
||||
version {
|
||||
require '1.1.0'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,35 +7,37 @@ import android.webkit.WebChromeClient
|
|||
import android.webkit.WebView
|
||||
|
||||
open class BaseChromeWebViewClient(
|
||||
private val onJsConfirm: (() -> Unit)? = null,
|
||||
private val onJsAlert: (() -> Unit)? = null,
|
||||
private val onJsPrompt: ((String?) -> Unit)? = null,
|
||||
private val onJsError: ((error: ConsoleMessage) -> Unit)? = null
|
||||
private val callback: WebViewCallback
|
||||
) : WebChromeClient() {
|
||||
|
||||
override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
|
||||
onJsConfirm?.invoke()
|
||||
callback.onJsConfirm(message)
|
||||
result?.confirm()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
|
||||
onJsAlert?.invoke()
|
||||
callback.onJsAlert(message)
|
||||
result?.confirm()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
|
||||
if (consoleMessage?.messageLevel() == ConsoleMessage.MessageLevel.ERROR) {
|
||||
onJsError?.invoke(consoleMessage)
|
||||
callback.onJsError(consoleMessage)
|
||||
}
|
||||
return super.onConsoleMessage(consoleMessage)
|
||||
}
|
||||
|
||||
override fun onJsPrompt(view: WebView?, url: String?, message: String?, defaultValue: String?, result: JsPromptResult?): Boolean {
|
||||
onJsPrompt?.invoke(defaultValue)
|
||||
callback.onJsPrompt(defaultValue)
|
||||
result?.confirm()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onProgressChanged(view: WebView?, newProgress: Int) {
|
||||
super.onProgressChanged(view, newProgress)
|
||||
callback.onProgressChanged(newProgress)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,14 @@ package ru.touchin.roboswag.webview.web_view
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.webkit.ConsoleMessage
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebView
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import ru.touchin.extensions.getColorOrNull
|
||||
import ru.touchin.extensions.getResourceIdOrNull
|
||||
import ru.touchin.extensions.setOnRippleClickListener
|
||||
import ru.touchin.roboswag.views.widget.Switcher
|
||||
import ru.touchin.roboswag.webview.R
|
||||
|
|
@ -26,17 +25,9 @@ open class BaseWebView @JvmOverloads constructor(
|
|||
|
||||
private val binding = BaseWebViewBinding.inflate(LayoutInflater.from(context), this)
|
||||
|
||||
var onWebViewLoaded: (() -> Unit)? = null
|
||||
var onWebViewRepeatButtonClicked: (() -> Unit)? = null
|
||||
var onWebViewScrolled: ((WebView, Int, Int) -> Unit)? = null
|
||||
var onCookieLoaded: ((cookies: Map<String, String>?) -> Unit)? = null
|
||||
private var isCircleProgressBar = true
|
||||
|
||||
var onJsConfirm: (() -> Unit)? = null
|
||||
var onJsAlert: (() -> Unit)? = null
|
||||
var onJsPrompt: ((defaultValue: String?) -> Unit)? = null
|
||||
var onJsError: ((error: ConsoleMessage) -> Unit)? = null
|
||||
|
||||
var isPullToRefreshEnable = false
|
||||
private var isPullToRefreshEnabled = false
|
||||
set(value) {
|
||||
binding.pullToRefresh.isEnabled = value
|
||||
binding.pullToRefresh.isRefreshing = false
|
||||
|
|
@ -45,45 +36,19 @@ open class BaseWebView @JvmOverloads constructor(
|
|||
|
||||
var redirectionController = RedirectionController()
|
||||
|
||||
/**
|
||||
* If you need to do some action on url click inside WebView, just assign this parameter and disable isRedirectEnable
|
||||
**/
|
||||
var actionOnRedirect: ((String?, WebView) -> Unit)? = null
|
||||
|
||||
init {
|
||||
binding.pullToRefresh.isEnabled = isPullToRefreshEnable
|
||||
initAttributes(attrs, defStyleAttr)
|
||||
binding.pullToRefresh.isEnabled = isPullToRefreshEnabled
|
||||
|
||||
binding.apply {
|
||||
context.withStyledAttributes(attrs, R.styleable.BaseWebView, defStyleAttr, 0) {
|
||||
if (hasValue(R.styleable.BaseWebView_errorTextAppearance)) {
|
||||
TextViewCompat.setTextAppearance(errorText, getResourceId(R.styleable.BaseWebView_errorTextAppearance, 0))
|
||||
}
|
||||
if (hasValue(R.styleable.BaseWebView_repeatButtonTextAppearance)) {
|
||||
TextViewCompat.setTextAppearance(errorRepeatButton, getResourceId(R.styleable.BaseWebView_repeatButtonTextAppearance, 0))
|
||||
}
|
||||
if (hasValue(R.styleable.BaseWebView_progressBarTintColor)) {
|
||||
progressBar.indeterminateTintList = ColorStateList.valueOf(getColor(R.styleable.BaseWebView_progressBarTintColor, Color.BLACK))
|
||||
}
|
||||
if (hasValue(R.styleable.BaseWebView_repeatButtonBackground)) {
|
||||
errorRepeatButton.setBackgroundResource(getResourceId(R.styleable.BaseWebView_repeatButtonBackground, 0))
|
||||
}
|
||||
if (hasValue(R.styleable.BaseWebView_screenBackground)) {
|
||||
setBackgroundResource(getResourceId(R.styleable.BaseWebView_screenBackground, 0))
|
||||
}
|
||||
if (hasValue(R.styleable.BaseWebView_errorText)) {
|
||||
errorText.text = getString(R.styleable.BaseWebView_errorText)
|
||||
}
|
||||
if (hasValue(R.styleable.BaseWebView_repeatButtonText)) {
|
||||
errorRepeatButton.text = getString(R.styleable.BaseWebView_repeatButtonText)
|
||||
}
|
||||
}
|
||||
pullToRefresh.setOnRefreshListener {
|
||||
webView.reload()
|
||||
}
|
||||
errorRepeatButton.setOnRippleClickListener {
|
||||
onWebViewRepeatButtonClicked?.invoke()
|
||||
onRepeatButtonClicked()
|
||||
}
|
||||
webView.onScrollChanged = { scrollX, scrollY, _, _ ->
|
||||
onWebViewScrolled?.invoke(binding.webView, scrollX, scrollY)
|
||||
onWebViewScrolled(scrollX, scrollY)
|
||||
}
|
||||
setWebViewPreferences()
|
||||
}
|
||||
|
|
@ -92,13 +57,11 @@ open class BaseWebView @JvmOverloads constructor(
|
|||
override fun onStateChanged(newState: WebViewLoadingState) {
|
||||
when {
|
||||
newState == WebViewLoadingState.LOADED -> {
|
||||
onWebViewLoaded?.invoke()
|
||||
binding.pullToRefresh.isRefreshing = false
|
||||
showChild(R.id.pull_to_refresh)
|
||||
}
|
||||
newState == WebViewLoadingState.LOADING
|
||||
&& !binding.pullToRefresh.isRefreshing -> {
|
||||
showChild(R.id.progress_bar)
|
||||
newState == WebViewLoadingState.LOADING && !binding.pullToRefresh.isRefreshing -> {
|
||||
showChild(if (isCircleProgressBar) R.id.progress_bar else R.id.linear_progress_bar)
|
||||
}
|
||||
newState == WebViewLoadingState.ERROR -> {
|
||||
showChild(R.id.error_layout)
|
||||
|
|
@ -109,17 +72,21 @@ open class BaseWebView @JvmOverloads constructor(
|
|||
override fun onOverrideUrlLoading(url: String?): Boolean =
|
||||
redirectionController.shouldRedirectToUrl(url)
|
||||
|
||||
override fun onPageCookiesLoaded(cookies: Map<String, String>?) {
|
||||
onCookieLoaded?.invoke(cookies)
|
||||
override fun onRepeatButtonClicked() {
|
||||
loadUrl(getWebView().url)
|
||||
}
|
||||
|
||||
override fun actionOnRedirectInsideWebView(webView: WebView, url: String?) {
|
||||
actionOnRedirect?.invoke(url, webView)
|
||||
override fun onProgressChanged(progress: Int) {
|
||||
binding.linearProgressBar.progress = progress
|
||||
}
|
||||
|
||||
fun setBaseWebViewClient(isSSlPinningEnable: Boolean = true) {
|
||||
binding.webView.webViewClient = BaseWebViewClient(this, isSSlPinningEnable)
|
||||
binding.webView.webChromeClient = BaseChromeWebViewClient(onJsConfirm, onJsAlert, onJsPrompt, onJsError)
|
||||
fun setBaseWebViewClient(callback: WebViewCallback = this) {
|
||||
binding.webView.webViewClient = BaseWebViewClient(callback)
|
||||
binding.webView.webChromeClient = BaseChromeWebViewClient(callback)
|
||||
}
|
||||
|
||||
fun handleBackPressed(closeScreenAction: () -> Unit) {
|
||||
with(getWebView()) { if (canGoBack()) goBack() else closeScreenAction.invoke() }
|
||||
}
|
||||
|
||||
fun getWebView() = binding.webView
|
||||
|
|
@ -168,14 +135,6 @@ open class BaseWebView @JvmOverloads constructor(
|
|||
)
|
||||
}
|
||||
|
||||
fun setState(newState: WebViewLoadingState) {
|
||||
onStateChanged(newState)
|
||||
}
|
||||
|
||||
fun setOnWebViewDisplayedContentAction(action: () -> Unit) {
|
||||
binding.webView.onWebViewDisplayedContent = action
|
||||
}
|
||||
|
||||
/**
|
||||
* loadWithOverviewMode loads the WebView completely zoomed out
|
||||
* useWideViewPort sets page size to fit screen
|
||||
|
|
@ -200,4 +159,33 @@ open class BaseWebView @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun initAttributes(attrs: AttributeSet?, defStyleAttr: Int) = with(binding) {
|
||||
context.withStyledAttributes(attrs, R.styleable.BaseWebView, defStyleAttr, 0) {
|
||||
getResourceIdOrNull(R.styleable.BaseWebView_errorTextAppearance)?.let {
|
||||
TextViewCompat.setTextAppearance(errorText, it)
|
||||
}
|
||||
getResourceIdOrNull(R.styleable.BaseWebView_repeatButtonTextAppearance)?.let {
|
||||
TextViewCompat.setTextAppearance(errorRepeatButton, it)
|
||||
}
|
||||
getResourceIdOrNull(R.styleable.BaseWebView_repeatButtonBackground)?.let {
|
||||
errorRepeatButton.setBackgroundResource(it)
|
||||
}
|
||||
getColorOrNull(R.styleable.BaseWebView_progressBarTintColor)?.let {
|
||||
progressBar.indeterminateTintList = ColorStateList.valueOf(it)
|
||||
linearProgressBar.indeterminateTintList = ColorStateList.valueOf(it)
|
||||
}
|
||||
getResourceIdOrNull(R.styleable.BaseWebView_repeatButtonBackground)?.let {
|
||||
setBackgroundResource(getResourceId(R.styleable.BaseWebView_screenBackground, 0))
|
||||
}
|
||||
|
||||
getString(R.styleable.BaseWebView_errorText)?.let { errorText.text = it }
|
||||
getString(R.styleable.BaseWebView_repeatButtonText)?.let { errorRepeatButton.text = it }
|
||||
|
||||
isCircleProgressBar = getBoolean(R.styleable.BaseWebView_isCircleProgressBar, true)
|
||||
isPullToRefreshEnabled = getBoolean(R.styleable.BaseWebView_isPullToRefreshEnabled, false)
|
||||
|
||||
onStateChanged(WebViewLoadingState.LOADING)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ open class BaseWebViewClient(
|
|||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
||||
val url = request.url.toString()
|
||||
return if (!callback.onOverrideUrlLoading(url) && view.originalUrl != null) {
|
||||
callback.actionOnRedirectInsideWebView(webView = view, url = url)
|
||||
callback.onRedirectInsideWebView(webView = view, url = url)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
|
@ -102,9 +102,3 @@ open class BaseWebViewClient(
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
enum class WebViewLoadingState {
|
||||
LOADING,
|
||||
ERROR,
|
||||
LOADED
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package ru.touchin.roboswag.webview.web_view
|
||||
|
||||
import android.webkit.ConsoleMessage
|
||||
import android.webkit.WebView
|
||||
|
||||
interface WebViewCallback {
|
||||
|
|
@ -8,8 +9,27 @@ interface WebViewCallback {
|
|||
|
||||
fun onOverrideUrlLoading(url: String?): Boolean
|
||||
|
||||
fun onPageCookiesLoaded(cookies: Map<String, String>?)
|
||||
fun onRepeatButtonClicked()
|
||||
|
||||
fun actionOnRedirectInsideWebView(webView: WebView, url: String?)
|
||||
fun onPageCookiesLoaded(cookies: Map<String, String>?) = Unit
|
||||
|
||||
fun onRedirectInsideWebView(webView: WebView, url: String?) = Unit
|
||||
|
||||
fun onWebViewScrolled(scrollX: Int, scrollY: Int) = Unit
|
||||
|
||||
fun onJsConfirm(message: String?) = Unit
|
||||
|
||||
fun onJsAlert(message: String?) = Unit
|
||||
|
||||
fun onJsPrompt(defaultValue: String?) = Unit
|
||||
|
||||
fun onJsError(error: ConsoleMessage) = Unit
|
||||
|
||||
fun onProgressChanged(progress: Int) = Unit
|
||||
}
|
||||
|
||||
enum class WebViewLoadingState {
|
||||
LOADING,
|
||||
ERROR,
|
||||
LOADED
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,14 @@
|
|||
android:layout_height="32dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<ProgressBar
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:id="@+id/linear_progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/error_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
<attr name="repeatButtonTextAppearance" format="reference"/>
|
||||
<attr name="errorTextAppearance" format="reference"/>
|
||||
<attr name="progressBarTintColor" format="color"/>
|
||||
<attr name="isCircleProgressBar" format="boolean"/>
|
||||
<attr name="isPullToRefreshEnabled" format="boolean"/>
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in New Issue