Visible password with TextInputLayouts passwordToggleEnabled

14,492

Solution 1

Easiest way is below Another solution is at last of this answer

private void setupPasswordToggleView() {
    final TextInputLayout textInputLayout = mRootView.findViewById(R.id.password);

    // You can skip post-call and write directly the code which is inside run method.
    // But to be safe (as toggle-view is child of TextInputLayout, post call
    // has been added.
    textInputLayout.post(new Runnable() {
        @Override
        public void run() {
            CheckableImageButton passwordToggleView = textInputLayout.findViewById(R.id.text_input_password_toggle);
            // passwordToggleView.toggle(); // Can not use as restricted to use same library group
            // passwordToggleView.setChecked(true); // Can not use as restricted to use same library group
            passwordToggleView.performClick();
        }
    });
}

Now let me explain the answer

While looking into code of TextInputLayout.java I found that, there is a layout design_text_input_password_icon.xml which is being added to TextInputLayout.java. Below is that code

private void updatePasswordToggleView() {
    if (mEditText == null) {
        // If there is no EditText, there is nothing to update
        return;
    }
    if (shouldShowPasswordIcon()) {
        if (mPasswordToggleView == null) {
            mPasswordToggleView = (CheckableImageButton) LayoutInflater.from(getContext())
                    .inflate(R.layout.design_text_input_password_icon, mInputFrame, false);
            mPasswordToggleView.setImageDrawable(mPasswordToggleDrawable);
            mPasswordToggleView.setContentDescription(mPasswordToggleContentDesc);
            mInputFrame.addView(mPasswordToggleView); // << HERE IS THAT
            .........
}

Now next target was to find design_text_input_password_icon.xml and lookup id of the toggle view. So found the layout design_text_input_password_icon.xml here and it has written as

18<android.support.design.widget.CheckableImageButton
19    xmlns:android="http://schemas.android.com/apk/res/android"
20    android:id="@+id/text_input_password_toggle"
21    android:layout_width="wrap_content"
22    android:layout_height="wrap_content"
23    android:layout_gravity="center_vertical|end|right"
24    android:background="?attr/selectableItemBackgroundBorderless"
25    android:minHeight="48dp"
26    android:minWidth="48dp"/>

I found the id text_input_password_toggle of that view and now everything was easy to just find that view in it's viewgroup and perform action on that.


Another solution would be to iterate childs of TextInputLayout and check if it is CheckableImageButton and then perform click on it. By this way there would not be dependancy on id of that view and if Android changes the id of view, our solution will still work. (Although they do not change id of a view in normal cases).

private void setupPasswordToggleViewMethod2() {
    final TextInputLayout textInputLayout = mRootView.findViewById(R.id.password);

    textInputLayout.post(new Runnable() {
        @Override
        public void run() {

            View toggleView = findViewByClassReference(textInputLayout, CheckableImageButton.class);
            if (toggleView != null) {
                toggleView.performClick();
            }
        }
    });
}

Where findViewByClassReference(View rootView, Class<T> clazz) original utility class is defined as below

public static <T extends View> T findViewByClassReference(View rootView, Class<T> clazz) {
    if(clazz.isInstance(rootView)) {
        return clazz.cast(rootView);
    }
    if(rootView instanceof ViewGroup) {
        ViewGroup viewGroup = (ViewGroup) rootView;
        for(int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);
            T match = findViewByClassReference(child, clazz);
            if(match != null) {
                return match;
            }
        }
    }
    return null;
}

Solution 2

With the Material Components Library (1.1.0 , 1.2.0-beta01, 1.3.0-alpha01) to start with a visible password just use:

<com.google.android.material.textfield.TextInputLayout
    app:endIconMode="password_toggle"
/>

and in your code:

textInputLayout.getEditText().setTransformationMethod(null);

If you want to return to the default behavior:

textInputLayout.getEditText()
    .setTransformationMethod(PasswordTransformationMethod.getInstance());
Share:
14,492

Related videos on Youtube

Gober
Author by

Gober

Mobile developer/consultant

Updated on September 15, 2022

Comments

  • Gober
    Gober almost 2 years

    I am using a TextInputLayout with the new function from the Support Library: passwordToggleEnabled. This gives a nice "eye"-icon that lets the user toggle password visibility on and off.

    My question is if there is a way to use this functionality but start with password visible?

    My xml:

    <android.support.design.widget.TextInputLayout
                        android:id="@+id/password"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:passwordToggleEnabled="true">
    
                        <EditText
                            android:id="@+id/password_edit"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:hint="@string/prompt_password"
                            android:inputType="textPassword" />
    </android.support.design.widget.TextInputLayout>
    

    The toggle looks similar to this: enter image description here

    I have not found a way to do this in xml, and not a way to manually toggle the visibility after the view is rendered. If I set the input type of the EditText to textVisiblePassword, the toggle is not shown. If I do it in code using for instance mPasswordEditText.setTransformationMethod(null); the password is shown but the toggle is gone and the user can't hide the password again. I know I can do it all manually but just wondering if I can make it work with the new magic toggle

    • JoshuaTree
      JoshuaTree over 7 years
      I'm looking for a way to achieve this too, without trying to extend the class directly from the AOSP
    • Sejal Baraiya
      Sejal Baraiya
      You can check this answer stackoverflow.com/a/27050480/7329597 Hope it helps you :)
  • Gober
    Gober over 7 years
    Thanks for the answer, but this also makes the toggle button disappear. I have expanded my question to make it clear what is not working.
  • Lumii
    Lumii almost 6 years
    Some comment on your first solution - R.id.text_input_password_toggle is not a public id.
  • Tyler V
    Tyler V almost 6 years
    @CheokYanCheng Solution I posted a few days ago finds the view without using the id, using the content description instead
  • Pankaj Kumar
    Pankaj Kumar almost 6 years
    @CheokYanCheng I did not get public-id concept. And if you are talking about the id which is declared in the layout created by Android itself, then I would say that is fine to use that id if you know and your solution will work until they do not change the id. This is similar to the old-styled listview example where we were giving id of listview what was declared by android. And there are many examples where we use such ids. But can you please explain public-id if I did not get it?
  • kos
    kos about 5 years
    In 2019, there's a public method called passwordVisibilityToggleRequested() on TextInputLayout that does this for you.
  • kos
    kos about 5 years
    In 2019, there's a public method called passwordVisibilityToggleRequested() on TextInputLayout that does this for you.
  • Nikos Hidalgo
    Nikos Hidalgo about 4 years
    I didn't downvote you, I just edited the code tags in your post
  • oriohac
    oriohac about 4 years
    Alright, but have you checked and seen if it works?
  • Nikos Hidalgo
    Nikos Hidalgo about 4 years
    I haven't; I'm not faced with this issue, so I can't check the validity of the answers here. Maybe ask the OP and see if what you suggested works in their case and if they benefit from your answer more than they do from the accepted one.
  • Adham Gamal
    Adham Gamal about 4 years
    nice answer pro
  • Rafael Baptista
    Rafael Baptista almost 4 years
    passwordVisibilityToggleRequested is deprecated