feat(设置界面): 添加长按重启应用功能并优化界面布局

- 在设置界面新增长按重启按钮,包含进度条动画反馈
- 添加自定义进度条样式以增强视觉体验
- 优化IP配置区域的布局结构,将保存按钮与输入框水平排列
- 移除MqttManager中冗余的注释
- 更新字符串资源以支持新功能
This commit is contained in:
2026-03-10 20:40:37 +08:00
parent 15fba9d1f9
commit 03cc654468
5 changed files with 135 additions and 47 deletions

View File

@@ -56,7 +56,7 @@ class MqttManager(private val context: Context, private val serverIp: String) {
isAutomaticReconnect = false
isCleanSession = true
connectionTimeout = 10
keepAliveInterval = 60 // 设置心跳间隔为60秒
keepAliveInterval = 60
userName = "lzwc"
password = "Lzwc@4187.".toCharArray()
}

View File

@@ -1,35 +1,38 @@
package com.example.lzwcai_terminal_temi
import android.animation.ValueAnimator
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.lzwcai_terminal_temi.databinding.ActivitySettingsBinding
import kotlin.system.exitProcess
class SettingsActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsBinding
private var restartAnimator: ValueAnimator? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
// 默认隐藏软键盘
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
val prefs = getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
val savedIp = prefs.getString("network_ip", "")
binding.etIpAddress.setText(savedIp)
// 点击外部隐藏键盘
binding.root.setOnClickListener {
hideKeyboard()
}
binding.root.setOnClickListener { hideKeyboard() }
binding.btnSave.setOnClickListener {
hideKeyboard()
@@ -50,6 +53,59 @@ class SettingsActivity : AppCompatActivity() {
finish()
}
setupRestartButton()
}
private fun setupRestartButton() {
binding.btnRestart.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
startRestartAnimation()
true
}
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> {
cancelRestartAnimation()
true
}
else -> false
}
}
}
private fun startRestartAnimation() {
binding.restartProgressBar.visibility = View.VISIBLE
restartAnimator = ValueAnimator.ofInt(0, 100).apply {
duration = 3000
addUpdateListener { animation ->
binding.restartProgressBar.progress = animation.animatedValue as Int
}
addListener(object : android.animation.Animator.AnimatorListener {
override fun onAnimationEnd(animation: android.animation.Animator) {
if (binding.restartProgressBar.progress == 100) {
restartApplication()
}
}
override fun onAnimationStart(animation: android.animation.Animator) {}
override fun onAnimationCancel(animation: android.animation.Animator) {}
override fun onAnimationRepeat(animation: android.animation.Animator) {}
})
start()
}
}
private fun cancelRestartAnimation() {
restartAnimator?.cancel()
binding.restartProgressBar.progress = 0
binding.restartProgressBar.visibility = View.INVISIBLE
}
private fun restartApplication() {
val intent = packageManager.getLaunchIntentForPackage(packageName)
val pendingIntent = PendingIntent.getActivity(this, 123456, intent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent)
exitProcess(0)
}
private fun hideKeyboard() {

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dp" />
<solid android:color="#E0E0E0" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dp" />
<solid android:color="#4CAF50" />
</shape>
</clip>
</item>
</layer-list>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"
android:fillViewport="true">
@@ -9,7 +10,6 @@
android:layout_height="wrap_content"
android:padding="24dp">
<!-- 返回按钮 -->
<ImageButton
android:id="@+id/btnBack"
android:layout_width="50dp"
@@ -20,7 +20,6 @@
android:contentDescription="@string/btn_back"
android:src="@android:drawable/ic_menu_revert" />
<!-- 标题 -->
<TextView
android:id="@+id/tvSettingsTitle"
android:layout_width="wrap_content"
@@ -31,35 +30,21 @@
android:textSize="32sp"
android:textStyle="bold" />
<!-- IP 配置部分 -->
<LinearLayout
android:id="@+id/ipConfigLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tvSettingsTitle"
android:layout_marginTop="24dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/label_ip_config"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/etIpAddress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:hint="@string/hint_ip_address"
android:inputType="number|numberDecimal"
android:digits="0123456789."
@@ -73,15 +58,44 @@
android:text="@string/btn_save"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
<!-- 日志部分 -->
<LinearLayout
android:id="@+id/restartLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ipConfigLayout"
android:layout_marginTop="32dp"
android:gravity="center"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/btnRestart"
android:layout_width="200dp"
android:layout_height="80dp"
android:text="@string/btn_restart_app"
android:textSize="18sp" />
<ProgressBar
android:id="@+id/restartProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200dp"
android:layout_height="80dp"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/custom_progress_bar"
android:visibility="invisible" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/restartLayout"
android:layout_marginTop="32dp"
android:orientation="vertical">
<View

View File

@@ -16,4 +16,5 @@
<string name="log_placeholder">日志将显示在这里...</string>
<string name="btn_random_expression">随机表情</string>
<string name="btn_speak">让机器人说话</string>
<string name="btn_restart_app">长按重启应用</string>
</resources>