切换家庭,我的修改名称,手机号

This commit is contained in:
2026-05-11 17:50:35 +08:00
parent a8def9d719
commit e8de34b136
32 changed files with 721 additions and 84 deletions

View File

@@ -0,0 +1,48 @@
kotlin version: 2.2.10
error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker3282876021996141864.tmp
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
at org.gradle.internal.Factories$1.create(Factories.java:30)
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)

View File

@@ -0,0 +1,48 @@
kotlin version: 2.2.10
error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker2395130266242289833.tmp
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
at org.gradle.internal.Factories$1.create(Factories.java:30)
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)

View File

@@ -0,0 +1,65 @@
package com.example.defenseapplication.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.ItemSwitchFamilyBinding
import com.example.defenseapplication.model.FamilyItem
class FamilySwitchAdapter(
private val familyList: List<FamilyItem>,
private val onItemClickListener: (FamilyItem) -> Unit
) : RecyclerView.Adapter<FamilySwitchAdapter.FamilyViewHolder>() {
private var selectedPosition = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FamilyViewHolder {
val binding = ItemSwitchFamilyBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return FamilyViewHolder(binding)
}
override fun onBindViewHolder(holder: FamilyViewHolder, position: Int) {
holder.bind(familyList[position], position == selectedPosition)
}
override fun getItemCount(): Int = familyList.size
fun selectPosition(position: Int) {
val previousPosition = selectedPosition
selectedPosition = position
notifyItemChanged(previousPosition)
notifyItemChanged(selectedPosition)
}
fun getSelectedItem(): FamilyItem = familyList[selectedPosition]
inner class FamilyViewHolder(
private val binding: ItemSwitchFamilyBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: FamilyItem, isSelected: Boolean) {
binding.tvFamilyName.text = item.name
binding.root.setBackgroundColor(
ContextCompat.getColor(
binding.root.context,
if (isSelected) R.color.bg_gray else R.color.white
)
)
binding.root.setOnClickListener {
val position = bindingAdapterPosition
if (position != RecyclerView.NO_POSITION) {
selectPosition(position)
onItemClickListener(item)
}
}
}
}
}

View File

@@ -21,11 +21,14 @@ class ConnectDeviceActivity : AppCompatActivity() {
private lateinit var binding: ConnectDeviceActivityBinding
private val handler = Handler(Looper.getMainLooper())
// 每一帧对应的步骤文字和提示
private val steps = listOf(
StepData("请保持手机蓝牙开启并将手机尽量靠近设备", "向设备传输信息","设备连接网络"),
StepData("请保持手机蓝牙开启并将手机尽量靠近设备", "设备连接网络请将设备尽量靠近路由器",""),
StepData("请将设备尽量靠近路由器", "","")
// 用 lazy 延迟初始化
private val steps: List<StepData> by lazy {
listOf(
StepData(getString(R.string.bluetooth_keep_enabled), getString(R.string.transmit_info_to_device), getString(R.string.device_connect_network)),
StepData(getString(R.string.bluetooth_keep_enabled), getString(R.string.device_connect_near_router), ""),
StepData(getString(R.string.keep_device_near_router), "", "")
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@@ -11,6 +11,7 @@ import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.PersonalFragmentBinding
import com.example.defenseapplication.personal.PersonalProfileActivity
import com.example.defenseapplication.utils.LanguageUtil
import com.example.defenseapplication.view.FamilySwitchDialog
import com.example.defenseapplication.view.LanguageDialog
import com.gyf.immersionbar.ImmersionBar
@@ -43,6 +44,10 @@ class PersonalFragment : Fragment() {
binding.itemLanguage.setOnClickListener {
showLanguageDialog()
}
// 切换家庭点击事件
binding.itemSwitchFamily.setOnClickListener {
showFamilySwitchDialog()
}
return binding.root
}
@@ -67,6 +72,16 @@ class PersonalFragment : Fragment() {
dialog.show()
}
/**
* 显示家庭切换对话框
*/
private fun showFamilySwitchDialog() {
val dialog = FamilySwitchDialog(requireContext()) { familyName ->
binding.tvCurrentFamily.text = familyName
}
dialog.show()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // 避免内存泄漏

View File

@@ -0,0 +1,6 @@
package com.example.defenseapplication.model
data class FamilyItem(
val id: String,
val name: String
)

View File

@@ -5,9 +5,13 @@ import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import android.widget.Toast
import com.bumptech.glide.Glide
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.PersonalProfileActivityBinding
import com.example.defenseapplication.view.CustomDialogFragmentText
import com.example.defenseapplication.view.PhoneModifyDialogFragment
import com.gyf.immersionbar.ImmersionBar
class PersonalProfileActivity : AppCompatActivity() {
@@ -15,24 +19,19 @@ class PersonalProfileActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = PersonalProfileActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
ImmersionBar.with(this)
.statusBarDarkFont(true)
.titleBar(binding.topBar)
.init()
ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
initView()
}
private fun initView() {
binding.ivBack.setOnClickListener { finish() }
binding.ivBack.setOnClickListener {
finish()
}
Glide.with(this)
.load(R.drawable.img)
@@ -42,9 +41,43 @@ class PersonalProfileActivity : AppCompatActivity() {
binding.tvNickname.text = getString(R.string.nickname_default)
binding.tvPhone.text = "13589898989"
// 点击行可跳转到“修改昵称/修改手机号”等页面
//binding.itemAvatar.setOnClickListener { /* TODO */ }
//binding.itemNickname.setOnClickListener { /* TODO */ }
//binding.itemPhone.setOnClickListener { /* TODO */ }
binding.itemNickname.setOnClickListener {
showNicknameDialog()
}
binding.itemPhone.setOnClickListener {
showPhoneDialog()
}
}
private fun showNicknameDialog() {
val currentNickname = binding.tvNickname.text.toString()
val dialog = CustomDialogFragmentText()
.setTitle(getString(R.string.set_name))
.setMessage("")
.setInputHint(getString(R.string.nickname_hint))
.setInputText(currentNickname)
.setShowInput(true)
.setPositiveText(getString(R.string.confirm))
.setNegativeText("")
.setOnConfirmListener { newNickname ->
if (newNickname.isNotBlank()) {
binding.tvNickname.text = newNickname
Toast.makeText(this, getString(R.string.operation_success), Toast.LENGTH_SHORT).show()
}
}
dialog.show(supportFragmentManager, "nickname_dialog")
}
private fun showPhoneDialog() {
val dialog = PhoneModifyDialogFragment()
.setTitle(getString(R.string.modify_phone))
.setNegativeText(getString(R.string.cancel))
.setPositiveText(getString(R.string.verify_and_bind))
.setOnConfirmListener { phone, code ->
binding.tvPhone.text = phone
Toast.makeText(this, getString(R.string.operation_success), Toast.LENGTH_SHORT).show()
}
dialog.show(supportFragmentManager, "phone_dialog")
}
}

View File

@@ -60,12 +60,14 @@ class CustomDialogFragmentText : DialogFragment() {
return this
}
fun setOnConfirmListener(listener: (String) -> Unit) {
fun setOnConfirmListener(listener: (String) -> Unit): CustomDialogFragmentText {
this.onConfirmListener = listener
return this
}
fun setOnDismissListener(listener: () -> Unit) {
fun setOnDismissListener(listener: () -> Unit): CustomDialogFragmentText {
this.onDismissListener = listener
return this
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

View File

@@ -0,0 +1,69 @@
package com.example.defenseapplication.view
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.Gravity
import android.view.Window
import android.view.WindowManager
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.defenseapplication.R
import com.example.defenseapplication.adapter.FamilySwitchAdapter
import com.example.defenseapplication.model.FamilyItem
/**
* 家庭切换对话框
*/
class FamilySwitchDialog(
context: Context,
private val onFamilySelected: (String) -> Unit
) : Dialog(context, R.style.BottomDialogStyle) {
private lateinit var adapter: FamilySwitchAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.dialog_family_switch)
val window = window
val params = window?.attributes
params?.width = WindowManager.LayoutParams.MATCH_PARENT
params?.height = WindowManager.LayoutParams.WRAP_CONTENT
params?.gravity = Gravity.BOTTOM
window?.attributes = params
window?.setBackgroundDrawableResource(android.R.color.transparent)
window?.setDimAmount(0.5f)
initViews()
}
private fun initViews() {
val tvCancel = findViewById<TextView>(R.id.tvCancel)
val tvConfirm = findViewById<TextView>(R.id.tvConfirm)
val rvMessageList = findViewById<RecyclerView>(R.id.rvMessageList)
val familyList = listOf(
FamilyItem("1", context.getString(R.string.my_family)),
FamilyItem("2", context.getString(R.string.zhangsan_family))
)
adapter = FamilySwitchAdapter(familyList) { familyItem ->
}
rvMessageList.layoutManager = LinearLayoutManager(context)
rvMessageList.adapter = adapter
tvCancel.setOnClickListener {
dismiss()
}
tvConfirm.setOnClickListener {
val selectedFamily = adapter.getSelectedItem()
onFamilySelected(selectedFamily.name)
dismiss()
}
}
}

View File

@@ -0,0 +1,134 @@
package com.example.defenseapplication.view
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.os.CountDownTimer
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.DialogPhoneModifyBinding
//手机号弹窗
class PhoneModifyDialogFragment : DialogFragment() {
private lateinit var binding: DialogPhoneModifyBinding
private var title: String = ""
private var negativeText: String = ""
private var positiveText: String = ""
private var onConfirmListener: ((String, String) -> Unit)? = null
private var onDismissListener: (() -> Unit)? = null
private var countDownTimer: CountDownTimer? = null
fun setTitle(title: String): PhoneModifyDialogFragment {
this.title = title
return this
}
fun setNegativeText(text: String): PhoneModifyDialogFragment {
this.negativeText = text
return this
}
fun setPositiveText(text: String): PhoneModifyDialogFragment {
this.positiveText = text
return this
}
fun setOnConfirmListener(listener: (phone: String, code: String) -> Unit): PhoneModifyDialogFragment {
this.onConfirmListener = listener
return this
}
fun setOnDismissListener(listener: () -> Unit): PhoneModifyDialogFragment {
this.onDismissListener = listener
return this
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.window?.let {
val params = it.attributes
params.gravity = Gravity.CENTER
params.width = WindowManager.LayoutParams.MATCH_PARENT
params.height = WindowManager.LayoutParams.WRAP_CONTENT
it.attributes = params
it.setBackgroundDrawableResource(R.drawable.round_bg)
}
return dialog
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DialogPhoneModifyBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (negativeText.isEmpty()) negativeText = getString(R.string.cancel)
if (positiveText.isEmpty()) positiveText = getString(R.string.confirm)
binding.tvTitle.text = title
binding.btnNegative.text = negativeText
binding.btnPositive.text = positiveText
binding.tvSendCode.setOnClickListener {
val phone = binding.etPhone.text.toString()
if (phone.length != 11) {
ToastUtils.showToast(requireContext(), getString(R.string.invalid_phone))
return@setOnClickListener
}
startCountDown()
}
binding.btnNegative.setOnClickListener {
dismiss()
}
binding.btnPositive.setOnClickListener {
val phone = binding.etPhone.text.toString()
val code = binding.etCode.text.toString()
if (phone.length != 11) {
ToastUtils.showToast(requireContext(), getString(R.string.invalid_phone))
return@setOnClickListener
}
if (code.isEmpty()) {
ToastUtils.showToast(requireContext(), getString(R.string.enter_verification_code))
return@setOnClickListener
}
onConfirmListener?.invoke(phone, code)
dismiss()
}
}
private fun startCountDown() {
binding.tvSendCode.isEnabled = false
countDownTimer = object : CountDownTimer(60000, 1000) {
override fun onTick(millisUntilFinished: Long) {
binding.tvSendCode.text = String.format("%ds", millisUntilFinished / 1000)
}
override fun onFinish() {
binding.tvSendCode.text = getString(R.string.send_sms_code)
binding.tvSendCode.isEnabled = true
}
}
countDownTimer?.start()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
countDownTimer?.cancel()
onDismissListener?.invoke()
onConfirmListener = null
onDismissListener = null
}
}

View File

@@ -10,6 +10,14 @@ object ToastUtils {
private var currentToast: Toast? = null
fun showToast(context: Context, message: String, duration: Int = Toast.LENGTH_SHORT) {
currentToast?.cancel()
val toast = Toast.makeText(context.applicationContext, message, duration)
toast.setGravity(Gravity.CENTER, 0, 0)
currentToast = toast
toast.show()
}
/**
* 显示成功提示
* @param message 提示文字

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%p" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="100%p"
android:toYDelta="0" />

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E6FBF2" />
<corners android:radius="30dp" />
</shape>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FAEEE5" />
<corners android:radius="30dp" />
</shape>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E9F4FF" />
<corners android:radius="30dp" />
</shape>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/gray"/>
<corners android:radius="16dp"/>
</shape>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -91,7 +91,7 @@
android:id="@+id/successText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接成功"
android:text="@string/connection_success"
android:textSize="16dp" />
</LinearLayout>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white"
android:orientation="vertical">
<LinearLayout
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tvCancel"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/cancel"
android:textColor="@color/gray"
android:textSize="14dp"
android:clickable="true"
android:focusable="true" />
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/tvConfirm"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/confirm"
android:textColor="@color/green"
android:textSize="14dp"
android:clickable="true"
android:focusable="true" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMessageList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingStart="14dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="16dp"/>
</LinearLayout>

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/round_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingStart="24dp"
android:paddingTop="32dp"
android:paddingEnd="24dp"
android:paddingBottom="28dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold" />
<EditText
android:id="@+id/et_phone"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginTop="18dp"
android:background="@drawable/setting_gray_bg"
android:gravity="center_vertical"
android:hint="@string/phone_hint"
android:inputType="phone"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginTop="12dp"
android:background="@drawable/setting_gray_bg">
<EditText
android:id="@+id/et_code"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:hint="@string/sms_code_hint"
android:inputType="number"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:background="@null"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_send_code"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:gravity="center"
android:text="@string/send_sms_code"
android:textColor="@color/green"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/v_divider_top"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dialog_view" />
<LinearLayout
android:id="@+id/layout_actions"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal">
<TextView
android:id="@+id/btn_negative"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold" />
<View
android:id="@+id/v_divider_center"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/dialog_view" />
<TextView
android:id="@+id/btn_positive"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textColor="@color/green"
android:textSize="16dp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/itemFamily1"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="30dp">
<TextView
android:id="@+id/tvFamilyName"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/my_family"
android:textColor="@color/black"
android:textSize="16dp" />
</LinearLayout>

View File

@@ -82,10 +82,8 @@
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_detail_border"
android:padding="8dp"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="@drawable/switch_family" />
<TextView
@@ -123,10 +121,8 @@
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_user_manage"
android:padding="8dp"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="@drawable/user_manage" />
<TextView
@@ -154,10 +150,8 @@
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_pwd_manager"
android:padding="8dp"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="@drawable/pwd_manager" />
<TextView
@@ -185,10 +179,8 @@
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="44dp"
android:layout_height="44dp"
android:background="@drawable/bg_face_manage"
android:padding="8dp"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="@drawable/face_manage" />
<TextView
@@ -213,21 +205,20 @@
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<ImageView
android:layout_width="42dp"
android:layout_height="42dp"
android:src="@drawable/voice_translation" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/language_settings"
android:layout_marginStart="16dp"
android:textColor="@color/black"
android:textSize="16dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tvCurrentLanguage"
android:layout_width="wrap_content"
@@ -242,7 +233,6 @@
android:layout_marginStart="8dp"
android:src="@drawable/right_back" />
</LinearLayout>
</LinearLayout>
<Space
android:layout_width="match_parent"

View File

@@ -9,34 +9,30 @@
android:orientation="vertical"
tools:context=".personal.PersonalProfileActivity">
<androidx.constraintlayout.widget.ConstraintLayout
<!-- 标题栏 -->
<LinearLayout
android:id="@+id/topBar"
android:layout_width="match_parent"
android:layout_height="56dp">
android:layout_height="56dp"
android:gravity="center_vertical"
android:paddingHorizontal="16dp">
<ImageView
android:id="@+id/ivBack"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:src="@mipmap/back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:src="@drawable/back" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/personal_info"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:textStyle="bold" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"

View File

@@ -235,6 +235,12 @@
<string name="wifi_connection_failed">WiFi连接失败</string>
<string name="wifi_connection_success">WiFi连接成功</string>
<string name="connect_device">连接设备</string>
<string name="connection_success">连接成功</string>
<string name="bluetooth_keep_enabled">请保持手机蓝牙开启并将手机尽量靠近设备</string>
<string name="transmit_info_to_device">向设备传输信息</string>
<string name="device_connect_network">设备连接网络</string>
<string name="device_connect_near_router">设备连接网络请将设备尽量靠近路由器</string>
<string name="keep_device_near_router">请将设备尽量靠近路由器</string>
<!-- Dialog -->
<string name="tip">提示</string>
@@ -366,4 +372,7 @@
<string name="code_sent_to">验证码已发送至 %s</string>
<string name="sms_login_success_title">登录成功</string>
<string name="password_login_success_title">登录成功</string>
<string name="modify_phone">修改手机号</string>
<string name="invalid_phone">手机号格式不正确</string>
<string name="verify_and_bind">验证并绑定</string>
</resources>

View File

@@ -17,5 +17,6 @@
<color name="bg_gray">#F7F7F7</color>
<color name="setting_gray">#F3F3F3</color>
<color name="ic_blake">#111111</color>
<color name="green_light">#E8F7F7</color>
</resources>

View File

@@ -103,6 +103,8 @@
<string name="add_user">Add User</string>
<string name="admin">Admin</string>
<string name="member">Member</string>
<string name="normal_member">Ordinary Member</string>
<string name="zhangsan_family">Zhang San Family</string>
<string name="phone_number">Phone Number</string>
<string name="enter_nickname">Enter nickname</string>
@@ -208,6 +210,12 @@
<string name="wifi_connection_failed">WiFi Connection failed</string>
<string name="wifi_connection_success">WiFi Connected successfully</string>
<string name="connect_device">Connect Device</string>
<string name="connection_success">Connected successfully</string>
<string name="bluetooth_keep_enabled">Please keep Bluetooth on and move your phone closer to the device</string>
<string name="transmit_info_to_device">Transmitting information to the device</string>
<string name="device_connect_network">Device connecting to the network</string>
<string name="device_connect_near_router">Please move the device closer to the router while connecting to the network</string>
<string name="keep_device_near_router">Please move the device closer to the router</string>
<!-- Dialog -->
<string name="tip">Tip</string>
@@ -359,6 +367,9 @@
<string name="auto_mode_notice">Auto Mode Instructions</string>
<string name="know_and_agree">I have read and agree</string>
<string name="auto_mode_notice_content">After enabling Full Auto Mode, the device/system will operate independently and automatically execute preset procedures without manual intervention.During operation, do not arbitrarily power off, force a restart, block sensor components or disassemble the device privately, so as to avoid program abnormalities and operation interruption. Full Auto Mode is only applicable to standard and conventional scenarios. Under special working conditions, abnormal environments or temporary special requirements, please manually switch to manual mode.The system will automatically identify normal status and make adaptive adjustments. In case of faults such as alarms, stuttering or abnormal prompts, immediately pause Full Auto Mode, troubleshoot the problem before restarting.Do not place sundries or dangerous goods within the automatic operation range. Keep the working area clean and unobstructed to prevent equipment collision, jamming and safety accidents.Operation data and execution records of Full Auto Mode will be automatically saved. Do not arbitrarily delete or tamper with system configuration parameters to avoid operational logic disorder.Check the device status, power level, network connection and hardware loss regularly on a daily basis to ensure stable and long-term operation of Full Auto Mode. Minors and irrelevant personnel are prohibited from touching or operating the Full Auto Mode switch and setting panel to prevent malfunctions and risks caused by misoperation.</string>
<string name="modify_phone">Modify Phone</string>
<string name="invalid_phone">Invalid phone number format</string>
<string name="verify_and_bind">Verify and Bind</string>
<string name="device_running_days">Device has been running for %d days, please maintain in time</string>

View File

@@ -6,4 +6,17 @@
</style>
<style name="Theme.DefenseApplication" parent="Base.Theme.DefenseApplication" />
<style name="BottomDialogStyle" parent="@android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@style/BottomDialogAnimation</item>
</style>
<style name="BottomDialogAnimation">
<item name="android:windowEnterAnimation">@anim/slide_up</item>
<item name="android:windowExitAnimation">@anim/slide_down</item>
</style>
</resources>