【问题标题】:How can I get the canvas size of a custom view outside of the onDraw method?如何在 onDraw 方法之外获取自定义视图的画布大小?
【发布时间】:2011-10-02 21:40:48
【问题描述】:

我需要能够访问视图画布的大小来执行一些计算。由于某种原因,传递给onSizeChanged 的视图大小与传递给onDraw 的画布大小不同。我当前的解决方法使用布尔标志来确定何时需要进行计算。

理想的解决方案将允许我在 onSizeChanged 方法中进行这些计算,所以我想知道......有什么方法可以让我在外面获得 Canvas 对象(或至少它的尺寸) onDraw 方法?

我的代码如下。它以给定角度绘制圆的半径。当我使用canvas.centerX() 确定半径的起点和终点时,一切正常。如果我使用传递给onSizeChanged 的参数,它甚至远不接近正确。

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  mSizeChanged = true;
}

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

  if (mSizeChanged) {
    RectF bounds = new RectF(canvas.getClipBounds());
    float centerX = bounds.centerX();
    float centerY = bounds.centerY();
    float radianAngle = (float) Math.toRadians(mStartAngle);

    mRadius[0] = center;
    mRadius[1] = center;
    mRadius[2] = center + center * FloatMath.cos(radianAngle);
    mRadius[3] = center + center * FloatMath.sin(radianAngle);
    mSizeChanged = false;
  }

  mPaint.setColor(0xFF330000);
  mPaint.setStrokeWidth(1);
  canvas.drawLines(mRadius, mPaint);
}

【问题讨论】:

    标签: android view custom-view android-custom-view


    【解决方案1】:

    出于绘图目的,您不应真正使用Canvas 对象的尺寸。

    只需使用onSizeChanged 方法中提供给您的尺寸即可。您可以存储尺寸以在onDraw 方法中使用,也可以调整大小/绘制为稍后可以绘制的支持位图。

    更新:

    快速编写一些代码,看起来这样可以:

    public class CustomView extends View{
        private Paint paint;
        private int w;
        private int h;
    
        public CustomView(Context context, AttributeSet attr) {
            super(context, attr);
            paint = new Paint();
            paint.setTextAlign(Align.CENTER);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            this.w = w;
            this.h = h;
            super.onSizeChanged(w, h, oldw, oldh);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawColor(Color.WHITE);
            canvas.drawText("TEST", w/2, h/2, paint);   
        }
    }
    

    更新 2

    关注圈码更新。

    我们可以这样做:

       @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawColor(Color.WHITE);
            float centerX = (float) w/2;
            float centerY = (float) h/2;
            float radianAngle = (float) Math.toRadians(startAngle);
    
            radius[0] = centerX;
            radius[1] = centerY;
            radius[2] = centerX + centerX * FloatMath.cos(radianAngle);
            radius[3] = centerY + centerY * FloatMath.sin(radianAngle);
    
            paint.setColor(0xFF330000);
            paint.setStrokeWidth(1);
            canvas.drawLines(radius, paint);
        }
    

    您会发现这现在适用于任何大小的视图。

    【讨论】:

    • 我可以接受,但是 onSizeChanged 方法没有给我正确的数字。例如,假设我想在视图的中心绘制一些文本。如果我存储传递给 onSizeChanged 的​​值,并使用这些值来确定应在何处绘制文本,则它不会绘制在正确的位置。如果我使用画布尺寸来确定应在何处绘制文本,则效果很好。
    • 如果您将 w/2 和 h/2 值与 canvas.centerX() 和 canvas.centerY() 方法的结果进行比较,您会发现这些值是不同的。跨度>
    • 当我使用您的代码时,文本根本不会出现,因为 w/2 和 h/2 给出的坐标大于画布。因此,文本被绘制在屏幕上不显示的位置。
    • 画布宽度和高度将为您提供屏幕宽度和高度。您不想使用视图的尺寸(在 onSizeChanged 中给出)吗?如果您能透露更多您的绘图代码以帮助我们查明问题,那就太好了。
    • 我已经用更多代码更新了 OP。我希望能够使用视图的尺寸,但它不适合我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多