TextView.onDraw导致无限循环

时间:2010-07-08 19:55:55

标签: android

我想要一个TextView来调整字体大小,以便视图中的文本自动展开(或缩小)以填充视图的整个宽度。我想我可以通过创建一个自定义的TextView来覆盖onDraw(),如下所示:

public class MaximisedTextView extends TextView {
    // (calls to super constructors here...)

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

        TextPaint textPaint = this.getPaint();
        Rect bounds = new Rect();

        String text = (String)this.getText(); // current text in view
        float textSize = this.getTextSize();  // current font size
        int viewWidth = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
        textPaint.getTextBounds(text, 0, text.length(), bounds);
        int textWidth = bounds.width();

        // reset font size to make text fill full width of this view
        this.setTextSize(textSize * viewWidth/textWidth);
    }
}

然而,这会将应用程序发送到一个无限循环(文本大小每次都会增长并略微缩小!),所以我显然是错误的方式。对setTextSize()的调用是否会触发无效,以便无休止地再次调用onDraw?

有没有办法阻止递归调用(如果发生这种情况)?或者我应该以一种完全不同的方式来解决它?

2 个答案:

答案 0 :(得分:3)

  

对setTextSize()的调用是否触发   无效以便调用onDraw   又一次,无休止地?

是的,这可能就是hapening。如果您setTextSize take a look of the source code,您会看到它会调用此方法:

private void setRawTextSize(float size) {
    if (size != mTextPaint.getTextSize()) {
        mTextPaint.setTextSize(size);

        if (mLayout != null) {
            nullLayouts();
            requestLayout();
            invalidate(); // yeahh... invalidate XD
        }
    }
}

那么,如果您正在努力覆盖onDraw方法,为什么不直接使用drawText类的Canvas方法?

答案 1 :(得分:3)

那是幻想!奖励!我仍然在适应这个我们生活的美好世界,在那里我们可以看一下源代码,看看发生了什么......

为了其他可能感兴趣的人的利益,我采用了TextPaint.setTextSize()方法的快捷方式,而不是深入研究Canvas.drawText(),所以我的onDraw()现在如下:

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

    TextPaint textPaint = this.getPaint();
    Rect bounds = new Rect();

    String text = (String)this.getText();
    float textSize = this.getTextSize();
    int viewWidth = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
    textPaint.getTextBounds(text, 0, text.length(), bounds);
    int textWidth = bounds.width();

    float newTextSize = (float)Math.floor(textSize * viewWidth/textWidth);

    // note: adapted from TextView.setTextSize(), removing invalidate() call:

    // get the raw text size...
    Context c = getContext();
    Resources r = c==null ? Resources.getSystem() : c.getResources();
    int unit = TypedValue.COMPLEX_UNIT_SP;
    float rawSize = TypedValue.applyDimension(unit, newTextSize, r.getDisplayMetrics());

    // ... and apply it directly to the TextPaint
    textPaint.setTextSize(rawSize);
}

......它有效。谢谢!