From e8de34b136caee1446bfec96da17c34e76c204dd Mon Sep 17 00:00:00 2001 From: maxinyu Date: Mon, 11 May 2026 17:50:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=AE=B6=E5=BA=AD=EF=BC=8C?= =?UTF-8?q?=E6=88=91=E7=9A=84=E4=BF=AE=E6=94=B9=E5=90=8D=E7=A7=B0=EF=BC=8C?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kotlin/errors/errors-1778489069185.log | 48 +++++++ .kotlin/errors/errors-1778489069506.log | 48 +++++++ .../adapter/FamilySwitchAdapter.kt | 65 +++++++++ .../home/ConnectDeviceActivity.kt | 13 +- .../home/PersonalFragment.kt | 15 ++ .../defenseapplication/model/FamilyItem.kt | 6 + .../personal/PersonalProfileActivity.kt | 59 ++++++-- .../view/CustomDialogFragment.kt | 6 +- .../view/FamilySwitchDialog.kt | 69 +++++++++ .../view/PhoneModifyDialogFragment.kt | 134 ++++++++++++++++++ .../defenseapplication/view/ToastUtils.kt | 8 ++ app/src/main/res/anim/slide_down.xml | 5 + app/src/main/res/anim/slide_up.xml | 5 + .../main/res/drawable/bg_detail_border.xml | 5 - app/src/main/res/drawable/bg_face_manage.xml | 5 - app/src/main/res/drawable/bg_pwd_manager.xml | 5 - app/src/main/res/drawable/face_manage.png | Bin 626 -> 1360 bytes app/src/main/res/drawable/pwd_manager.png | Bin 648 -> 1363 bytes app/src/main/res/drawable/rounded_gray_bg.xml | 6 + app/src/main/res/drawable/switch_family.png | Bin 595 -> 1346 bytes app/src/main/res/drawable/user_manage.png | Bin 651 -> 1357 bytes .../main/res/drawable/voice_translation.png | Bin 0 -> 2321 bytes .../res/layout/connect_device_activity.xml | 2 +- .../main/res/layout/dialog_family_switch.xml | 54 +++++++ .../main/res/layout/dialog_phone_modify.xml | 113 +++++++++++++++ .../main/res/layout/item_switch_family.xml | 18 +++ app/src/main/res/layout/personal_fragment.xml | 56 +++----- .../res/layout/personal_profile_activity.xml | 26 ++-- app/src/main/res/values-zh/strings.xml | 9 ++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 11 ++ app/src/main/res/values/themes.xml | 13 ++ 32 files changed, 721 insertions(+), 84 deletions(-) create mode 100644 .kotlin/errors/errors-1778489069185.log create mode 100644 .kotlin/errors/errors-1778489069506.log create mode 100644 app/src/main/java/com/example/defenseapplication/adapter/FamilySwitchAdapter.kt create mode 100644 app/src/main/java/com/example/defenseapplication/model/FamilyItem.kt create mode 100644 app/src/main/java/com/example/defenseapplication/view/FamilySwitchDialog.kt create mode 100644 app/src/main/java/com/example/defenseapplication/view/PhoneModifyDialogFragment.kt create mode 100644 app/src/main/res/anim/slide_down.xml create mode 100644 app/src/main/res/anim/slide_up.xml delete mode 100644 app/src/main/res/drawable/bg_detail_border.xml delete mode 100644 app/src/main/res/drawable/bg_face_manage.xml delete mode 100644 app/src/main/res/drawable/bg_pwd_manager.xml create mode 100644 app/src/main/res/drawable/rounded_gray_bg.xml create mode 100644 app/src/main/res/drawable/voice_translation.png create mode 100644 app/src/main/res/layout/dialog_family_switch.xml create mode 100644 app/src/main/res/layout/dialog_phone_modify.xml create mode 100644 app/src/main/res/layout/item_switch_family.xml diff --git a/.kotlin/errors/errors-1778489069185.log b/.kotlin/errors/errors-1778489069185.log new file mode 100644 index 0000000..00829bf --- /dev/null +++ b/.kotlin/errors/errors-1778489069185.log @@ -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) + + diff --git a/.kotlin/errors/errors-1778489069506.log b/.kotlin/errors/errors-1778489069506.log new file mode 100644 index 0000000..4a730dd --- /dev/null +++ b/.kotlin/errors/errors-1778489069506.log @@ -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) + + diff --git a/app/src/main/java/com/example/defenseapplication/adapter/FamilySwitchAdapter.kt b/app/src/main/java/com/example/defenseapplication/adapter/FamilySwitchAdapter.kt new file mode 100644 index 0000000..1ce576a --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/adapter/FamilySwitchAdapter.kt @@ -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, + private val onItemClickListener: (FamilyItem) -> Unit +) : RecyclerView.Adapter() { + + 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) + } + } + } + } +} diff --git a/app/src/main/java/com/example/defenseapplication/home/ConnectDeviceActivity.kt b/app/src/main/java/com/example/defenseapplication/home/ConnectDeviceActivity.kt index 6df6f66..dff2fd1 100644 --- a/app/src/main/java/com/example/defenseapplication/home/ConnectDeviceActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/home/ConnectDeviceActivity.kt @@ -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 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) diff --git a/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt b/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt index b8a7993..ef9d1c2 100644 --- a/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/home/PersonalFragment.kt @@ -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 // 避免内存泄漏 diff --git a/app/src/main/java/com/example/defenseapplication/model/FamilyItem.kt b/app/src/main/java/com/example/defenseapplication/model/FamilyItem.kt new file mode 100644 index 0000000..c984f37 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/model/FamilyItem.kt @@ -0,0 +1,6 @@ +package com.example.defenseapplication.model + +data class FamilyItem( + val id: String, + val name: String +) diff --git a/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt b/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt index 800fcde..881688b 100644 --- a/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/personal/PersonalProfileActivity.kt @@ -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() + } } -} \ No newline at end of file + + 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") + } +} diff --git a/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt b/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt index 9f6dfef..1f2a83f 100644 --- a/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/view/CustomDialogFragment.kt @@ -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 { diff --git a/app/src/main/java/com/example/defenseapplication/view/FamilySwitchDialog.kt b/app/src/main/java/com/example/defenseapplication/view/FamilySwitchDialog.kt new file mode 100644 index 0000000..0567437 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/view/FamilySwitchDialog.kt @@ -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(R.id.tvCancel) + val tvConfirm = findViewById(R.id.tvConfirm) + val rvMessageList = findViewById(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() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/defenseapplication/view/PhoneModifyDialogFragment.kt b/app/src/main/java/com/example/defenseapplication/view/PhoneModifyDialogFragment.kt new file mode 100644 index 0000000..190f022 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/view/PhoneModifyDialogFragment.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/defenseapplication/view/ToastUtils.kt b/app/src/main/java/com/example/defenseapplication/view/ToastUtils.kt index 0155d7e..8cee0a7 100644 --- a/app/src/main/java/com/example/defenseapplication/view/ToastUtils.kt +++ b/app/src/main/java/com/example/defenseapplication/view/ToastUtils.kt @@ -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 提示文字 diff --git a/app/src/main/res/anim/slide_down.xml b/app/src/main/res/anim/slide_down.xml new file mode 100644 index 0000000..351bdee --- /dev/null +++ b/app/src/main/res/anim/slide_down.xml @@ -0,0 +1,5 @@ + + diff --git a/app/src/main/res/anim/slide_up.xml b/app/src/main/res/anim/slide_up.xml new file mode 100644 index 0000000..8b06947 --- /dev/null +++ b/app/src/main/res/anim/slide_up.xml @@ -0,0 +1,5 @@ + + diff --git a/app/src/main/res/drawable/bg_detail_border.xml b/app/src/main/res/drawable/bg_detail_border.xml deleted file mode 100644 index ec78199..0000000 --- a/app/src/main/res/drawable/bg_detail_border.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/bg_face_manage.xml b/app/src/main/res/drawable/bg_face_manage.xml deleted file mode 100644 index eb0a1b1..0000000 --- a/app/src/main/res/drawable/bg_face_manage.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/bg_pwd_manager.xml b/app/src/main/res/drawable/bg_pwd_manager.xml deleted file mode 100644 index 150ba0f..0000000 --- a/app/src/main/res/drawable/bg_pwd_manager.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/face_manage.png b/app/src/main/res/drawable/face_manage.png index 0d27cdf4d999d1ec69277df4009f9a03e6aeed2b..7027a12f72bb2bff04cbb27cc20a54b0bdd35246 100644 GIT binary patch literal 1360 zcmV-W1+V&vP)9(E6#nj=siM}VA zdndJ6=AR4>J|I)+y)u#NmQ1Qw#&2GsJtdiR*6BoQ%K0+sUi!ObJiS*j%WQ|LiIQ9g z8=pqgBV+L792=j2;2@0IL3=YqVorh0&L?t^{u3~APBDs=+t)kjt4eItY?-{(E)(gq zB-c;O5o#T^T2agq*m%Fzl7CX|Q453;6&ZerMNh(?BSCqQg$;G3!Wygq9f1k0nn3HU?q_pL@6p{)=b)DqvK3a&ZyCFvxuCoQA@UtI~8w;hNUlzlT%!|!RAghhZjb}Y;PisSVIeHnxAnRmY>gyZEb;K!}3ew7KfFi#kShr z4AfDhi=Tzv^k`YW%w*tS{m!Y(PM5_U#>YwR`Or#=VLz6`ISe_XpAGPuY^;PEW{N2C&6_EWeKXkT#`OD%sXH~-HLcuqKb_?Hc z4bG?{a%Z$Wd3vPWw=9pe>Jx2R7IrbHZrfrHkVuyMmg6y|Nr|q?;lsAS3Ou;r3r5@S zd}TSb$}z^&+H!C89^on=Ll@kAThUl>F+jJZgn=KHAmmGVsM^Dten z!#s7MvUa@&)4IaVPw<1q*xesVV2T=DVm0t*@9=v#KLu>E6SnO@WleT*^P68>6a!+T zH*%R%%F&v(wtF1*P$NsMJ_&F9CbC19r~{!mech^xQEVunG~sjQnER;Nj~EkbB(V?I zp=SF|)FeBoPlsY^a>qf%C^i&OOc4I^_*jRIsA+hD>x=nT9UDrG>6_;UIHHc6CvWq< zI@<^ft%7*S$~*Zw1)^qaGnXlIDj!()yO>k+oaUJnh`M3I>L(a<_WE81QSZ1ESdUs%(&v=I%mjw(;h^pT-v|L3NF9T-9hZR))$DZu%I4r`J5!JY9Y(CG4 zyr1@3KG}@+biLVlu~a0gNeJ9s>$vZBx0R_`4Bv9Qde6% z2y3&4>$ODnC5b9dC$*_h9)|}K7M_j~c?VN`fC>)){Ko}4&6ebG?GcbyaEB7jXX=_} z>L1$=KikP)uAk6f-9d%`iegS{4UV^8$Rl3&A%$ zO8v>4X+9~>DKPDP8iVPE<`QG-o8QzL%&kiP2LJ&7|2ub$YybcN21!IgR09Bv75K)b SVh=_D0000A6-QXOaat?eF`kt6*N!@t_qz<_UYP(DYdV0%d=k^KEHHzMVG#Y7|XXb2d89 zNDmEkn$IKkxXLcvq-I<-8nO)N^b7s!GAJ6-nGiT0B zqS421>Z}=(Hu}gJQ`~pjOiaILCij16?qXw~Hu@MNZK#h@NDO-5q_G~FH)GQaW^%ZS zoze3MEhskjX`_!Z(snY3xztDs9UoKx_q=a*ly_sIID(O!ll&r?!(3`m z3!)hpI2P!`ADF__0~pWekc%taD~?*!q;{`Z`lCV5n#|0C86O?O=&%Ka0sp8;ZPtL) zijwaNIx}yw(`y)qgKU(*KzvezwOF&8UMMINss-%e1JNyU(00~hP1X+64uZ-psA_>s z@vwvyNMhr|#@b=iAOJdJqsXgEQecp=tWAba%{EZ)36%NL8MN)^!r-yA6y5@rH7%oY zM~m;4c0Cqh@*y@s_uPv+xm@^;TYV%8nS2fpl&>@{z`pTzIg*KNzgq?wbv@-f-Jt#3^!3MpFJA;6y}MEF zt*3yGo(A?#HqJNq3W=v088sKyO_4r26&on#w*=$?!aXt#uKc@YV^2n1HumB-GV1u@ z?U7Q=X|*-jPu|S=3`^v;>+Aevn)JMT;rA zYhc?3Z$t-$d&$U$sTS_;ZFLpqBGb9NT{DE8A`q literal 648 zcmV;30(bq1P)bG1&nBtOcA-p@WL)SN>^X*Q6zwIJ6*S81 z?r!v2eU1SFY_t@SJ29A1ObZy1E&OJHFp{N?wMoQMPse!8a;IpFzbBX8uyl{xSKCR*z zZ$B_nFc(!rzG<{H2)oJ!Q!e+JUS7Ci5vMAB=0jL-wf~nvs|(uIR=>eN00030|35;5 iwg3PC21!IgR09B}8>}&%eUkYA0000 + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/switch_family.png b/app/src/main/res/drawable/switch_family.png index a9d1ed61b4f9cc1069dd7cee03c7ef13c251c8a7..aad448d03928ba69e7d57f3391d5b2c787c134f7 100644 GIT binary patch literal 1346 zcmV-I1-<%-P)D(3dM<{U@DIrG*k;7`7phP|=q`cs2d?Kk{Fdu9lqgA%D!9c1xrEd~Ky{AJ02c=|M zIQ&$=m1+t`CbP92{V$iaIYlIy?na>Kk9CX1^@EW$>P(MY5S1r{&ZGPRpA5`XO~J@C z=BS%aRqqvPl&vU|U%iWn4;8x{;ZEcNBjZ$8Yd=w4D47xZx^iwPYdaO>5;JmV+MFpa zz{pb6g-TpWZM7=Q+;ZN*hy5ur()pmjFxLGb5?=mXRsqJWX+ua%{A&*if zzjUSjbjz7y0!HSFj7U*?tAsgkDVQg3U9^9yyRRwF+k)s1OPc#+lICuMDPQ6fjLggl z9-}gp;>gDRgpw1XfO1Gl)+A$(Ys@^GVfvps5prgz@YtcD@vjb<#XD6>q7#gaHiw-= zRolr-kcI7OXiz`xPu-WBzWafZsq4O(l%1uNPEG3ON1=i~4luH^Rc`jliwsL5?~M!) z@{2}{%PUUxQk}Z5by|(^H%P(*jO;v}Z>ld3$=4~RE+MoLGD?3S>aa3HcbQUq#}w?e zA=wGva#D+2E~+H*1REF`q8n9PHN-5w>CC)GW5#UAsBs!9OZDN=pAKUL6M9{@Lv9j zRZd2#*e>83q(Kwf=z(6nw0na3g?I!1vW8Z%0sFq4j?jW8wBu;S0)-Ivv=64|Z~j&^ z%IlTN7Sb%707*qoM6N<$ Eg2>o}>Hq)$ literal 595 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 diff --git a/app/src/main/res/layout/dialog_family_switch.xml b/app/src/main/res/layout/dialog_family_switch.xml new file mode 100644 index 0000000..199c2c8 --- /dev/null +++ b/app/src/main/res/layout/dialog_family_switch.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_phone_modify.xml b/app/src/main/res/layout/dialog_phone_modify.xml new file mode 100644 index 0000000..544929d --- /dev/null +++ b/app/src/main/res/layout/dialog_phone_modify.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_switch_family.xml b/app/src/main/res/layout/item_switch_family.xml new file mode 100644 index 0000000..51be970 --- /dev/null +++ b/app/src/main/res/layout/item_switch_family.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/personal_fragment.xml b/app/src/main/res/layout/personal_fragment.xml index 3eadf9f..7ad70e8 100644 --- a/app/src/main/res/layout/personal_fragment.xml +++ b/app/src/main/res/layout/personal_fragment.xml @@ -82,10 +82,8 @@ android:paddingHorizontal="16dp"> + - + android:text="@string/chinese" + android:textColor="@color/gray" + android:textSize="14sp" /> - - - - + - + + android:layout_height="56dp" + android:gravity="center_vertical" + android:paddingHorizontal="16dp"> + android:src="@drawable/back" /> - + android:textStyle="bold" /> + WiFi连接失败 WiFi连接成功 连接设备 + 连接成功 + 请保持手机蓝牙开启并将手机尽量靠近设备 + 向设备传输信息 + 设备连接网络 + 设备连接网络请将设备尽量靠近路由器 + 请将设备尽量靠近路由器 提示 @@ -366,4 +372,7 @@ 验证码已发送至 %s 登录成功 登录成功 + 修改手机号 + 手机号格式不正确 + 验证并绑定 \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f403e13..7fcf1d7 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -17,5 +17,6 @@ #F7F7F7 #F3F3F3 #111111 + #E8F7F7 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 210239b..3fee377 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -103,6 +103,8 @@ Add User Admin Member + Ordinary Member + Zhang San Family Phone Number Enter nickname @@ -208,6 +210,12 @@ WiFi Connection failed WiFi Connected successfully Connect Device + Connected successfully + Please keep Bluetooth on and move your phone closer to the device + Transmitting information to the device + Device connecting to the network + Please move the device closer to the router while connecting to the network + Please move the device closer to the router Tip @@ -359,6 +367,9 @@ Auto Mode Instructions I have read and agree 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. + Modify Phone + Invalid phone number format + Verify and Bind Device has been running for %d days, please maintain in time diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 48be0b6..9b74115 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -6,4 +6,17 @@ + + \ No newline at end of file