java - 如何在 TextView 的扩展类中正确绘制文本?

标签 java android textview extend outline

我目前正在扩展 TextView,在文本周围添加轮廓。到目前为止,我一直遇到的唯一问题是我无法将“大纲”正确定位在文本后面。如果我像下面描述的那样对扩展类进行编码,我会得到一个如下所示的标签:

注意:在上面的截图中,我将填充颜色设置为白色,描边颜色设置为黑色。

我做错了什么?

public class OutlinedTextView extends TextView {
    /* ===========================================================
     * Constants
     * =========================================================== */
    private static final float OUTLINE_PROPORTION = 0.1f;

    /* ===========================================================
     * Members
     * =========================================================== */
    private final Paint mStrokePaint = new Paint();
    private int mOutlineColor = Color.TRANSPARENT;

    /* ===========================================================
     * Constructors
     * =========================================================== */
    public OutlinedTextView(Context context) {
        super(context);
        this.setupPaint();
    }
    public OutlinedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setupPaint();
        this.setupAttributes(context, attrs);
    }
    public OutlinedTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setupPaint();
        this.setupAttributes(context, attrs);
    }

    /* ===========================================================
     * Overrides
     * =========================================================== */
    @Override
    protected void onDraw(Canvas canvas) {
        // Get the text to print
        final float textSize = super.getTextSize();
        final String text = super.getText().toString();

        // setup stroke
        mStrokePaint.setColor(mOutlineColor);
        mStrokePaint.setStrokeWidth(textSize * OUTLINE_PROPORTION);
        mStrokePaint.setTextSize(textSize);
        mStrokePaint.setFlags(super.getPaintFlags());
        mStrokePaint.setTypeface(super.getTypeface());

        // Figure out the drawing coordinates
        //mStrokePaint.getTextBounds(text, 0, text.length(), mTextBounds);

        // draw everything
        canvas.drawText(text,
                super.getWidth() * 0.5f, super.getBottom() * 0.5f,
                mStrokePaint);
        super.onDraw(canvas);
    }

    /* ===========================================================
     * Private/Protected Methods
     * =========================================================== */
    private final void setupPaint() {
        mStrokePaint.setAntiAlias(true);
        mStrokePaint.setStyle(Paint.Style.STROKE);
        mStrokePaint.setTextAlign(Paint.Align.CENTER);
    }
    private final void setupAttributes(Context context, AttributeSet attrs) {
        final TypedArray array = context.obtainStyledAttributes(attrs,
                R.styleable.OutlinedTextView);
        mOutlineColor = array.getColor(
                R.styleable.OutlinedTextView_outlineColor, 0x00000000);
        array.recycle(); 

        // Force this text label to be centered
        super.setGravity(Gravity.CENTER_HORIZONTAL);
    }
}

最佳答案

呸,我真是太蠢了。我只需要更改注释掉的行:

super.getPaint().getTextBounds(text, 0, text.length(), mTextBounds);

此外,为了实际渲染文本,我需要平均这个 View 的高度和文本的高度:

// draw everything
canvas.drawText(text,
    super.getWidth() * 0.5f, (super.getHeight() + mTextBounds.height()) * 0.5f,
    mStrokePaint);

现在整个代码如下:

public class OutlinedTextView extends TextView {
    /* ===========================================================
     * Constants
     * =========================================================== */
    private static final float OUTLINE_PROPORTION = 0.1f;

    /* ===========================================================
     * Members
     * =========================================================== */
    private final Paint mStrokePaint = new Paint();
    private final Rect mTextBounds = new Rect();
    private int mOutlineColor = Color.TRANSPARENT;

    /* ===========================================================
     * Constructors
     * =========================================================== */
    public OutlinedTextView(Context context) {
        super(context);
        this.setupPaint();
    }
    public OutlinedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setupPaint();
        this.setupAttributes(context, attrs);
    }
    public OutlinedTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setupPaint();
        this.setupAttributes(context, attrs);
    }

    /* ===========================================================
     * Overrides
     * =========================================================== */
    @Override
    protected void onDraw(Canvas canvas) {
        // Get the text to print
        final float textSize = super.getTextSize();
        final String text = super.getText().toString();

        // setup stroke
        mStrokePaint.setColor(mOutlineColor);
        mStrokePaint.setStrokeWidth(textSize * OUTLINE_PROPORTION);
        mStrokePaint.setTextSize(textSize);
        mStrokePaint.setFlags(super.getPaintFlags());
        mStrokePaint.setTypeface(super.getTypeface());

        // Figure out the drawing coordinates
        super.getPaint().getTextBounds(text, 0, text.length(), mTextBounds);

        // draw everything
        canvas.drawText(text,
                super.getWidth() * 0.5f, (super.getHeight() + mTextBounds.height()) * 0.5f,
                mStrokePaint);
        super.onDraw(canvas);
    }

    /* ===========================================================
     * Private/Protected Methods
     * =========================================================== */
    private final void setupPaint() {
        mStrokePaint.setAntiAlias(true);
        mStrokePaint.setStyle(Paint.Style.STROKE);
        mStrokePaint.setTextAlign(Paint.Align.CENTER);
    }
    private final void setupAttributes(Context context, AttributeSet attrs) {
        final TypedArray array = context.obtainStyledAttributes(attrs,
                R.styleable.OutlinedTextView);
        mOutlineColor = array.getColor(
                R.styleable.OutlinedTextView_outlineColor, 0x00000000);
        array.recycle(); 

        // Force this text label to be centered
        super.setGravity(Gravity.CENTER_HORIZONTAL);
    }
}

关于java - 如何在 TextView 的扩展类中正确绘制文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4342927/

相关文章:

java - Eclipse (Java) 中未找到源错误

Java,将值传递给实现 Callable 的类的构造函数

java - 从URL下载xml文件进行解析

android - Exoplayer播放m3u8文件Android

android - TextView.setText() 位置困惑 : onCreate() vs userMethod()

java - @ManyToOne 未填写父 ID 字段

java - 如何在共享首选项中保存按钮状态?

java - 如何从 ImageView 获取背景颜色

android - 如何获取对 WebView 系统 bundle 字体的字体引用? (格鲁吉亚,Times New Roman..)

java - 渲染前如何获取textview的行数?