【问题标题】:Draw a circle onto a view (android)在视图上画一个圆圈(android)
【发布时间】:2014-11-15 15:54:09
【问题描述】:

我开始第一次尝试编写一个 Android 应用程序。我想可视化 pi 的 Monte-Carlo-Approximation。因此,我首先想在视图上绘制一个圆圈,但我没有让它工作! 我试图创建自己的“CircleView”类,它扩展了“View”并覆盖了 onDraw(..) 方法,就像这里解释的那样:How to draw circle by canvas in Android?

这是我的 CircleView 类

public class CircleView extends View {
    public CircleView(Context context) {
        super(context);
    }

    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(150);
        canvas.drawCircle(50,50,20,paint);
    }
}

我已使用以下 XML 代码将 CircleView 插入到 LinearLayout 中

<com.tak3r07.montecarlopi.CircleView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/circleView"
    android:layout_weight="1"/>

(顺便说一句,Android Studio 在右侧的 XML 视图中告诉我:“渲染问题自定义视图 CircleView 未使用 2 或 3 参数视图构造函数;XML 属性将不起作用”)

应用程序崩溃并显示以下日志:http://pastebin.com/Gv1GaHtX

谁能告诉我我做错了什么?

我认为这种设置会创建一个带有显示圆圈的视图的活动。

问候

编辑:通过在 CircleView 中添加 2 和 3 参数构造函数来修复崩溃(参见 https://stackoverflow.com/a/13797457/3248708

但现在我仍然没有在活动中看到任何圈子

【问题讨论】:

  • 您在编辑器或设备上没有看到任何圆圈?
  • 设备上的@DanielBo
  • 为什么不在 XML 中创建一个圆形并将其作为源添加到 ImageView 中?
  • 您是否尝试设置固定的宽度和高度值,例如 100dp?
  • @joao2fast4u 是的,我已经尝试过了。其他的不知道,我明天试试

标签: java android xml view


【解决方案1】:

几个观察:

在确定圆的中心点和半径时,您需要考虑分配给视图的宽度和高度。

您应该考虑分配给您的视图的填充,这样您就不会在该保留部分中绘制。

您应该避免在 onDraw 方法中分配对象,因为这会被大量调用。

为了允许在 XML 布局中指定视图,您需要提供接受 Context 和 AttributeSet 的构造函数。 AttributeSet 是将 XML 属性传递给视图的机制。

试试这个:

package com.tak3r07.montecarlopi;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class CircleView extends View
{
    private static final int DEFAULT_CIRCLE_COLOR = Color.RED;

    private int circleColor = DEFAULT_CIRCLE_COLOR;
    private Paint paint;

    public CircleView(Context context) 
    {
        super(context);
        init(context, null);
    }

    public CircleView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs)
    {
        paint = new Paint();
        paint.setAntiAlias(true);
    }

    public void setCircleColor(int circleColor)
    {
        this.circleColor = circleColor;
        invalidate();
    }

    public int getCircleColor()
    {
        return circleColor;
    }

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

        int w = getWidth();
        int h = getHeight();

        int pl = getPaddingLeft();
        int pr = getPaddingRight();
        int pt = getPaddingTop();
        int pb = getPaddingBottom();

        int usableWidth = w - (pl + pr);
        int usableHeight = h - (pt + pb);

        int radius = Math.min(usableWidth, usableHeight) / 2;
        int cx = pl + (usableWidth / 2);
        int cy = pt + (usableHeight / 2);

        paint.setColor(circleColor);
        canvas.drawCircle(cx, cy, radius, paint);
    }
}

【讨论】:

  • 谢谢,这为我画了一个圆圈。明天我将对此进行更深入的研究!
  • @MichaelKrause 如何在这个圈子上启用 ontouch 或 onclick 事件?
  • @PranavMS 由于 CircleView 在上面的示例中是一个视图,因此您可以覆盖布尔 onTouchEvent(MotionEvent event) 方法和/或通过调用 setOnClickListener(View.OnClickListener l) 在其上添加 onClickListener 您可能需要调用 setClickable(true),但不确定。
  • @Michael 你能看看这个吗? stackoverflow.com/questions/41421662/…这是我的问题。我想你可以帮我解决这个问题。
  • 如何在xml中设置圆圈颜色?
【解决方案2】:

你可以创建一个圆形布局,在这个视图中,每个孩子都应该四舍五入:

public class CircleView extends FrameLayout {

    private Bitmap maskBitmap;
    private Paint paint, maskPaint;


    public CircleView(Context context) {
        super(context);
        init();
    }

    public CircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

    }

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

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        Bitmap offscreenBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas offscreenCanvas = new Canvas(offscreenBitmap);

        super.draw(offscreenCanvas);

        if (maskBitmap == null) {
            maskBitmap = createMask(getWidth(), getHeight());
        }

        offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
        canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
    }

    private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);

        canvas.drawRect(0, 0, width, height, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), width/2f, height/2f, paint);

        return mask;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 2021-10-04
    • 1970-01-01
    相关资源
    最近更新 更多