RTL 支持可绘制左侧的自定义编辑文本
RTL support to custom editext for drawable left
我有一个 edittext,它有一个可绘制的图像,左边有一个不可编辑的前缀 editext,但现在我想让它支持 rtl。尽管我很努力,但我还是无法支持 rtl。
我的自定义class如下,
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();
}
}
我的xml这个class的调用如下,
<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"/>
这是我的建议。
不是扩展 TextInputEditText
,而是基于布局创建自定义视图。
布局可以是这样的:
<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>
然后,您可以创建自定义视图,使用此布局扩展 RelativeLayout
。它会适应语言方向的变化。
有一些缺点 - 生成的视图不会在 EditText
class 层次结构中,并且在很多地方使用它最终会伤害 UI性能,因为它引入了嵌套布局,但至少 RTL 部分是可以的。
您需要确保 supportsRtl
在您的 AndroidManifest.xml
中设置为 true
<application
...
android:supportsRtl="true">
并在您的布局中将 layoutDirection
设置为 locale
、inherit
或 rtl
xml 如果您的目标是 SDK 17+
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layoutDirection="locale">
如果您的目标 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"/>
这样就可以了。
我有一个 edittext,它有一个可绘制的图像,左边有一个不可编辑的前缀 editext,但现在我想让它支持 rtl。尽管我很努力,但我还是无法支持 rtl。
我的自定义class如下,
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();
}
}
我的xml这个class的调用如下,
<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"/>
这是我的建议。
不是扩展 TextInputEditText
,而是基于布局创建自定义视图。
布局可以是这样的:
<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>
然后,您可以创建自定义视图,使用此布局扩展 RelativeLayout
。它会适应语言方向的变化。
有一些缺点 - 生成的视图不会在 EditText
class 层次结构中,并且在很多地方使用它最终会伤害 UI性能,因为它引入了嵌套布局,但至少 RTL 部分是可以的。
您需要确保 supportsRtl
在您的 AndroidManifest.xml
<application
...
android:supportsRtl="true">
并在您的布局中将 layoutDirection
设置为 locale
、inherit
或 rtl
xml 如果您的目标是 SDK 17+
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layoutDirection="locale">
如果您的目标 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"/>
这样就可以了。