TextInputLayout错误消息右对齐

16

我有一个包含在TextInputLayout中的EditText。我希望在EditText下方显示错误,但对齐到屏幕的右侧。

这是我目前拥有的:Text Input Layout

错误显示如下:Error right now

我想要它看起来像这样:What I want

我的XML是这个:

        <android.support.design.widget.TextInputLayout
            android:id="@+id/text_input_email"
            style="@style/forgot_pass_text_inputlayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/tv_enter_email_message"
            android:layout_marginTop="@dimen/email_padding_top"
            android:hintTextAppearance="@{forgotPasswordVM.hintTextAppearance}"
            android:theme="@style/forgot_pass_til_state"
            app:error="@{forgotPasswordVM.email.textInputError}">

            <EditText
                android:id="@+id/actv_email"
                style="@style/forgot_pass_edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/email_address"
                android:imeActionId="@+id/btn_submit"
                android:imeOptions="actionSend"
                android:inputType="textEmailAddress"
                android:maxLines="1"
                android:onEditorAction="@{forgotPasswordVM.onEditorAction}"
                android:singleLine="true"
                app:binding="@{forgotPasswordVM.email.text}" />
        </android.support.design.widget.TextInputLayout>

我正在使用数据绑定。

我尝试在EditText和TextInputLayout上设置android:gravity="right"android:layout_gravity="right",但都无法达到我想要的效果。

我尝试在主题和样式中设置右对齐,但都没有影响错误文本的位置。

我尝试在app:errorTextAppearance="@style/right_error"中应用的样式中设置右对齐,但仍然不起作用。

我还尝试通过使用AlignmentSpan的SpannableStringBuilder进行编程以将错误消息向右移动,具体可以参考这个链接。但是这对我也没有用。

我不知道还有什么其他尝试的方法,请提供建议。


2
你可以尝试使用我在这里的回答中提到的选项来获取TextView错误,并在其上调用setGravity(Gravity.RIGHT)。虽然我没有测试过,但如果我没记错的话,错误的TextView具有match_parent宽度,因此它应该按照你描述的对齐其文本。 - Mike M.
1
Mike M. 的建议不错,但我已经尝试了 RIGHT 和 END,都没有用。只能采用下面详细介绍的编程方法... - BonanzaDriver
https://dev59.com/K5Hea4cB1Zd3GeqPrJRY#65991884 - Erfan Eghterafi
6个回答

12
所以感谢迈克的回答,我能够找出解决方案。 我创建了一个自定义类:
public class CustomTextInputLayout extends TextInputLayout {

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

    @Override
    public void setErrorEnabled(boolean enabled) {
        super.setErrorEnabled(enabled);

        if (!enabled) {
            return;
        }

        try {
            Field errorViewField = TextInputLayout.class.getDeclaredField("mErrorView");
            errorViewField.setAccessible(true);
            TextView errorView = (TextView) errorViewField.get(this);
            if (errorView != null) {
                errorView.setGravity(Gravity.RIGHT);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                params.gravity = Gravity.END;
                errorView.setLayoutParams(params);
            }
        }
        catch (Exception e) {
            // At least log what went wrong
            e.printStackTrace();
        }
    }
}

现在我只是用 CustomTextInputLayout 替换了我的 TextInputLayout。效果很好。非常感谢 Mike。我希望我能更多地为这个答案贡献。


嗨,我正在尝试在EditText上显示错误消息并将其右对齐,你有什么想法吗? - usr30911
@ViVekH,您能否更详细地解释一下您想要什么? - Rachit
这似乎不再起作用了(或者,在3.3.2 / Android 9设置上肯定不起作用)。 - BonanzaDriver
这对我不起作用。 我已经在清单中禁用了supportsRtl。有没有什么方法可以做到这一点? - Javid Sattar

5

以下是一种不依赖于视图层次结构的 Kotlin hack:

class CustomTextInputLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextInputLayout(context, attrs, defStyleAttr) {

    override fun setError(errorText: CharSequence?) {
        super.setError(errorText)
        with(findViewById<TextView>(R.id.textinput_error)) {
            // this will work as long as errorView's layout width is
            // MATCH_PARENT -- it is, at least now in material:1.2.0-alpha06
            textAlignment = TextView.TEXT_ALIGNMENT_VIEW_END
        }
    }
}

谢谢,这对我帮助很大。如果有人想要在视图绑定中使用它,请按照以下步骤操作:with(binding.root.findViewById(R.id.textinput_error)) { textAlignment = TextView.TEXT_ALIGNMENT_CENTER } - manoellribeiro

4

我的自定义类是用Kotlin编写的

class CustomTextInputLayout(context: Context, attrs: AttributeSet) :
    TextInputLayout(context, attrs) {

    override fun setErrorEnabled(enabled: Boolean) {
        super.setErrorEnabled(enabled)

        if (!enabled) {
            return
        }

        try {
            val layout = this
            val errorView : TextView = ((this.getChildAt(1) as ViewGroup).getChildAt(0) as ViewGroup).getChildAt(0) as TextView

            (layout.getChildAt(1) as ViewGroup).layoutParams.width = LayoutParams.MATCH_PARENT
            (layout.getChildAt(1) as ViewGroup).getChildAt(0).layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT

            errorView.gravity = Gravity.END

        } catch (e: Exception) {
            e.printStackTrace()
        }

    }
}

目前(2019-02-18)这个方法是可行的,但当视图层次结构再次发生变化时,它将不再有效。 - Aidan Host

3

使用 material-components 版本 1.2.0-rc01,您可以创建一个从 TextInputLayout 继承的 CustomTextInputLayout,将文本对齐更改为末尾(或您想要的任何位置),如下所示:

class CustomTextInputLayout : TextInputLayout {

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttrs: Int
    ) : super(context, attrs, defStyleAttrs)

    override fun setErrorEnabled(enabled: Boolean) {
        super.setErrorEnabled(enabled)
        if (!enabled) {
            return
        }
        try {
            changeTextAlignment(
                com.google.android.material.R.id.textinput_error,
                View.TEXT_ALIGNMENT_VIEW_END
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

   
    private fun changeTextAlignment(textViewId: Int, alignment: Int) {
        val textView = findViewById<TextView>(textViewId)
        textView.textAlignment = alignment
    }
}

对齐方式在IndicatorViewController类中被指定为始终为View.TEXT_ALIGNMENT_VIEW_START。该类被TextInputLayout使用。

IndicatorViewController类中

  void setErrorEnabled(boolean enabled) {
    if (errorEnabled == enabled) {
      return;
    }

    cancelCaptionAnimator();

    if (enabled) {
      errorView = new AppCompatTextView(context);
      errorView.setId(R.id.textinput_error);
      if (VERSION.SDK_INT >= 17) {
        errorView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
      }
//More code...

0

基于@Emmanuel Guerra的回答,我也将其应用于helperText:

class CustomTextInputLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = com.google.android.material.R.attr.textInputStyle
) : TextInputLayout(context, attrs, defStyleAttr) {

    override fun setErrorEnabled(enabled: Boolean) {
        super.setErrorEnabled(enabled)
        if (!enabled) return
        centerMiniText(com.google.android.material.R.id.textinput_error)
    }

    override fun setHelperTextEnabled(enabled: Boolean) {
        super.setHelperTextEnabled(enabled)
        if (!enabled) return
        centerMiniText(com.google.android.material.R.id.textinput_helper_text)
    }

    private fun centerMiniText(textViewId: Int) {
        try {
            changeTextAlignment(textViewId, View.TEXT_ALIGNMENT_CENTER)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    @Suppress("SameParameterValue")
    private fun changeTextAlignment(textViewId: Int, alignment: Int) {
        findViewById<TextView>(textViewId)?.textAlignment = alignment
    }

}


0
如果选择的答案不起作用,下面是另一个解决方案:
创建以下自定义类:
public class CustomTextInputLayout extends TextInputLayout
{

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

@Override
public void setErrorEnabled(boolean enabled)
{
    super.setErrorEnabled(enabled);

    if (!enabled)
    {
        return;
    }

    try
    {
        TextView errorView = this.findViewById(R.id.textinput_error);
        FrameLayout errorViewParent = (FrameLayout) errorView.getParent();
        errorViewParent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
        errorView.setGravity(Gravity.CENTER); // replace CENTER  with END or RIGHT
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}
}

然后按照以下方式创建您的自定义TextInputLayout:

 <CustomTextInputLayout
    android:id="@+id/til_first_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/activity_horizontal_margin"
    app:layout_constraintBottom_toTopOf="@+id/til_last_name">

    <EditText
        android:id="@+id/et_first_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/first_name"
        android:gravity="right"
        />

</CustomTextInputLayout>

然后在您的代码中进行初始化:

private CustomTextInputLayout tilFirstName;
tilFirstName = view.findViewById(R.id.til_first_name);

恭喜!你已经完成了你所需要的。


这基本上是一个TextView,用于显示TextInputLayout中的错误。 - Muhammad Saad Rafique
我认为id应该是com.google.android.material.R.id.textinput_error,否则它会抱怨找不到R。 - katie
兄弟,我有上面的工作代码。它运行良好。 - Muhammad Saad Rafique
Android Studio在我的端上对你的代码进行了投诉。除非你导入com.google.android.material.R,否则你应该在答案中提到它。 - katie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接