【问题标题】:Adding a drawableLeft to an EditText shifts the hint towards right, if edittext is inside TextInputlayout如果 edittext 在 TextInputlayout 内,将 drawableLeft 添加到 EditText 会将提示向右移动
【发布时间】:2016-09-16 11:35:45
【问题描述】:

我在 TextInputLayout 中创建了一个 EditText。我在我的代码中在运行时将 drawableLeft 设置为 EditText,但是一旦我添加 drawableLeft,TextInputLayout 内的浮动提示就会向右移动,从而使空间等于可绘制宽度。但是我不想在提示中使用那个空格,所以请帮我解决这个问题!

【问题讨论】:

  • 请张贴您的 xml
  • 使用 setCompoundDrawablePadding

标签: android


【解决方案1】:

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>


注意事项:

  • 在迁移到 Material Components 库时,帮助类和边界的字段名称已删除 m 前缀符号。如 cmets 中所述,它们现在分别命名为 collapsingTextHelpercollapsedBounds

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

【讨论】:

  • 在支持库 28 中,他们更改了变量的名称,因此 getDeclaredField 反射不再起作用。他们改变了所有变量的大小写,所以你必须改变 mCollapsingTextHelper -> collapsingTextHelper
  • 将这些行添加到 proguard 规则中,这样它仍然可以在您的生产版本中工作:-keep class android.support.design.widget.TextInputLayout{ *; }-keep class android.support.design.widget.CollapsingTextHelper{ *; }
  • 对于 android X 包,字段名称发生变化。请改用 collapsingTextHelper 和 collapsedBounds。
  • 你能分享一下你的 TextLabel 风格吗?
  • @android_sh 我真的没有了。对不起。我当时只是拼凑一些东西,以模糊地匹配 OP 的形象。我记得这没什么特别的。可能只是parent="TextAppearance.AppCompat"android:textColor 是一些灰色阴影,并且尺寸比默认值小一些。
【解决方案2】:

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

【讨论】:

    【解决方案3】:
     editText.setCompoundDrawablePadding(your padding value);
    

    试试看,然后告诉我。它对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      • 2016-01-27
      • 2021-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多