平台
RK3288 + Android 7.1 + Android Studio Chipmunk | 2021.2.1
问题
重写也TextView, 尝试在onDraw中绘制一些图形时不能正确显示出来.
比如, 给TextView 增加下个蓝色边框, 再绘制一条从左上到右下的绿色直线
然而, 实际的效果却是
根源及解决方法
先看下代码:
import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.View; import android.widget.TextView; public class TextViewTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final XTextView tv = new XTextView(this); tv.setTextSize(32); tv.setTextColor(Color.RED); tv.setText("Test"); tv.setSingleLine(true); tv.setGravity(Gravity.CENTER); tv.setTag(0); setContentView(tv); } static class XTextView extends TextView { Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); int W, H; public XTextView(Context context) { super(context); } public XTextView(Context context, AttributeSet attrs) { super(context, attrs); } public XTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); W = w; H = h; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //draw line leftTop to rightBottom mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.GREEN); mPaint.setStrokeWidth(2); canvas.drawLine(0, 0, W, H, mPaint); //draw rect for view. mPaint.setColor(Color.BLUE); canvas.drawRect(0, 0, W, H, mPaint); } } }
问题的根源就在于这两行代码:
tv.setSingleLine(true); tv.setGravity(Gravity.CENTER);
google 后, 在Canvas.drawRect is not work in TextView’s onDraw when set gravity中发现了同样的问题.
当SingleLine和Gravity.CENTER同时出现设置后, 会出现上面的问题, 尝试注释
tv.setSingleLine(true);
或
tv.setGravity(Gravity.CENTER);
确实可以解决这个问题.
PS: 除了Gravity.CENTER, Gravity.CENTER_HORIZONTAL 同样会引起这个问题
解决方法, 在前面的链接中已经有提及.
另一种方法: 通过canvas.getClipBounds(bound); 获取视窗的坐标.
Rect bound = new Rect(); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //get bound for viewport canvas.getClipBounds(bound); Log.d("XTextView", "onDraw " + getText() + ":" + bound.toShortString()); Log.d("XTextView", "onDraw " + getText() + ":" + getScrollX() + "," + getScrollY()); //draw line leftTop to rightBottom mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.GREEN); mPaint.setStrokeWidth(2); canvas.drawLine(bound.left, bound.top, bound.right, bound.bottom, mPaint); //draw rect for view. mPaint.setColor(Color.BLUE); canvas.drawRect(bound, mPaint); //canvas.drawRect(bound, mPaint); }
参考
Canvas.drawRect is not work in TextView’s onDraw when set gravity