Android RTL支持自定义EditText,用于可绘制左视图

Android RTL支持自定义EditText,用于可绘制左视图,android,android-edittext,android-canvas,android-custom-view,right-to-left,Android,Android Edittext,Android Canvas,Android Custom View,Right To Left,我有一个edittext,它的左边有一个可绘制的图像,带有一个不可编辑的前缀edittext,但现在我想让它支持rtl。尽管我付出了努力,但我无法支持rtl 我的自定义类如下所示 public class PrefixedEditText extends TextInputEditText { private String mPrefix = "+"; // can be hardcoded for demo purposes private Rect mPrefixRect = new Re

我有一个edittext,它的左边有一个可绘制的图像,带有一个不可编辑的前缀edittext,但现在我想让它支持rtl。尽管我付出了努力,但我无法支持rtl

我的自定义类如下所示

public class PrefixedEditText extends TextInputEditText {

private String mPrefix = "+"; // can be hardcoded for demo purposes
private Rect mPrefixRect = new Rect(); // actual prefix size

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

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect);
    mPrefixRect.right += getPaint().measureText(" "); // add some offset

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint());
}

@Override
public int getCompoundPaddingLeft() {
    return super.getCompoundPaddingLeft() + mPrefixRect.width();
}

}
<cl.dd.ui.PrefixedEditText
                    style="@style/edittext"
                    android:id="@+id/etCode"
                    android:maxLength="3"
                    android:drawableLeft="@drawable/icon_phone_number"
                    android:drawableStart="@drawable/icon_phone_number"
                    android:minWidth="@dimen/dim_img_width"
                    android:hint="@string/s_login_code"
                    android:tag="@string/s_login_country_code"
                    android:inputType="number"/>
我对这个类的xml调用如下:

public class PrefixedEditText extends TextInputEditText {

private String mPrefix = "+"; // can be hardcoded for demo purposes
private Rect mPrefixRect = new Rect(); // actual prefix size

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

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect);
    mPrefixRect.right += getPaint().measureText(" "); // add some offset

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint());
}

@Override
public int getCompoundPaddingLeft() {
    return super.getCompoundPaddingLeft() + mPrefixRect.width();
}

}
<cl.dd.ui.PrefixedEditText
                    style="@style/edittext"
                    android:id="@+id/etCode"
                    android:maxLength="3"
                    android:drawableLeft="@drawable/icon_phone_number"
                    android:drawableStart="@drawable/icon_phone_number"
                    android:minWidth="@dimen/dim_img_width"
                    android:hint="@string/s_login_code"
                    android:tag="@string/s_login_country_code"
                    android:inputType="number"/>

以下是我的建议

不要扩展
textinputtext
,而是基于布局创建自定义视图

布局可以如下所示:

<RelativeLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">

     <TextView
         android:id="@+id/prefixTextView"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentStart="true />

     <EditText
         android:id="@+id/editText"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"     
         android:layout_toEndOf="@id/prefixTextView" />

</RelativeLayout>


您需要确保在
AndroidManifest.xml

<application
    ...
    android:supportsRtl="true">

如果目标SDK低于17,则必须创建另一个res目录,如
layout ldrtl
values ldrtl
,并可能向自定义视图发送rtl标志。

要实现带区域设置支持的前缀编辑文本,只需创建自定义编辑文本并将前缀绘制为可绘制文本

请参阅下面的代码段:

    /**
     * Custom EditText that displays a fixed prefix in line with the text.
     * The trick here is to draw the prefix as a drawable and attach it via
     * setCompoundDrawables().
     */

    public class PrefixEditText extends AppCompatEditText {

        private ColorStateList mPrefixTextColor;

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

        public PrefixEditText(Context context, AttributeSet attrs) {
            this(context, attrs, android.R.attr.editTextStyle);
        }

        public PrefixEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            mPrefixTextColor = getTextColors();
        }

        public void setPrefix(String prefix) {
            if (Locale.getDefault().getLanguage().equalsIgnoreCase("en"))
                setCompoundDrawables(new TextDrawable(prefix + " "), null, null, null);
            else if (Locale.getDefault().getLanguage().equalsIgnoreCase("ar"))
                setCompoundDrawables(null, null, new TextDrawable(" " + prefix), null);
        }

        public void setPrefixTextColor(int color) {
            mPrefixTextColor = ColorStateList.valueOf(color);
        }

        private class TextDrawable extends Drawable {
            private String mText = "";

            TextDrawable(String text) {
                mText = text;
                setBounds(0, 0, (int) getPaint().measureText(mText) + 3, (int) getTextSize());
            }

            @Override
            public void draw(Canvas canvas) {
                Paint paint = getPaint();
                paint.setColor(mPrefixTextColor.getColorForState(getDrawableState(), 0));
                int lineBaseline = getLineBounds(0, null);
                canvas.drawText(mText, 0, canvas.getClipBounds().top + lineBaseline, paint);
            }

            @Override
            public void setAlpha(int alpha) {/* Not supported */}

            @Override
            public void setColorFilter(ColorFilter colorFilter) {/* Not supported */}

            @Override
            public int getOpacity() {
                return 1;
}
}
}

要实现RTL,只需将drawableStart而不是drawableLeft。 像这样:

<cl.dd.ui.PrefixedEditText
                    style="@style/edittext"
                    android:id="@+id/etCode"
                    android:maxLength="3"
                    android:drawableStart="@drawable/icon_phone_number"
                    android:drawableStart="@drawable/icon_phone_number"
                    android:minWidth="@dimen/dim_img_width"
                    android:hint="@string/s_login_code"
                    android:tag="@string/s_login_country_code"
                    android:inputType="number"/>


这就可以了。

您是否在API 17+或更低版本上尝试过此功能?是,但不起作用。目前正在marshmellow上试用。英语不错,但当应用程序以阿拉伯语模式打开时,前缀没有出现。请尝试
drawableEnd
drawableRight
并查看它是否会自动更改您没有收到请求,它有一个可绘制的左或开始,但我添加了一个不可编辑的前缀,这个前缀不会随rtlI而改变。我最后一次问这个问题,你试过我上面说的吗?通常它会选择它的布局并进行切换。无论如何,谢谢,我知道如何使用xml实现这一点,但我想使用canvas实现。您如何更改设备区域设置,您的测试设置是什么?我用阿拉伯语在Android 5 emulator和Android N Nexus 6P上试过,效果很好。为了调试目的,试着强制你将Android:layoutDirection设置为rtl,通过查看设置、langauge&Input查看它是否工作。你确定你的设备的语言环境已经改变了吗,你能检查一下收件箱或Gmail之类的应用程序,看看语言和布局是否已经更新了。您也可以尝试将布局方向强制为rtl,并让我知道它是否有效吗