Android扩展EditText在画布上绘制超出边界

3
我正在尝试通过扩展EditText并重写onDraw函数在下面绘制文本:

enter image description here

正如您所看到的,这个单词被切断了,从我在网上看到的来看,他们除了在画布上绘制外没有对画布做任何事情。从我观察到的情况来看,我认为是因为EditText的画布受限,所以才会被切断。我知道有一个更好的解决方案,而不是覆盖onDraw,但我想知道为什么会发生这种情况。有人可以解释或给个提示吗?非常感谢。

CustomEditText.java:

public class CustomEditText extends AppCompatEditText {

private Rect mTitleRect;
private Rect mErrorTextRect;

private Paint mTitlePaint;
private Paint mErrorTextPaint;

private String mTitle = "";
private String mErrorText = "";

private int mEditTextHeight;

public CustomEditText(Context context) {
    super(context);
}

public CustomEditText(Context context, AttributeSet attrs) {
    super(context, attrs, R.attr.customEditTextStyle);
    init();
    init(context, attrs);
}

public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
    init(context, attrs);
}

private void init() {
    mTitleRect = new Rect();
    mErrorTextRect = new Rect();

    mTitlePaint = new Paint();
    mErrorTextPaint = new Paint();

    mTitlePaint.setColor(Color.BLACK);
    mTitlePaint.setTextSize(getResources().getDimension(R.dimen.text_small));

    mErrorTextPaint.setColor(Color.parseColor("#FF4336"));
    mErrorTextPaint.setTextSize(getResources().getDimension(R.dimen.text_small));
}

private void init(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText);

    try {
        mTitle = a.getString(R.styleable.CustomEditText_headerTitle);
        mErrorText = a.getString(R.styleable.CustomEditText_errorText);
    } finally {
        a.recycle();
    }
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    mEditTextHeight = h;

    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (mTitle != null && !mTitle.isEmpty()) {
        mTitlePaint.getTextBounds(mTitle, 0, mTitle.length(), mTitleRect);
        canvas.drawText(mTitle, getPaddingLeft(), getPaddingTop() - mTitleRect.height(), mTitlePaint);
    }

    if (mErrorText != null && !mErrorText.isEmpty()) {
        mErrorTextPaint.getTextBounds(mErrorText, 0, mErrorText.length(), mErrorTextRect);
        canvas.drawText(mErrorText, getPaddingLeft(), mEditTextHeight + mErrorTextRect.height() / 2, mErrorTextPaint);
    }
}
}

attrs.xml

<declare-styleable name="CustomEditText">
    <attr name="errorText" format="string|reference" />
    <attr name="headerTitle" format="string|reference" />
</declare-styleable>

XML:
<com.mypackage.CustomEditText
                android:id="@+id/et_username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Username"
                app:errorText="errorrrr"
                app:headerTitle="testing title" />

尝试将 android:clipChildren="false" 和 android:clipToPadding="false" 添加到此 EditText 及其所有父布局中。 - user10053723
请编辑问题并在XML中添加'R.styleable.CustomEditText'。 - Sukhbir
更新了 :) 我会尝试使用这个剪辑,谢谢 - Tenten Ponce
嗨@Subzero,谢谢,现在它正在显示:)但是似乎它并不像我预期的那样工作,它没有被包裹在EditText中,因此它不被视为视图,而是只是超出范围,下面的视图(密码)也没有调整。它只是重叠:/ - Tenten Ponce
顺便说一下,标题(在顶部)也被截断了 :( 顺便更新了图片 - Tenten Ponce
理论:我认为解决这个问题的方法是在另一个带有文本空间的画布上重新绘制整个画布,而不是在包含整个编辑文本的现有画布上进行绘制。你不能移动它,因为它代表当前的画布,你需要将它放在另一个画布中作为整体移动。 - Tenten Ponce
2个回答

1
我认为您误解了Android画布坐标。画布的原点坐标(0, 0)位于左上角,x坐标向右增加,y坐标向下增加。 您需要传递要绘制文本的左上角坐标。

https://developer.android.com/reference/android/graphics/Canvas#drawText(java.lang.String,%20float,%20float,%20android.graphics.Paint)

我不明白你想在哪里绘制文本,因此假设你想在视图的左上角绘制,必须这样调用绘制文本。
canvas.drawText(mTitle, getPaddingLeft(), getPaddingTop(), mTitlePaint);


非常感谢你的建议,一旦我再次遇到此问题,我会尝试这个方法。目前,我已经创建了一个包含TextView和EditText的自定义视图,并创建了一个方法来返回EditText,以便在需要修改EditText本身时使用。 - Tenten Ponce
1
不用谢,我认为这比重写EditText的onDraw方法更好。 - jfawkes

0
public class CustomEditText extends AppCompatEditText {

private Rect mTitleRect;
private Rect mErrorTextRect;

private Paint mTitlePaint;
private Paint mErrorTextPaint;

private String mTitle = "";
private String mErrorText = "";

private int mEditTextHeight;

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

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

public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
    init(attrs);
}

private void init() {
    mTitleRect = new Rect();
    mErrorTextRect = new Rect();

    mTitlePaint = new Paint();
    mErrorTextPaint = new Paint();

    mTitlePaint.setColor(Color.BLACK);
    mTitlePaint.setTextSize(getResources().getDimension(R.dimen.text_small));

    mErrorTextPaint.setColor(Color.parseColor("#FF4336"));
    mErrorTextPaint.setTextSize(getResources().getDimension(R.dimen.text_small));
}

private void init(AttributeSet attrs) {
    TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomEditText);

    try {
        mTitle = a.getString(R.styleable.CustomEditText_headerTitle);
        mErrorText = a.getString(R.styleable.CustomEditText_errorText);
    } finally {
        a.recycle();
    }
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    mEditTextHeight = h;

    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    setPadding(0, 0, 0, (int) getResources().getDimension(R.dimen.text_small));

    if (mTitle != null && !mTitle.isEmpty()) {
        mTitlePaint.getTextBounds(mTitle, 0, mTitle.length(), mTitleRect);
        canvas.drawText(mTitle, getPaddingLeft(), getPaddingTop() - mTitleRect.height(), mTitlePaint);
    }

    if (mErrorText != null && !mErrorText.isEmpty()) {
        mErrorTextPaint.getTextBounds(mErrorText, 0, mErrorText.length(), mErrorTextRect);
        canvas.drawText(mErrorText, getPaddingLeft(), getHeight(), mErrorTextPaint);
    }
}

我已经尝试过以编程方式添加填充,但它只是推动了提示 :( - Tenten Ponce
最后一行 canvas.drawText(mErrorText, getPaddingLeft(), getHeight(), mErrorTextPaint); - UgAr0FF
这是我尝试的第一件事,它显示在下面,但上面也是一个问题。这只是一个补丁,不是我正在寻找的正确解决方案。顺便说一句,谢谢您的建议 :) - Tenten Ponce
最好在视图内部绘制,为此请使用填充。如果您想在视图外部绘制,则需要在根布局中设置android:clipChildren="false"和android:clipToPadding="false"。但要注意其他视图不要覆盖您的图片。 - UgAr0FF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接