使用 FrameLayout 时,TextInputLayout 文本 header 消失了

TextInputLayout text header gone when using FrameLayout

这是我当前的 xml 布局:

<android.support.design.widget.TextInputLayout
                    android:id="@+id/emailAddressLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp"
                    android:focusable="true"
                    android:clickable="true">

                    <FrameLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="9dp"
                        android:padding="5dp"
                        android:focusable="false"
                        android:clickable="false">

                        <AutoCompleteTextView
                            android:id="@+id/emailAddress"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:focusableInTouchMode="true"
                            android:hint="email address"
                            android:inputType="textEmailAddress"
                            android:imeOptions="actionNext"
                            android:maxLines="1" />

                    <Button
                        android:id="@+id/emailTextClearButton"
                        android:layout_width="20dp"
                        android:layout_height="20dp"
                        android:layout_marginRight="5dp"
                        android:layout_marginEnd="5dp"
                        android:layout_gravity="end|center_vertical"
                        android:background="@drawable/ic_clear_black_svg" />

                    </FrameLayout>

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

我需要 FrameLayout 才能在我的 AutoCompleteTextView 中完成 (x) 清除按钮。

问题是 FrameLayout 否定了 TextInputLayout 的效果,因此当用户输入文本或单击 AutoCompleteTextView 时,文本不会被推上去。

当前结果:(缺少电子邮件地址 header 文本)

想要的结果:(我添加了一个 x 清除按钮来显示不使用 FrameLayout 时缺少的内容)

TextInputLayout 有一些内部行为并不完全符合您对 "normal" ViewGroup 的期望。其中大部分没有记录,但 the Javadoc for the class itself 确实告诉了你一点:

Note: The actual view hierarchy present under TextInputLayout is NOT guaranteed to match the view hierarchy as written in XML. As a result, calls to getParent() on children of the TextInputLayout -- such as an TextInputEditText -- may not return the TextInputLayout itself, but rather an intermediate View. If you need to access a View directly, set an android:id and use View#findViewById(int).

你应该从中得到的是 TextInputLayout 可能会 "re-write" 你声明的 XML 布局和你应该 尽力确保您的 XML 布局按照 TextInputLayout "expects".

的方式设置

我认为您的具体问题源于这样一个事实,即您的 XML 布局没有指定 EditText,它是 TextInputLayout 的直接子项。如果你查看 the source for TextInputLayout#addView(),你会看到:

@Override
public void addView(View child, int index, final ViewGroup.LayoutParams params) {
    if (child instanceof EditText) {
        ...
        setEditText((EditText) child);
    } else {
        ...
    }
}

因为您有一个 FrameLayout 包装 EditText,所以永远不会调用 setEditText()。因此,TextInputLayout 的特殊功能的 none 将起作用。

如何解决这个问题比较难。我将从更改您的布局开始,改为使用此结构:

<FrameLayout>
    <TextInputLayout>
        <EditText/>
    </TextInputLayout>
    <Button/>
</FrameLayout>

这样你就可以有一个 "normal" TextInputLayout 层次结构 一个按钮来清除文本。您需要做更多的工作来定位按钮,使一切看起来自然,但这应该是一个可行的起点。

我最终在 XML 中使用以下内容解决了我的问题:

<android.support.design.widget.TextInputLayout
                    android:id="@+id/emailAddressTextInput"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp">

                        <AutoCompleteTextView
                            android:id="@+id/emailAddress"
                            style="@style/body_text_style"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:clickable="true"
                            android:focusable="true"
                            android:focusableInTouchMode="true"
                            android:hint="@string/prompt_email_address"
                            android:imeOptions="actionNext"
                            android:inputType="textEmailAddress"
                            android:maxLines="1"/>

                        <!--work around solution using negative marginTop-->
                        <Button
                            android:id="@+id/emailTextClearButton"
                            android:layout_width="20dp"
                            android:layout_height="20dp"
                            android:layout_gravity="end|center_vertical"
                            android:layout_alignParentRight="true"
                            android:layout_alignParentEnd="true"
                            android:layout_centerVertical="true"
                            android:layout_marginEnd="5dp"
                            android:layout_marginRight="5dp"
                            //work around solution
                            android:layout_marginTop="-32dp"
                            android:background="@drawable/ic_clear_black_svg"/>

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

WORKAROUND 是将我的 button 设置在我的 AutoCompleteTextView 下方,并使用 负 marginTop按钮,以便能够将其设置在需要设置的位置。

结果:

注意:我使用 RelativeLayout 作为 TextInputLayout

的父级