TextInputLayout错误右对齐

时间:2017-03-03 10:01:00

标签: android layout textinputlayout

我在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"中应用的样式上尝试了正确的重力。即使这样也行不通。

我尝试通过在this link之后使用带有AlignmentSpan的SpannableStringBuilder以编程方式将Error转移到右侧。即使这对我也不起作用。

我不确定还有什么可以尝试的。请建议。

6 个答案:

答案 0 :(得分:12)

感谢Mike's answer我能够找到解决方案。

我创建了一个自定义类:

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。我希望我能为你的答案多点赞扬。

答案 1 :(得分:3)

我的自定义课程在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 = LinearLayout.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()
        }

    }
}

答案 2 :(得分:2)

这是Kotlin中的一种不依赖于视图层次结构的黑客:

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
        }
    }
}

答案 3 :(得分:1)

对于材料成分版本1.2.0-rc01,您可以创建一个CustomTextInputLayout,它继承自TextInputLayout,以将文本对齐方式更改为末尾(或您希望的位置),如下所示:

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...

答案 4 :(得分: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);

恭喜!您已完成所需的工作。

答案 5 :(得分: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
    }

}