1

I am trying to use TextInputLayout in a preference screen so as have a nice neat password box that has a show password option. I know there are ways and means of doing it with checkboxes and scripting but I would really love to be to just use the TextInputLayout, maybe wrapped or in a custom widget. Gradle dependencies are correct as it works fine in other activity screens.

The following preferences.xml crashes with an "Error inflating class com.google.android.material.textfield.TextInputLayout"

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

<com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:passwordToggleEnabled="true">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

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

</androidx.preference.PreferenceScreen>
poby
  • 1,572
  • 15
  • 39

2 Answers2

3

Ok I worked out the answer (and learned a lot in the process). Took a lot of research and trial and error but I hope the following might prove helpful to someone similarly frustrated.

The custom preference layout:

password.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textLay"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="66dp"
    android:hint="@string/Set_Password"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:passwordToggleEnabled="true">

    <com.google.android.material.textfield.TextInputEditText
        android:id="@android:id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword" />

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

</androidx.constraintlayout.widget.ConstraintLayout>

The preference screen layout:

preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<com.toggen.myapplication.PasswordPreference
    android:key="pref_password"
    android:layout="@layout/password" />

</PreferenceScreen>

SettingsActivity.kt

package com.toggen.myapplication

import kotlinx.android.synthetic.main.password0.view.*
import androidx.appcompat.app.AppCompatActivity
import android.util.AttributeSet
import android.widget.EditText
import android.content.Context
import androidx.preference.*
import android.os.Bundle

class PasswordPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs){
    private var passW: EditText? = null

    override fun onBindViewHolder(holder: PreferenceViewHolder?) {
        super.onBindViewHolder(holder)
        passW = holder?.itemView?.textLay?.editText?.apply{ setText(getPersistedString("admin")) }
    }

    override fun onDetached() {
        super.onDetached()
        passW?.apply{ persistString("$text") }
    }
}

class SettingsActivity:  AppCompatActivity()  {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if(savedInstanceState == null) {
            supportActionBar?.title = "Settings"
            supportFragmentManager.beginTransaction()
                .replace(android.R.id.content, SettingsFragment()).commit()
        }
    }
    override fun onSupportNavigateUp() = onBackPressed().run { true }

    class SettingsFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) = setPreferencesFromResource(R.xml.preferences, rootKey)
    }
}
poby
  • 1,572
  • 15
  • 39
0

Finally the answer that I've been looking for!! THANK YOU!!

Only modification that I would make is to use:

android:dialogLayout="@layout/password"

instead of:

android:layout="@layout/password"
Dave Enstrom
  • 105
  • 7