Home » Android » android – TextInputLayout and AutoCompleteTextView

android – TextInputLayout and AutoCompleteTextView

Posted by: admin April 23, 2020 Leave a comment

Questions:

I’m using TextInputLayout in my Android app to achieve that neat floating label effect for my input fields. I know that I should be using the TextInputEditText as well to allow hints to be displayed when in landscape mode and the input are fills the entire screen.

However, in some of my input fields I have got autocompletion going on using AutoCompleteTextView (which IMO has a really inconsistent name to it – “TextView” instead of “EditText” – but that’s another story) and that obviously inherits directly from EditText. Thus it doesn’t have the same functionality as TextInputEditText brings.

So I’m wondering if there’s a way to achieve the same hint-in-landscape functionality (without making my own TextInputAutoCompleteTextView implementation, that is) and to also avoid the lint warnings that are produced. Am I missing something here? I suppose I get that they didn’t make custom versions of all direct and indirect subclasses of EditText for this specific thing, so am I expected to make my own?

How to&Answers:

A little late, but yes, you’ll have to roll your own implementation. The good news is that this is fairly straightforward. Here’s how TextInputEditText was implemented:

https://android.googlesource.com/platform/frameworks/support.git/+/master/design/src/android/support/design/widget/TextInputEditText.java

Accordingly, here’s what TextInputAutoCompleteTextView might look like.

public class TextInputAutoCompleteTextView extends AppCompatAutoCompleteTextView {

    public TextInputAutoCompleteTextView(Context context) {
        super(context);
    }

    public TextInputAutoCompleteTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TextInputAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        final InputConnection ic = super.onCreateInputConnection(outAttrs);
        if (ic != null && outAttrs.hintText == null) {
            // If we don't have a hint and our parent is a TextInputLayout, use it's hint for the
            // EditorInfo. This allows us to display a hint in 'extract mode'.
            final ViewParent parent = getParent();
            if (parent instanceof TextInputLayout) {
                outAttrs.hintText = ((TextInputLayout) parent).getHint();
            }
        }
        return ic;
    }
}

Answer:

Now, with AndroidX you don’t need customise something.
Need just add material component style (was added in 1.1.0-alpha06, see release notes).

<com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Example TextInputLayout">

    <androidx.appcompat.widget.AppCompatAutoCompleteTextView
    style="@style/Widget.MaterialComponents.AutoCompleteTextView.FilledBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

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

Answer:

Building off of chessdork’s answer, I thought I’d go more into detail on how you can incorporate an autofill with a hint into your project. Here are the exact steps I used to get it working:

1) Make sure you have implementation 'com.android.support:design:26.1.0' in your gradle dependencies. The exact package name be slightly different depending on your SDK version.

2) Copy the TextInputAutoCompleteTextView class from @chessdork’s answer and put it in a public class within your project.

3) Place where you want the autofill edittext to be in your XML layout. It should be structured like this:

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="16dp">
        <mycompany.views.TextInputAutoCompleteTextView
            android:id="@+id/myAutoFill"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/myHint"/>
        </android.support.design.widget.TextInputLayout>

Answer:

Both answers (@chessdork and @Shn_Android_Dev) help to achieve the correct behavior of an AutoCompleteTextView (ACTV) inside a TextInputLayout (TIL), however I found that there was no space between the start/end of the TIL and the ACTV inside of it as you can see in the following image:

Example of how there is no space between the ACTV and the TIL

What I did to solve the issue was to add a couple of padding values to the start and the end of the TextInputAutoCompleteTextView, the values that worked for me are 12dp at the beginning and 8dp at the end but of course you can play with that and get your desired effect. Taking @Shn_Android_Dev example, the TextInputAutoCompleteTextView would end up as:

<mycompany.views.TextInputAutoCompleteTextView
    android:id="@+id/myAutoFill"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingStart="12dp"
    android:paddingEnd="8dp"
    android:hint="@string/myHint"/>

And the view now looks like this:

Example with the correct spacing

Answer:

With the Material Components library just use a TextInputLayout with a Widget.MaterialComponents.TextInputLayout.*.ExposedDropdownMenu style.

Something like:

  <com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
     android:hint="Hint..."
     ...>

       <AutoCompleteTextView
           android:background="@null"
           .../>

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

enter image description here

Answer:

Maybe someone needs the code for Xamarin Android implementation.

Here

namespace YourNamespace
{
    public class TextInputAutoCompleteTextView : AppCompatAutoCompleteTextView
    {
        public TextInputAutoCompleteTextView(Context context) : base(context)
        {
        }

        public TextInputAutoCompleteTextView(Context context, IAttributeSet attrs) : base(context, attrs)
        {
        }

        public TextInputAutoCompleteTextView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context,
            attrs, defStyleAttr)
        {
        }

        public override IInputConnection OnCreateInputConnection(EditorInfo outAttrs)
        {
            IInputConnection ic = base.OnCreateInputConnection(outAttrs);
            if (ic != null && outAttrs.HintText == null)
            {
                IViewParent parent = Parent;
                if (parent is TextInputLayout layout)
                {
                    outAttrs.HintText = new Java.Lang.String(layout.Hint);
                }
            }

            return ic;
        }
    }
}

And in the Xml…

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <YourNamespace.TextInputAutoCompleteTextView
            android:id="@+id/edtDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Movements"
            android:inputType="textCapSentences" />

    </android.support.design.widget.TextInputLayout>

Answer:

The easy solution is to cast your EditText to AutoCompleteTextView

XML

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textInputLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"   
    <AutoCompleteTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>

Java

AutoCompleteTextView autoCompleteTextView;
TextInputLayout textInputLayout = findViewById(R.id.textInputLayout);
autoCompleteTextView = (AutoCompleteTextView) textInputLayout.getEditText();