Skip to content

Commit

Permalink
优化webBrowser
Browse files Browse the repository at this point in the history
  • Loading branch information
ITGungnir committed May 21, 2019
1 parent 100f973 commit ba8f3b9
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 172 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ dependencies {
api "com.github.ITGungnir:UIKit:$uikit_version"
}
```
**注意:** 如果要使用`WebBrowser`控件,需要先在项目的`AndroidManifest.xml`文件中添加相关权限:
```xml
<manifest>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Your codes -->
</manifest>
```
参考不同控件的相关文档,使用控件即可。

## License
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package="test.itgungnir.ui">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
android:name=".App"
Expand Down
45 changes: 15 additions & 30 deletions app/src/main/java/test/itgungnir/ui/fragment3/ChildFragment3.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package test.itgungnir.ui.fragment3

import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_child3.*
import my.itgungnir.ui.browser.WebBrowser
import my.itgungnir.ui.input.ProgressButton
import my.itgungnir.ui.status_view.StatusView
import org.jetbrains.anko.support.v4.toast
import test.itgungnir.ui.R

class ChildFragment3 : Fragment() {
Expand All @@ -23,36 +21,23 @@ class ChildFragment3 : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

statusView.addDelegate(StatusView.Status.SUCCEED, R.layout.status_view_web) {
loadSucceedPage(it)
}.addDelegate(StatusView.Status.FAILED, R.layout.status_view_error) {
loadFailedPage(it)
}

statusView.succeed { }
}

@SuppressLint("SetTextI18n")
private fun loadSucceedPage(view: View) {
view.findViewById<WebBrowser>(R.id.browser).apply {
load("https://www.baidu.com/", false)
.onError { code, msg ->
statusView.failed { view ->
view.findViewById<TextView>(R.id.errorMsg).text = "$code$msg"
view.findViewById<ProgressButton>(R.id.reload).ready("重新加载")
}
backButton.apply {
ready("Go Back")
setOnClickListener {
if (!browserView.goBack()) {
toast("Back stack empty.")
}
mask(Color.parseColor("#44000000"))
}
}
}

private fun loadFailedPage(view: View) {
view.findViewById<ProgressButton>(R.id.reload).apply {
ready("重新加载")
setOnClickListener {
loading()
statusView.succeed { v -> loadSucceedPage(v) }
browserView.load(
url = "https://bugly.qq.com/v2/index",
blockImage = false,
errorLayoutId = R.layout.status_view_error,
errorCallback = {
it.findViewById<TextView>(R.id.errorMsg).text = "页面加载时出现问题,请重试~"
it.findViewById<ProgressButton>(R.id.reload).ready("重新加载")
}
}
)
}
}
16 changes: 11 additions & 5 deletions app/src/main/res/layout/fragment_child3.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">

<my.itgungnir.ui.status_view.StatusView
android:id="@+id/statusView"
<my.itgungnir.ui.input.ProgressButton
android:id="@+id/backButton"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />

<my.itgungnir.ui.browser.WebBrowser
android:id="@+id/browserView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>
</LinearLayout>
1 change: 1 addition & 0 deletions base_ui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ dependencies {
implementation "com.jakewharton.rxbinding2:rxbinding:$rxbinding_version"
// Widgets
implementation "com.google.android:flexbox:$flex_version"
implementation "com.just.agentweb:agentweb:$agent_web_version"
}
115 changes: 30 additions & 85 deletions base_ui/src/main/java/my/itgungnir/ui/browser/WebBrowser.kt
Original file line number Diff line number Diff line change
@@ -1,115 +1,60 @@
package my.itgungnir.ui.browser

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.webkit.*
import android.widget.ProgressBar
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import android.webkit.WebSettings
import android.widget.FrameLayout
import android.widget.LinearLayout
import com.just.agentweb.AgentWeb
import kotlinx.android.synthetic.main.view_web_browser.view.*
import my.itgungnir.ui.R
import org.jetbrains.anko.backgroundColor

@SuppressLint("SetJavaScriptEnabled")
class WebBrowser @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
ConstraintLayout(context, attrs, defStyleAttr) {
class WebBrowser @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
FrameLayout(context, attrs, defStyleAttr) {

private var browserView: WebView
private var containerView: FrameLayout

private var progressView: ProgressBar

private var onErrorCallback: ((Int, String) -> Unit)? = null
private lateinit var agentWeb: AgentWeb

init {

View.inflate(context, R.layout.view_web_browser, this)

browserView = webView
progressView = progressBar
this.containerView = webContainer
}

fun load(url: String, blockImage: Boolean = false, errorLayoutId: Int, errorCallback: (View) -> Unit) {

val errorView = LayoutInflater.from(context).inflate(errorLayoutId, this, false).apply {
errorCallback.invoke(this)
}

agentWeb = AgentWeb.with(context as Activity)
.setAgentWebParent(webContainer, LinearLayout.LayoutParams(-1, -1))
.useDefaultIndicator()
.setMainFrameErrorView(errorView)
.createAgentWeb()
.ready()
.go(url)

browserView.apply {
agentWeb.webCreator.webView.apply {
settings.apply {
javaScriptEnabled = true
// 支持手势缩放
setSupportZoom(true)
builtInZoomControls = true
displayZoomControls = false
useWideViewPort = true
layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
loadWithOverviewMode = true
// 显示图片
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
}
webViewClient = object : WebViewClient() {
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
): Boolean {
view.loadUrl(request.url.toString())
return true
}

@Suppress("OverridingDeprecatedMember")
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}

@RequiresApi(Build.VERSION_CODES.M)
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
error?.let {
onErrorCallback?.invoke(it.errorCode, it.description.toString())
}
super.onReceivedError(view, request, error)
}
}
webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView?, newProgress: Int) {
progressView.apply {
progress = newProgress
visibility = when (newProgress) {
100 -> View.GONE
else -> View.VISIBLE
}
}
}
layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
blockNetworkImage = blockImage
}
}
}

fun load(url: String, blockImage: Boolean = false): WebBrowser {
browserView.apply {
settings.blockNetworkImage = blockImage
loadUrl(url)
}
return this
}

fun onError(block: (Int, String) -> Unit) {
this.onErrorCallback = block
}

/**
* 在页面上加一层遮盖
*/
fun mask(maskColor: Int) {
mask.apply {
visibility = View.VISIBLE
backgroundColor = maskColor
}
}
fun goBack() = agentWeb.back()
}
37 changes: 3 additions & 34 deletions base_ui/src/main/res/layout/view_web_browser.xml
Original file line number Diff line number Diff line change
@@ -1,36 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">

<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="2dp"
android:progress="40"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<View
android:id="@+id/mask"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar" />

</androidx.constraintlayout.widget.ConstraintLayout>
android:layout_height="match_parent" />
1 change: 1 addition & 0 deletions config.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ext {
rxbinding_version = '2.2.0'
// Widgets
flex_version = '1.0.0'
agent_web_version = '4.0.2'
// Tools
jitpack_version = '2.1'
rxmvvm_version = '1.1.6'
Expand Down
51 changes: 33 additions & 18 deletions docs/Browser.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,50 @@
# UIKit - Browser

`WebBrowser`是一个带进度条的网页加载和展示控件。
`WebBrowser`是一个带进度条的网页加载和展示控件,支持`错误回调``页内回退``阻绝图片加载`等功能。

## 0、准备
如果要使用`WebBrowser`控件,需要先在项目的`AndroidManifest.xml`文件中添加权限:
```xml
<manifest>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Your codes -->
</manifest>
```

## 1、布局
```xml
<my.itgungnir.ui.browser.WebBrowser
android:id="@+id/browser"
android:id="@+id/browserView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
```

## 2、使用
### (1)加载网页
```kotlin
// load():设置要加载的网页URL
browser.load("https://www.baidu.com/")
// onError():加载网页失败时的回调方法,提供错误码code和错误信息msg
.onError { code, msg ->
statusView.failed { view ->
view.findViewById<TextView>(R.id.errorMsg).text = "$code$msg"
view.findViewById<ProgressButton>(R.id.reload).ready("重新加载")
}
browserView.load(
// url:要加载的网页URL
url = "https://bugly.qq.com/v2/index",
// blockImage:是否要阻绝图片加载,置为true时将不加载网页中的图片
blockImage = false,
// errorLayoutId:当页面发生错误时,显示的布局
errorLayoutId = R.layout.status_view_error,
// errorCallback:对错误布局的渲染
errorCallback = {
it.findViewById<TextView>(R.id.errorMsg).text = "页面加载时出现问题,请重试~"
it.findViewById<ProgressButton>(R.id.reload).ready("重新加载")
}
)
```
**注意:** `WebBrowser`中进度条的颜色取决于系统配置的`colorAccent`颜色值。

`WebBrowser``load()`方法支持两个参数,第二个参数可以指明是否支持无图模式,设置为`true`时,将不会加载页面中的图片:
### (2)页内回退
`WebBrowser`控件提供了一个`goBack()`方法,支持页内回退,当该方法返回为`true`时,表示前面仍有其他页面可以回退,否则表示当前页已位于栈底。示例代码如下:
```kotlin
browser.load("https://www.baidu.com/", true)
```
`WebBrowser`同时提供了一个`mask()`方法,可以应用于主题切换(如夜间模式)中:
```kotlin
browser.mask(Color.parseColor("#44000000"))
```
上述代码用于在`WebView`上层添加一层遮罩,建议设置为半透明色;如果不写这行代码,则`WebView`上不会添加任何遮罩层。
override fun onBackPressed() {
if (!browserView.goBack()) {
super.onBackPressed()
}
}
```

0 comments on commit ba8f3b9

Please sign in to comment.