Add Functionality and Fix Issues in WebViewActivity

- Implemented draggable FloatingActionButton with click functionality.
- Resolved touch conflict between touch and click events on FloatingActionButton.
- Improved WebView reload logic and ensured UI components are not obstructed.
- Updated XML layouts for better constraint alignment and visual consistency.
- Enhanced logging for user actions on the refresh button.

Ensures a smoother user experience and UI operation.
This commit is contained in:
moreoronce 2024-10-07 13:29:12 +08:00
parent b82febf82a
commit 236bb140f8
12 changed files with 126 additions and 55 deletions

1
.gitignore vendored
View file

@ -16,4 +16,3 @@ local.properties
/android
/.tmp
/kotlin-profile

View file

@ -67,6 +67,8 @@ dependencies {
implementation(libs.androidx.constraintlayout)
implementation("androidx.activity:activity-ktx:1.9.2")
implementation(libs.material)
implementation("androidx.browser:browser:1.3.0")
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)

View file

@ -9,7 +9,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.WebViewApp"> <!-- 使用 Theme.WebViewApp 作为主题 -->
android:theme="@style/Theme.WebViewApp">
<activity
android:name=".MainActivity"

View file

@ -1,10 +1,9 @@
package com.example.lobchat
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.webkit.WebSettings
import android.webkit.WebView
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
@ -12,7 +11,6 @@ import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var webView: WebView
private lateinit var urlInput: EditText
private lateinit var loadUrlButton: Button
@ -21,15 +19,17 @@ class MainActivity : AppCompatActivity() {
const val KEY_SAVED_URL = "saved_url"
}
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 初始化视图组件
webView = findViewById(R.id.webView)
urlInput = findViewById(R.id.urlInput)
loadUrlButton = findViewById(R.id.loadUrlButton)
// 从 SharedPreferences 加载上次保存的 URL
val sharedPreferences = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
val savedUrl = sharedPreferences.getString(KEY_SAVED_URL, "")
@ -37,14 +37,6 @@ class MainActivity : AppCompatActivity() {
urlInput.setText(savedUrl)
}
// 设置状态栏为透明,使系统自动使用默认的颜色
window.statusBarColor = resources.getColor(android.R.color.transparent, theme)
// 初始化 WebView 设置
val webSettings: WebSettings = webView.settings
webSettings.javaScriptEnabled = true
webSettings.domStorageEnabled = true
// 点击按钮后加载用户输入的 URL
loadUrlButton.setOnClickListener {
val url = urlInput.text.toString().trim()
@ -53,11 +45,9 @@ class MainActivity : AppCompatActivity() {
if (url.isNotEmpty()) {
// 确保 URL 包含 http 或 https
val formattedUrl = if (!urlPattern.matches(url)) {
// 如果 URL 格式不正确,则提示用户
Toast.makeText(this, "请输入正确的网站地址", Toast.LENGTH_SHORT).show()
return@setOnClickListener // 结束函数
return@setOnClickListener
} else {
// 确保 URL 包含 http 或 https
if (!url.startsWith("http://") && !url.startsWith("https://")) {
"https://$url"
} else {

View file

@ -1,40 +1,51 @@
package com.example.lobchat
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.webkit.ConsoleMessage
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.view.MotionEvent
import android.view.View
import android.webkit.*
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
class WebViewActivity : AppCompatActivity() {
private lateinit var webView: WebView
private var filePathCallback: ValueCallback<Array<Uri>>? = null
private lateinit var fileChooserLauncher: ActivityResultLauncher<Intent>
private var isFinalUrlLoaded = false
// 用于标记是否通过 LobeChat 验证
private var isLobeChatVerified = false
private lateinit var refreshButton: FloatingActionButton
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_web_view)
refreshButton = findViewById(R.id.refreshButton)
// 初始化 WebView
webView = findViewById(R.id.webView)
setupWebView()
// 刷新按钮的点击事件
refreshButton.bringToFront()
refreshButton.setOnClickListener {
Log.i("WebViewActivity", "Refresh button clicked")
webView.reload()
}
// 设置拖动事件监听器
refreshButton.setOnTouchListener(DraggableTouchListener())
// 初始化文件选择器启动器
fileChooserLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
handleFileChooserResult(result)
@ -49,29 +60,30 @@ class WebViewActivity : AppCompatActivity() {
}
}
// 增加处理Android返回键逻辑
// 处理返回键
override fun onBackPressed() {
if (webView.canGoBack()) {
// 如果WebView能够返回上一页
webView.goBack()
} else {
// 否则调用super以处理默认的后退行为
super.onBackPressed()
}
}
private fun setupWebView() {
val webSettings: WebSettings = webView.settings
webSettings.javaScriptEnabled = true
webSettings.domStorageEnabled = true
webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
webSettings.cacheMode = WebSettings.LOAD_DEFAULT // Use default caching strategy
// Other optimizations
webSettings.databaseEnabled = true
webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
webSettings.userAgentString = "Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Mobile Safari/537.36"
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
// 当 URL 变化时重置 isFinalUrlLoaded 标志
isFinalUrlLoaded = false
// 返回 false 表示允许 WebView 处理请求
return false
}
@ -88,12 +100,10 @@ class WebViewActivity : AppCompatActivity() {
""".trimIndent()
) { result ->
if (result == "true") {
// 验证通过,不再继续验证
isLobeChatVerified = true
Toast.makeText(this@WebViewActivity, "LobeChat validation passed", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this@WebViewActivity, "The webpage does not contain the required LobeChat text in the header.", Toast.LENGTH_LONG).show()
// 如果验证失败,返回 MainActivity
val intent = Intent(this@WebViewActivity, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
@ -145,4 +155,37 @@ class WebViewActivity : AppCompatActivity() {
private fun showSnackbar(message: String) {
Snackbar.make(findViewById(android.R.id.content), message, Snackbar.LENGTH_LONG).show()
}
private inner class DraggableTouchListener : View.OnTouchListener {
private var dX = 0f
private var dY = 0f
private var isClick = false
override fun onTouch(view: View, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
dX = view.x - event.rawX
dY = view.y - event.rawY
isClick = true
}
MotionEvent.ACTION_MOVE -> {
view.animate()
.x(event.rawX + dX)
.y(event.rawY + dY)
.setDuration(0)
.start()
isClick = false
}
MotionEvent.ACTION_UP -> {
if (isClick) {
// 处理点击事件
Log.i("WebViewActivity", "Refresh button clicked")
webView.reload()
}
}
}
return true
}
}
}

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="100dp" android:viewportHeight="24" android:viewportWidth="24" android:width="100dp">
<path android:fillColor="@color/transparent" android:pathData="M3,12a9,9 0,0 1,9 -9,9.75 9.75,0 0,1 6.74,2.74L21,8" android:strokeColor="@color/purple_dark_10" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="@color/transparent" android:pathData="M21,3v5h-5" android:strokeColor="@color/purple_dark_10" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="@color/transparent" android:pathData="M21,12a9,9 0,0 1,-9 9,9.75 9.75,0 0,1 -6.74,-2.74L3,16" android:strokeColor="@color/purple_dark_10" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2"/>
<path android:fillColor="@color/transparent" android:pathData="M8,16H3v5" android:strokeColor="@color/purple_dark_10" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2"/>
</vector>

View file

@ -6,7 +6,9 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- 包含两个ImageView的容器 -->
<LinearLayout
@ -59,7 +61,7 @@
android:hint="@string/enter_your_server_url"
android:inputType="textUri"
android:textColor="@color/cyan_dark_0"
android:textColorHint="@color/gray_dark_8"
android:textColorHint="@color/gray_dark_4"
android:textSize="14sp" />
</com.google.android.material.textfield.TextInputLayout>

View file

@ -1,11 +1,27 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".WebViewActivity">
<!-- FloatingActionButton -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/refreshButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginBottom="100dp"
android:backgroundTint="@color/purple_dark_9"
android:contentDescription="Refresh"
app:srcCompat="@drawable/ic_refresh"
app:backgroundTint="@color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- WebView 控件 -->
<WebView
android:id="@+id/webView"

View file

@ -675,4 +675,7 @@
<color name="slate_light_10">#484a4d</color>
<color name="slate_light_11">#1b1c1d</color>
<color name="slate_light_12">#111111</color>
<color name="transparent">#00000000</color>
</resources>

View file

@ -1,5 +1,5 @@
<resources>
<string name="app_name">lobchat</string>
<string name="app_name">LobeChat</string>
<string name="enter_your_server_url">Enter your server URL</string>
<string name="send">Send</string>
<string name="app_logo">App Logo</string>

View file

@ -1,7 +1,2 @@
<resources>
<!-- 使主题继承自 Theme.AppCompat.DayNight.NoActionBar以获得系统默认的状态栏 -->
<style name="Theme.WebViewApp" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- 使用系统默认的颜色 -->
<item name="android:statusBarColor">?attr/colorPrimaryDark</item> <!-- 让状态栏使用主题色 -->
</style>
</resources>

View file

@ -1,5 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Lobchat" parent="android:Theme.Material.Light.NoActionBar" />
<!-- 使主题继承自 Theme.AppCompat.DayNight.NoActionBar以获得系统默认的状态栏 -->
<style name="Theme.WebViewApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="android:statusBarColor">
@color/purple_dark_9
</item>
<item name="android:navigationBarColor">
@color/design_default_color_background
</item>
<item name="android:windowTitleBackgroundStyle">
@color/design_default_color_background
</item>
</style>
</resources>