java 在视图上画一个圆圈(android)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25961263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Draw a circle onto a view (android)
提问by Tak3r07
I am starting with my first attempts to write an android app. I'd like to to visualize the Monte-Carlo-Approximation for pi. Hence I first want to draw a Circle onto a view but i dont get it working! I have tried to create my own "CircleView" Class which extends "View" and overwrite the onDraw(..) method like its explained over here: How to draw circle by canvas in Android?
我从我第一次尝试编写一个 android 应用程序开始。我想可视化 pi 的蒙特卡罗近似。因此我首先想在视图上绘制一个圆,但我没有让它工作!我试图创建我自己的“CircleView”类,它扩展了“View”并覆盖了 onDraw(..) 方法,就像这里解释的那样:How to draw circle by canvas in Android?
This is my CircleView Class
这是我的 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);
}
}
I have inserted the CircleView into a LinearLayout with the following XML-code
我已使用以下 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"/>
(Btw Android Studio is telling me in the XML-view at the right side: "Rendering Problems Custom view CircleView is not using the 2- or 3-argument View constructors; XML attributes will not work")
(顺便说一句,Android Studio 在右侧的 XML 视图中告诉我:“渲染问题自定义视图 CircleView 未使用 2 或 3 参数视图构造函数;XML 属性不起作用”)
The App just crashes with the following log: http://pastebin.com/Gv1GaHtX
该应用程序崩溃并显示以下日志:http: //pastebin.com/Gv1GaHtX
Can someone tell what i did wrong?
有人能告诉我我做错了什么吗?
I thought this setup would create an activity with a view which displays a circle.
我认为这个设置会创建一个带有显示圆圈的视图的活动。
Regards
问候
Edit: Crash is fixed by adding the 2 and 3 Parameter Constructor in CircleView (See https://stackoverflow.com/a/13797457/3248708)
编辑:通过在 CircleView 中添加 2 和 3 参数构造函数来修复崩溃(参见https://stackoverflow.com/a/13797457/3248708)
But now i still do not see any Circle in the activity
但现在我仍然没有在活动中看到任何圆圈
回答by Michael Krause
A couple of observations:
几个观察:
You need to take into account the width and height assigned to your view when determining your circle's center point and radius.
在确定圆的中心点和半径时,您需要考虑分配给视图的宽度和高度。
You should take into account the padding assigned to your View so you don't draw in that reserved portion.
您应该考虑分配给您的视图的填充,这样您就不会在该保留部分中进行绘制。
You should avoid allocating objects within your onDraw method since this gets called a lot.
您应该避免在 onDraw 方法中分配对象,因为这会被调用很多。
In order to allow your view to be specified in an XML layout, you need to provide the constructor that takes a Context and an AttributeSet. The AttributeSet is the mechanism by which your XML attributes are passed to your view.
为了允许在 XML 布局中指定您的视图,您需要提供接受 Context 和 AttributeSet 的构造函数。AttributeSet 是将 XML 属性传递给视图的机制。
Give this a try:
试试这个:
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);
}
}
回答by Mr.Hosseini
You can create a Circular layout and inside this view, every childs should be rounded up :
你可以创建一个圆形布局,在这个视图中,每个孩子都应该四舍五入:
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;
}
}