操作密码
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package com.example.defenseapplication.bean
|
||||
|
||||
data class VerifyOptionPasswordRequest(
|
||||
val optionPassword: String
|
||||
)
|
||||
@@ -8,6 +8,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.UserInfoBean
|
||||
import com.example.defenseapplication.databinding.PersonalFragmentBinding
|
||||
@@ -203,8 +204,13 @@ class PersonalFragment : Fragment() {
|
||||
binding.tvPhone.text = it
|
||||
}
|
||||
userInfo.avatar?.let {
|
||||
val requestOptions = RequestOptions()
|
||||
.placeholder(R.drawable.img) // 加载中显示
|
||||
.error(R.drawable.img) // 失败时显示
|
||||
|
||||
Glide.with(this)
|
||||
.load(it)
|
||||
.load(it) // 如果 avatar 为 null,Glide 会直接回调 error
|
||||
.apply(requestOptions)
|
||||
.circleCrop()
|
||||
.into(binding.ivAvatar)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.example.defenseapplication.personal
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.blankj.utilcode.util.SPUtils
|
||||
@@ -36,45 +38,49 @@ class OperationPasswordActivity : AppCompatActivity() {
|
||||
true -> {
|
||||
binding.etPassword.isEnabled = true
|
||||
binding.etConfirmPassword.isEnabled = true
|
||||
binding.btnConfirmReset.isEnabled = true
|
||||
Toast.makeText(this, getString(R.string.operation_password_enabled), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
false -> {
|
||||
binding.etPassword.isEnabled = false
|
||||
binding.etConfirmPassword.isEnabled = false
|
||||
binding.btnConfirmReset.isEnabled = false
|
||||
SPUtils.getInstance().remove("operation_password")
|
||||
Toast.makeText(this, getString(R.string.operation_password_disabled), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnConfirmReset.setOnClickListener {
|
||||
val password = binding.etPassword.text.toString()
|
||||
val confirmPassword = binding.etConfirmPassword.text.toString()
|
||||
binding.etPassword.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
|
||||
if (password.isEmpty()) {
|
||||
Toast.makeText(this, getString(R.string.password_cannot_empty), Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
autoValidatePassword()
|
||||
}
|
||||
})
|
||||
|
||||
if (password.length != 6) {
|
||||
Toast.makeText(this, getString(R.string.password_must_be_6_digits), Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
binding.etConfirmPassword.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
autoValidatePassword()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (confirmPassword.isEmpty()) {
|
||||
Toast.makeText(this, getString(R.string.please_confirm_password), Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
private fun autoValidatePassword() {
|
||||
val password = binding.etPassword.text.toString()
|
||||
val confirmPassword = binding.etConfirmPassword.text.toString()
|
||||
|
||||
if (password != confirmPassword) {
|
||||
if (password.length == 6 && confirmPassword.length == 6) {
|
||||
if (password == confirmPassword) {
|
||||
SPUtils.getInstance().put("operation_password", password)
|
||||
Toast.makeText(this, getString(R.string.operation_success), Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this, getString(R.string.password_mismatch), Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
SPUtils.getInstance().put("operation_password", password)
|
||||
Toast.makeText(this, getString(R.string.operation_success), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,14 @@ import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import com.example.defenseapplication.databinding.PasswordManagementActivityBinding
|
||||
import com.example.defenseapplication.view.PasswordInputDialog
|
||||
import com.blankj.utilcode.util.SPUtils
|
||||
import com.example.defenseapplication.utils.RetrofitNetwork
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
//密码管理
|
||||
class PasswordManagementActivity : AppCompatActivity() {
|
||||
|
||||
@@ -45,18 +49,26 @@ class PasswordManagementActivity : AppCompatActivity() {
|
||||
private fun showPasswordDialog() {
|
||||
passwordDialog = PasswordInputDialog(this).apply {
|
||||
setOnConfirmListener { inputPassword ->
|
||||
val savedPassword = SPUtils.getInstance().getString("operation_password", "111111")
|
||||
if (savedPassword.isEmpty()) {
|
||||
Toast.makeText(this@PasswordManagementActivity, getString(R.string.operation_password_not_set), Toast.LENGTH_SHORT).show()
|
||||
dismiss()
|
||||
return@setOnConfirmListener
|
||||
}
|
||||
if (inputPassword == savedPassword) {
|
||||
startActivity(Intent(this@PasswordManagementActivity, OperationPasswordActivity::class.java))
|
||||
dismiss()
|
||||
} else {
|
||||
showError(getString(R.string.password_error))
|
||||
clearPassword()
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val response = RetrofitNetwork.getNetworkService().verifyOptionPassword(VerifyOptionPasswordRequest(inputPassword))
|
||||
withContext(Dispatchers.Main) {
|
||||
if (response.code == 200) {
|
||||
startActivity(Intent(this@PasswordManagementActivity, OperationPasswordActivity::class.java))
|
||||
dismiss()
|
||||
} else {
|
||||
Toast.makeText(this@PasswordManagementActivity, response.msg ?: "校验失败", Toast.LENGTH_SHORT).show()
|
||||
showError(getString(R.string.password_error))
|
||||
clearPassword()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(this@PasswordManagementActivity, "网络请求失败", Toast.LENGTH_SHORT).show()
|
||||
showError(getString(R.string.password_error))
|
||||
clearPassword()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setOnDismissListener {
|
||||
|
||||
@@ -2,12 +2,14 @@ package com.example.defenseapplication.personal
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
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.bumptech.glide.request.RequestOptions
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.bean.UpdateUserInfo
|
||||
import com.example.defenseapplication.bean.UserInfoBean
|
||||
@@ -45,27 +47,18 @@ class PersonalProfileActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
userInfo?.let { info ->
|
||||
info.avatar?.let { avatarUrl ->
|
||||
Glide.with(this)
|
||||
.load(avatarUrl)
|
||||
.circleCrop()
|
||||
.into(binding.ivAvatar)
|
||||
} ?: run {
|
||||
Glide.with(this)
|
||||
.load(R.drawable.img)
|
||||
.circleCrop()
|
||||
.into(binding.ivAvatar)
|
||||
}
|
||||
Log.d("头像", "头像 URL = ${info.avatar}")
|
||||
val requestOptions = RequestOptions()
|
||||
.placeholder(R.drawable.img) // 加载中显示
|
||||
.error(R.drawable.img) // 失败时显示
|
||||
|
||||
binding.tvNickname.text = info.nickName ?: getString(R.string.nickname_default)
|
||||
binding.tvPhone.text = info.phonenumber ?: "13589898989"
|
||||
} ?: run {
|
||||
Glide.with(this)
|
||||
.load(R.drawable.img)
|
||||
.load(info.avatar) // 如果 avatar 为 null,Glide 会直接回调 error
|
||||
.apply(requestOptions)
|
||||
.circleCrop()
|
||||
.into(binding.ivAvatar)
|
||||
binding.tvNickname.text = getString(R.string.nickname_default)
|
||||
binding.tvPhone.text = "13589898989"
|
||||
binding.tvNickname.text = info.nickName ?: getString(R.string.nickname_default)
|
||||
binding.tvPhone.text = info.phonenumber ?: ""
|
||||
}
|
||||
|
||||
binding.itemNickname.setOnClickListener {
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.example.defenseapplication.bean.SwitchFamilyRequest
|
||||
import com.example.defenseapplication.bean.UpdatePassword
|
||||
import com.example.defenseapplication.bean.UpdateUserInfo
|
||||
import com.example.defenseapplication.bean.UserInfoBean
|
||||
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
@@ -156,6 +157,11 @@ interface ApiService {
|
||||
@POST("/app/retrievePassword")
|
||||
suspend fun retrievePassword(@Body request: ForgotRequest): GetCodeBean<ForgotRequest>
|
||||
|
||||
/**
|
||||
* 校验操作密码
|
||||
*/
|
||||
@POST("/app/verifyOptionPassword")
|
||||
suspend fun verifyOptionPassword(@Body request: VerifyOptionPasswordRequest): GetCodeBean<Any>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package com.example.defenseapplication.view
|
||||
package com.example.defenseapplication.personal
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.text.Editable
|
||||
import android.text.InputFilter
|
||||
import android.text.TextWatcher
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import com.example.defenseapplication.R
|
||||
import com.example.defenseapplication.databinding.DialogPasswordInputBinding
|
||||
@@ -18,6 +23,9 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
|
||||
private var onConfirmListener: ((String) -> Unit)? = null
|
||||
private var onDismissListener: (() -> Unit)? = null
|
||||
|
||||
// 6个密码输入框数组
|
||||
private lateinit var passwordEditTexts: Array<EditText>
|
||||
|
||||
init {
|
||||
initView()
|
||||
}
|
||||
@@ -26,68 +34,204 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
|
||||
binding = DialogPasswordInputBinding.inflate(LayoutInflater.from(context))
|
||||
setContentView(binding.root)
|
||||
|
||||
setCanceledOnTouchOutside(true)
|
||||
|
||||
window?.apply {
|
||||
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
val params = attributes
|
||||
params.gravity = Gravity.CENTER
|
||||
params.width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
// 设置弹窗宽度:屏幕宽度 - 左边距37 - 右边距36
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
val screenWidth = displayMetrics.widthPixels
|
||||
params.width = screenWidth - 73 // 37 + 36
|
||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
params.horizontalMargin = 40f
|
||||
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
|
||||
attributes = params
|
||||
}
|
||||
|
||||
// 初始化输入框数组
|
||||
passwordEditTexts = arrayOf(
|
||||
binding.etPwd0,
|
||||
binding.etPwd1,
|
||||
binding.etPwd2,
|
||||
binding.etPwd3,
|
||||
binding.etPwd4,
|
||||
binding.etPwd5
|
||||
)
|
||||
|
||||
setupPasswordInput()
|
||||
|
||||
binding.btnCancel.setOnClickListener {
|
||||
binding.ivClose.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.btnConfirm.setOnClickListener {
|
||||
val password = getPassword()
|
||||
if (password.length == 6) {
|
||||
onConfirmListener?.invoke(password)
|
||||
dismiss()
|
||||
}
|
||||
// 自动弹出键盘
|
||||
binding.root.post {
|
||||
passwordEditTexts[0].requestFocus()
|
||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.showSoftInput(passwordEditTexts[0], InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupPasswordInput() {
|
||||
val editTexts = listOf(
|
||||
binding.etPassword1,
|
||||
binding.etPassword2,
|
||||
binding.etPassword3,
|
||||
binding.etPassword4,
|
||||
binding.etPassword5,
|
||||
binding.etPassword6
|
||||
)
|
||||
// 为每个输入框设置监听器
|
||||
for (i in passwordEditTexts.indices) {
|
||||
val currentEt = passwordEditTexts[i]
|
||||
|
||||
editTexts.forEachIndexed { index, editText ->
|
||||
editText.setOnKeyListener { _, _, _ ->
|
||||
if (editText.text.isNotEmpty()) {
|
||||
if (index < editTexts.size - 1) {
|
||||
editTexts[index + 1].requestFocus()
|
||||
// 设置只能输入数字
|
||||
currentEt.filters = arrayOf(InputFilter.LengthFilter(1))
|
||||
|
||||
currentEt.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
// 用户手动输入或删除时清除错误
|
||||
if (count > 0 || before > 0) {
|
||||
clearError()
|
||||
}
|
||||
}
|
||||
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
val text = s?.toString() ?: ""
|
||||
|
||||
if (text.isNotEmpty()) {
|
||||
// 输入了内容,自动跳转到下一个输入框
|
||||
if (i < passwordEditTexts.size - 1) {
|
||||
// 检查是否按顺序输入:当前位置之前的所有输入框都必须有内容
|
||||
if (isInputInOrder(i)) {
|
||||
passwordEditTexts[i + 1].requestFocus()
|
||||
} else {
|
||||
// 不是按顺序输入,清空当前输入
|
||||
currentEt.text?.clear()
|
||||
}
|
||||
}
|
||||
// 检查是否已输入完6位密码
|
||||
checkPasswordComplete()
|
||||
} else {
|
||||
editText.clearFocus()
|
||||
// 删除了内容,自动跳转到上一个有内容的输入框
|
||||
if (currentEt.hasFocus()) {
|
||||
// 从当前位置往前查找第一个有内容的输入框
|
||||
val previousFilledIndex = findPreviousFilledIndex(i)
|
||||
if (previousFilledIndex >= 0) {
|
||||
passwordEditTexts[previousFilledIndex].requestFocus()
|
||||
// 选中内容,方便继续删除
|
||||
passwordEditTexts[previousFilledIndex].selectAll()
|
||||
} else if (i > 0) {
|
||||
// 如果前面都为空,保持在第一个输入框
|
||||
passwordEditTexts[0].requestFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 设置键盘监听器,处理当前框为空时按删除键的情况
|
||||
currentEt.setOnKeyListener { _, keyCode, event ->
|
||||
// 只处理删除键按下事件
|
||||
if (keyCode == android.view.KeyEvent.KEYCODE_DEL && event.action == android.view.KeyEvent.ACTION_DOWN) {
|
||||
val currentText = currentEt.text.toString()
|
||||
// 如果当前输入框为空,跳转到上一个有内容的输入框并删除
|
||||
if (currentText.isEmpty() && i > 0) {
|
||||
val previousFilledIndex = findPreviousFilledIndex(i)
|
||||
if (previousFilledIndex >= 0) {
|
||||
// 删除上一个输入框的内容
|
||||
passwordEditTexts[previousFilledIndex].text?.clear()
|
||||
// 继续向前查找下一个有内容的输入框
|
||||
val newPreviousIndex = findPreviousFilledIndex(previousFilledIndex)
|
||||
if (newPreviousIndex >= 0) {
|
||||
passwordEditTexts[newPreviousIndex].requestFocus()
|
||||
passwordEditTexts[newPreviousIndex].selectAll()
|
||||
} else {
|
||||
// 如果前面都为空,定位到第一个输入框
|
||||
passwordEditTexts[0].requestFocus()
|
||||
}
|
||||
return@setOnKeyListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
editText.setOnFocusChangeListener { v, hasFocus ->
|
||||
if (hasFocus) {
|
||||
(v as EditText).setSelection((v.text?.length ?: 0))
|
||||
// 设置触摸监听器,确保按顺序输入
|
||||
currentEt.setOnTouchListener { _, _ ->
|
||||
// 如果不是第一个输入框,检查前面的输入框是否都有内容
|
||||
if (i > 0) {
|
||||
val previousText = passwordEditTexts[i - 1].text.toString()
|
||||
if (previousText.isEmpty()) {
|
||||
// 前面的输入框为空,自动跳转到第一个空的输入框
|
||||
val firstEmptyIndex = findFirstEmptyIndex()
|
||||
if (firstEmptyIndex < i) {
|
||||
passwordEditTexts[firstEmptyIndex].requestFocus()
|
||||
return@setOnTouchListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否按顺序输入
|
||||
*/
|
||||
private fun isInputInOrder(currentIndex: Int): Boolean {
|
||||
for (i in 0 until currentIndex) {
|
||||
if (passwordEditTexts[i].text.toString().isEmpty()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找第一个空的输入框索引
|
||||
*/
|
||||
private fun findFirstEmptyIndex(): Int {
|
||||
for (i in passwordEditTexts.indices) {
|
||||
if (passwordEditTexts[i].text.toString().isEmpty()) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return passwordEditTexts.size
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定位置往前查找第一个有内容的输入框索引
|
||||
* @param startIndex 开始查找的位置(不包含)
|
||||
* @return 第一个有内容的输入框索引,未找到返回 -1
|
||||
*/
|
||||
private fun findPreviousFilledIndex(startIndex: Int): Int {
|
||||
for (i in startIndex - 1 downTo 0) {
|
||||
if (passwordEditTexts[i].text.toString().isNotEmpty()) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查密码是否输入完成
|
||||
*/
|
||||
private fun checkPasswordComplete() {
|
||||
val password = getPassword()
|
||||
if (password.length == 6) {
|
||||
autoVerifyPassword()
|
||||
}
|
||||
}
|
||||
|
||||
private fun autoVerifyPassword() {
|
||||
val password = getPassword()
|
||||
if (password.length == 6) {
|
||||
onConfirmListener?.invoke(password)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPassword(): String {
|
||||
return binding.etPassword1.text.toString() +
|
||||
binding.etPassword2.text.toString() +
|
||||
binding.etPassword3.text.toString() +
|
||||
binding.etPassword4.text.toString() +
|
||||
binding.etPassword5.text.toString() +
|
||||
binding.etPassword6.text.toString()
|
||||
val sb = StringBuilder()
|
||||
for (et in passwordEditTexts) {
|
||||
sb.append(et.text.toString())
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
fun setOnConfirmListener(listener: (String) -> Unit): PasswordInputDialog {
|
||||
@@ -103,6 +247,15 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
|
||||
fun showError(message: String) {
|
||||
binding.tvError.text = message
|
||||
binding.tvError.visibility = View.VISIBLE
|
||||
shakePasswordInput()
|
||||
}
|
||||
|
||||
private fun shakePasswordInput() {
|
||||
val shakeAnimation = AnimationUtils.loadAnimation(context, R.anim.shake)
|
||||
// 对每个输入框应用抖动动画
|
||||
for (et in passwordEditTexts) {
|
||||
et.startAnimation(shakeAnimation)
|
||||
}
|
||||
}
|
||||
|
||||
fun clearError() {
|
||||
@@ -111,16 +264,16 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
|
||||
}
|
||||
|
||||
fun clearPassword() {
|
||||
binding.etPassword1.text?.clear()
|
||||
binding.etPassword2.text?.clear()
|
||||
binding.etPassword3.text?.clear()
|
||||
binding.etPassword4.text?.clear()
|
||||
binding.etPassword5.text?.clear()
|
||||
binding.etPassword6.text?.clear()
|
||||
binding.etPassword1.requestFocus()
|
||||
for (et in passwordEditTexts) {
|
||||
et.text?.clear()
|
||||
}
|
||||
passwordEditTexts[0].requestFocus()
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
// 隐藏键盘
|
||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(passwordEditTexts[0].windowToken, 0)
|
||||
super.dismiss()
|
||||
onDismissListener?.invoke()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user