(Android) 在复选框 unchecked/checked 上,当用于 hide/show 密码时,编辑文本中的光标移动到初始位置

(Android) On checkbox unchecked/checked, the cursor in edit text shifts to initial position when used to hide/show password

我正在使用复选框来切换编辑文本中的密码可见性。基本上,当我 check/uncheck 复选框时,编辑文本的光标移动到密码文本中字符的初始位置。选中或取消选中复选框时,不应更改编辑文本中的光标位置。

请谁能提出为什么光标位置会改变?我该如何解决?

login_layout

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">


        <EditText
            android:id="@+id/etUsername"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:autofillHints="name"
            android:hint="Username"
            android:imeOptions="actionNext"
            android:inputType="text"
            android:maxLines="1"
            android:padding="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:id="@+id/etPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:autofillHints="password"
            android:hint="Password"
            android:imeOptions="actionDone"
            android:inputType="textPassword"
            android:maxLines="1"
            android:padding="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/etUsername" />

        <CheckBox
            android:id="@+id/imgTogglePassword"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="-5dp"
            android:layout_marginEnd="-5dp"
            android:button="@drawable/btn_toggle_password"
            android:padding="16dp"
            app:layout_constraintBottom_toBottomOf="@id/etPassword"
            app:layout_constraintEnd_toEndOf="@id/etPassword"
            app:layout_constraintTop_toTopOf="@id/etPassword" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

登录活动

import android.os.Bundle
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.testapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        initUI()
    }

    private fun initUI() {
        binding.imgTogglePassword.setOnCheckedChangeListener { _, isChecked ->
            // checkbox status is changed from uncheck to checked.
            if (!isChecked) {
                // hide password
                binding.etPassword.transformationMethod = PasswordTransformationMethod.getInstance()
            } else {
                // show password
                binding.etPassword.transformationMethod = HideReturnsTransformationMethod.getInstance()
            }
        }
    }


}

Login Page

Issue

你只需要使用这一行: binding.etPassword.setSelection(binding.etPassword.text.length) 如下代码。

 import android.os.Bundle
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.testapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        initUI()
    }

    private fun initUI() {
        binding.imgTogglePassword.setOnCheckedChangeListener { _, isChecked ->
            // checkbox status is changed from uncheck to checked.
            if (!isChecked) {
                // hide password
                binding.etPassword.transformationMethod = PasswordTransformationMethod.getInstance()
            } else {
                // show password
                binding.etPassword.transformationMethod = HideReturnsTransformationMethod.getInstance()
            }

           binding.etPassword.setSelection(binding.etPassword.text.length)
        }
    }


}

CheckBox 不是 show/hide 密码的常用方法。

尝试 endIconDrawable:

<com.google.android.material.textfield.TextInputLayout
    ...
    app:endIconDrawable="@drawable/selector_button_eye"
    app:endIconCheckable="true"
    app:endIconTint="@color/colorEyeButtonTint">

        <com.google.android.material.textfield.TextInputEditText
            ...
            android:inputType="textPassword" />

</com.google.android.material.textfield.TextInputLayout>

我不确定“endIconXXX”属性,因为我之前只使用过已弃用的 passwordToggleDrawable。但它们是相似的。