TextInputLayout Ошибка выравнивания вправо

У меня есть EditText, заключенный в TextInputLayout. Я хочу отображать ошибки в EditText, но выравнивается в правый конец экрана.

Это то, что я сейчас имею: Текстовый входной макет

Ошибка отображается следующим образом: Ошибка прямо сейчас

Что я хочу, чтобы он выглядел так: Что я хочу

Мой 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>

Я использую привязку данных.

Я попытался установить android:gravity="right" и android:layout_gravity="right" как в EditText, так и в TextInputLayout. Не работает так, как я хочу.

Я попытался установить правильную гравитацию в теме, а также в стиле. Не влияет на ошибку.

Я пробовал правильную гравитацию в стиле, который применяется в app:errorTextAppearance="@style/right_error". Даже это не работает.

Я попытался программно перевести ошибку вправо, используя SpannableStringBuilder с выравниванием по следующей ссылке эту ссылку. Даже это не работает для меня.

Я не уверен, что еще попробовать. Пожалуйста, предложите.

Ответ 1

Итак, спасибо Майк ответ Я смог найти решение.

Я создал собственный класс:

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();
        }
    }
}

Теперь я просто заменил TextInputLayout на CustomTextInputLayout. Работает как шарм. Большое спасибо Mike. Мне жаль, что я не мог бы отблагодарить вас за этот ответ.

Ответ 2

Мой пользовательский класс в Котлине

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

    }
}

Ответ 3

Если выбранный ответ не работает. Другое решение ниже:

Создайте пользовательский класс, как показано ниже:

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);

Поздравляем! Вы сделали то, что вам нужно.