如果edittext位于TextInputlayout内,则将drawableLeft添加到EditText会将提示向右移动

时间:2016-09-16 11:35:45

标签: android

this我在TextInputLayout中创建了一个EditText。我在运行时在我的代码中将drawableLeft设置为EditText,但是一旦我添加了drawableLeft,TextInputLayout中的浮动提示就会向右移动,使空间等于drawable宽度。但是我不希望这个空间有提示,所以请帮我解决这个问题!

3 个答案:

答案 0 :(得分:33)

TextInputLayout使用辅助类 - CollapsingTextHelper - 来操作其提示文本。此帮助程序的实例是私有的,并且没有公开与其布局关联的任何属性,因此我们需要使用一点反射来访问它。此外,每次TextInputLayout布局时都会设置并重新计算其属性,因此将TextInputLayout子类化,覆盖其onLayout()方法并在那里进行调整是有意义的。

import android.content.Context;
import android.graphics.Rect;
import android.support.design.widget.TextInputLayout;
import android.util.AttributeSet;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class CustomTextInputLayout extends TextInputLayout {
    private Object collapsingTextHelper;
    private Rect bounds;
    private Method recalculateMethod;

    public CustomTextInputLayout(Context context) {
        this(context, null);
    }

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

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

        init();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        adjustBounds();
    }

    private void init() {
        try {
            Field cthField = TextInputLayout.class.getDeclaredField("mCollapsingTextHelper");
            cthField.setAccessible(true);
            collapsingTextHelper = cthField.get(this);

            Field boundsField = collapsingTextHelper.getClass().getDeclaredField("mCollapsedBounds");
            boundsField.setAccessible(true);
            bounds = (Rect) boundsField.get(collapsingTextHelper);

            recalculateMethod = collapsingTextHelper.getClass().getDeclaredMethod("recalculate");
        }
        catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) {
            collapsingTextHelper = null;
            bounds = null;
            recalculateMethod = null;
            e.printStackTrace();
        }
    }

    private void adjustBounds() {
        if (collapsingTextHelper == null) {
            return;
        }

        try {
            bounds.left = getEditText().getLeft() + getEditText().getPaddingLeft();
            recalculateMethod.invoke(collapsingTextHelper);
        }
        catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
}

此自定义类是常规TextInputLayout的替代品,您可以使用相同的方式。例如:

<com.mycompany.myapp.CustomTextInputLayout
    android:id="@+id/text_input_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Model (Example i10, Swift, etc.)"
    app:hintTextAppearance="@style/TextLabel">

    <android.support.design.widget.TextInputEditText
        android:id="@+id/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableLeft="@drawable/bmw"
        android:text="M Series" />

</com.mycompany.myapp.CustomTextInputLayout>

screenshot

注意:

  • 在移动到Material Components库时,帮助程序类和边界的字段名称已删除m前缀表示法。如评论中所述,它们现在分别命名为collapsingTextHelpercollapsedBounds

  • 从API级别28(Pie)开始,有一些Restrictions on non-SDK interfaces(包括反射)可以访问SDK中通常无法访问的成员。但是,各种可用文档似乎表明不禁止对您自己的包中的组件进行反射。由于支持库不是平台SDK的一部分,并且在构建时合并到您的包中,因此该解决方案应该仍然有效。实际上,最近的测试没有发现问题,这仍然可以在可用的Pie仿真器上运行。

答案 1 :(得分:-1)

是的,这是我最近遇到的一个常见问题。我用简单的一行代码解决了这个问题: 使用drawbleleft在提示与drawble padding之间放置填充。 如果要在运行时添加drawble,只需在xml中添加drawblepadding,或者可以动态添加drawble padding。

答案 2 :(得分:-1)

 editText.setCompoundDrawablePadding(your padding value);

尝试一下,让我知道。它对我有用。