feat: 添加WebView页面

This commit is contained in:
糕小菜 2024-12-03 21:37:58 +08:00
parent d534f15efd
commit b7654c644c
11 changed files with 315 additions and 31 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RenderSettings">
<option name="showDecorations" value="true" />
</component>
</project>

View File

@ -39,6 +39,9 @@
android:theme="@style/Theme.KChatAndroid"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.activity.WebViewActivity"
android:exported="false" />
<activity
android:name=".ui.activity.FriendCircleActivity"
android:exported="false" />

View File

@ -1,19 +1,27 @@
package com.kaixed.kchat.ui.activity
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ClickableSpan
import android.text.util.Linkify
import android.util.Patterns
import android.view.View
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ProgressBar
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.recyclerview.widget.LinearLayoutManager
import com.kaixed.kchat.R
import com.kaixed.kchat.data.model.dynamic.Comment
import com.kaixed.kchat.data.model.dynamic.FriendCircleItem
import com.kaixed.kchat.databinding.ActivityTestBinding
import com.kaixed.kchat.ui.adapter.FriendCircleAdapter
import com.kaixed.kchat.ui.base.BaseActivity
import java.util.regex.Pattern
class TestActivity : BaseActivity<ActivityTestBinding>() {
override fun inflateBinding(): ActivityTestBinding {
return ActivityTestBinding.inflate(layoutInflater)
}
@ -22,33 +30,44 @@ class TestActivity : BaseActivity<ActivityTestBinding>() {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
initView()
val text = "访问我们的站点 https://www.example.com/ 或者 http://www.abc.com"
val spannableString = SpannableString(text)
// 使用正则表达式找到 URL
val urlPattern = Pattern.compile("(https?://[\\w\\-]+(?:\\.[\\w\\-]+)+[/#?]?.*)")
val matcher = urlPattern.matcher(text)
// 创建可点击的 span
while (matcher.find()) {
val url = matcher.group()
spannableString.setSpan(object : ClickableSpan() {
override fun onClick(widget: View) {
// 这里可以做点击处理,例如打开 WebView 或外部浏览器
println("点击了链接: $url")
}
}, matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
val textView: TextView = binding.textView
textView.text = spannableString
textView.isClickable = true
textView.movementMethod = android.text.method.LinkMovementMethod.getInstance()
}
private fun extractUrlsWithPatterns(text: String): List<String> {
val matcher = Patterns.WEB_URL.matcher(text)
val urls = mutableListOf<String>()
private fun initView() {
while (matcher.find()) {
urls.add(matcher.group())
}
return urls
}
override fun initData() {
// PictureSelector.create(this)
// .openGallery(SelectMimeType.ofImage())
// .setImageEngine(ImageEngines())
// .forResult(object : OnResultCallbackListener<LocalMedia?> {
// override fun onResult(result: ArrayList<LocalMedia?>) {
// result.forEach { localMedia ->
// localMedia?.let {
// val imagePath = it.realPath
// toast("图片路径: $imagePath")
// }
// }
// }
//
// override fun onCancel() {
// toast("已取消")
// }
// })
}
}

View File

@ -0,0 +1,110 @@
package com.kaixed.kchat.ui.activity
import android.os.Bundle
import android.view.View
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ProgressBar
import androidx.activity.enableEdgeToEdge
import com.kaixed.kchat.databinding.ActivityWebViewBinding
import com.kaixed.kchat.ui.base.BaseActivity
class WebViewActivity : BaseActivity<ActivityWebViewBinding>() {
private lateinit var webView: WebView
private lateinit var progressBar: ProgressBar
private var url = ""
override fun inflateBinding(): ActivityWebViewBinding {
return ActivityWebViewBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding.ivSetting.setOnClickListener {
finish()
}
webView = binding.webView
progressBar = binding.progressBar
// 初始化 WebView
setupWebView()
// 加载网页
webView.loadUrl(url)
setListener()
}
private fun setListener() {
binding.ivBack.setOnClickListener {
if (webView.canGoBack()) {
webView.goBack()
} else {
finish()
}
}
}
override fun initData() {
url = intent.getStringExtra("url") ?: ""
}
private fun setupWebView() {
// 启用 JavaScript
webView.settings.javaScriptEnabled = true
// 设置 WebViewClient 来处理页面跳转
webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(
view: WebView,
url: String,
favicon: android.graphics.Bitmap?
) {
super.onPageStarted(view, url, favicon)
// 页面开始加载时显示 ProgressBar
progressBar.visibility = View.VISIBLE
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
// 页面加载完成时隐藏 ProgressBar
progressBar.visibility = View.INVISIBLE
binding.tvTitle.visibility = View.VISIBLE
binding.tvTitle.text = webView.title
binding.tvUrl.text = webView.url
binding.tvUrl.visibility = View.VISIBLE
}
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
): Boolean {
return false
}
}
// 设置 WebChromeClient 监听进度变化
webView.webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView, newProgress: Int) {
super.onProgressChanged(view, newProgress)
// 更新进度条的进度
progressBar.progress = newProgress
if (newProgress == 100) {
progressBar.visibility = View.INVISIBLE
} else {
progressBar.visibility = View.VISIBLE
}
}
}
}
}

View File

@ -32,6 +32,7 @@ import com.kaixed.kchat.ui.activity.AddFriendsActivity
import com.kaixed.kchat.ui.activity.FriendCircleActivity
import com.kaixed.kchat.ui.activity.SearchActivity
import com.kaixed.kchat.ui.activity.TestActivity
import com.kaixed.kchat.ui.activity.WebViewActivity
import com.kaixed.kchat.ui.adapter.ConversationAdapter
import com.kaixed.kchat.ui.adapter.MyGridAdapter
import com.kaixed.kchat.ui.base.BaseFragment

View File

@ -6,6 +6,7 @@ import android.graphics.Color
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.kaixed.kchat.R
@ -26,6 +27,9 @@ class CustomTitleBar @JvmOverloads constructor(
private var isBtnEnabled: Boolean = false
val ivSetting: ImageView
get() = binding.ivSetting
init {
attrs?.let {
val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomTitleBar, 0, 0)

View File

@ -3,6 +3,7 @@ package com.kaixed.kchat.ui.widget
import android.content.Intent
import android.os.Bundle
import android.text.util.Linkify
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

View File

@ -0,0 +1,14 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<color android:color="@color/white" />
</item>
<item android:id="@android:id/progress">
<clip
android:clipOrientation="horizontal"
android:gravity="left">
<color android:color="@color/green" />
</clip>
</item>
</layer-list>

View File

@ -2,16 +2,20 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
<com.kaixed.kchat.ui.widget.CustomTitleBar
android:id="@+id/ctb"
app:titleIcon="@drawable/ic_more"
android:layout_width="match_parent"
android:layout_height="0dp"
android:overScrollMode="never"
android:layout_weight="1.0"
android:visibility="visible" />
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text_view"
android:text="haha"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -0,0 +1,80 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EDEDED"
android:fitsSystemWindows="true"
tools:context=".ui.activity.WebViewActivity">
<ImageView
android:id="@+id/iv_back"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:src="@drawable/ic_left_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:ellipsize="end"
android:maxLines="1"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="15sp"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="@id/tv_url"
app:layout_constraintEnd_toStartOf="@id/iv_setting"
app:layout_constraintStart_toEndOf="@id/iv_back"
app:layout_constraintTop_toTopOf="@id/iv_back" />
<TextView
android:id="@+id/tv_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="kaixed.com"
android:textColor="@color/black"
android:textSize="11sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintEnd_toEndOf="@id/tv_title"
app:layout_constraintStart_toStartOf="@id/tv_title"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<ImageView
android:id="@+id/iv_setting"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_marginEnd="15dp"
android:src="@drawable/ic_more"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_back"
app:layout_goneMarginEnd="15dp" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_marginTop="8dp"
android:progressDrawable="@drawable/progress_bar_color"
app:layout_constraintTop_toBottomOf="@id/iv_back" />
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBar" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,42 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_back"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginVertical="20dp"
android:layout_marginStart="15dp"
android:src="@drawable/ic_left_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="16sp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_back" />
<ImageView
android:id="@+id/iv_setting"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_marginEnd="15dp"
android:src="@drawable/ic_more"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_back"
app:layout_goneMarginEnd="15dp" />
</androidx.constraintlayout.widget.ConstraintLayout>