Android 如何绘制填充多边形?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2047573/
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
How to draw filled polygon?
提问by AndroiDBeginner
How to draw filled polygon in Android ?
如何在 Android 中绘制填充多边形?
采纳答案by Adrian Faciu
You need to set the paint object to FILL
您需要将绘制对象设置为 FILL
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
Then you can draw whatever you want, and it will be filled.
然后你可以画任何你想要的东西,它就会被填满。
canvas.drawCircle(20, 20, 15, paint);
canvas.drawRectangle(60, 20, 15, paint);
etc.
等等。
For more complex shapes you need to use the PATH object.
对于更复杂的形状,您需要使用PATH 对象。
回答by Androidcoder
Android does not have a handy drawPolygon(x_array, y_array, numberofpoints)
action like Java. You have to walk through making a Path
object point by point. For example, to make a filled trapezoid shape for a 3D dungeon wall, you could put all your points in x and y arrays then code as follows:
Android 没有drawPolygon(x_array, y_array, numberofpoints)
像 Java 那样方便的操作。您必须Path
逐点创建对象。例如,要为 3D 地牢墙制作一个填充梯形形状,您可以将所有点放在 x 和 y 数组中,然后代码如下:
Paint wallpaint = new Paint();
wallpaint.setColor(Color.GRAY);
wallpaint.setStyle(Style.FILL);
Path wallpath = new Path();
wallpath.reset(); // only needed when reusing this path for a new build
wallpath.moveTo(x[0], y[0]); // used for first point
wallpath.lineTo(x[1], y[1]);
wallpath.lineTo(x[2], y[2]);
wallpath.lineTo(x[3], y[3]);
wallpath.lineTo(x[0], y[0]); // there is a setLastPoint action but i found it not to work as expected
canvas.drawPath(wallpath, wallpaint);
To add a constant linear gradient for some depth, you could code as follows. Note y[0] is used twice to keep the gradient horizontal:
要为某个深度添加恒定的线性渐变,您可以编写如下代码。注意 y[0] 被使用了两次以保持梯度水平:
wallPaint.reset(); // precaution when resusing Paint object, here shader replaces solid GRAY anyway
wallPaint.setShader(new LinearGradient(x[0], y[0], x[1], y[0], Color.GRAY, Color.DKGRAY,TileMode.CLAMP));
canvas.drawPath(wallpath, wallpaint);
Refer to Paint, Pathand Canvasdocumentation for more options, such as array defined gradients, adding arcs, and laying a Bitmap over your polygon.
回答by Nux
I like to do it in three steps...
我喜欢分三步做...
Step 1. Create a pointy class ;-)
步骤 1. 创建一个尖头类 ;-)
/**
* Simple point
*/
private class Point {
public float x = 0;
public float y = 0;
public Point(float x, float y) {
this.x = x;
this.y = y;
}
}
Step 2. Add a method/function for drawing
步骤 2. 添加绘图方法/函数
/**
* Draw polygon
*
* @param canvas The canvas to draw on
* @param color Integer representing a fill color (see http://developer.android.com/reference/android/graphics/Color.html)
* @param points Polygon corner points
*/
private void drawPoly(Canvas canvas, int color, Point[] points) {
// line at minimum...
if (points.length < 2) {
return;
}
// paint
Paint polyPaint = new Paint();
polyPaint.setColor(color);
polyPaint.setStyle(Style.FILL);
// path
Path polyPath = new Path();
polyPath.moveTo(points[0].x, points[0].y);
int i, len;
len = points.length;
for (i = 0; i < len; i++) {
polyPath.lineTo(points[i].x, points[i].y);
}
polyPath.lineTo(points[0].x, points[0].y);
// draw
canvas.drawPath(polyPath, polyPaint);
}
Step 3. Draw
步骤 3. 画画
drawPoly(canvas, 0xFF5555ee,
new Point[]{
new Point(10, 10),
new Point(15, 10),
new Point(15, 20)
});
Yes, you could probably do it more efficiently, but probably not much more readable :-).
是的,您可能可以更有效地做到这一点,但可能不会更具可读性:-)。
回答by luQ
Draw Polygon with x sides and custom radius:
用 x 边和自定义半径绘制多边形:
private void drawPolygon(Canvas mCanvas, float x, float y, float radius, float sides, float startAngle, boolean anticlockwise, Paint paint) {
if (sides < 3) { return; }
float a = ((float) Math.PI *2) / sides * (anticlockwise ? -1 : 1);
mCanvas.save();
mCanvas.translate(x, y);
mCanvas.rotate(startAngle);
Path path = new Path();
path.moveTo(radius, 0);
for(int i = 1; i < sides; i++) {
path.lineTo(radius * (float) Math.cos(a * i), radius * (float) Math.sin(a * i));
}
path.close();
mCanvas.drawPath(path, paint);
mCanvas.restore();
}
回答by user1325094
BTW - I discovered that once you begin creating your path, any moveTo commands within the path will mean that the shape is left unfilled.
顺便说一句 - 我发现一旦你开始创建你的路径,路径中的任何 moveTo 命令都意味着形状没有被填充。
It makes sense when you think about it, that Android/Java would leave the shape unfilled as the moveTo would represent a break in the polygon.
当您考虑它时,Android/Java 会保留未填充的形状,因为 moveTo 将表示多边形的中断。
However I've seen some tutorials like this How to draw a filled triangle in android canvas?
但是我看过一些这样的教程如何在android画布中绘制一个实心三角形?
which have moveTo's after each lineTo. Even though this may result in an unbroken polygon, Android assumes that a moveTo represents a break in the polygon.
每个 lineTo 之后都有 moveTo。尽管这可能会导致多边形完整,但 Android 假定 moveTo 表示多边形的中断。
回答by netsplit
Old question, but a trick for anyone who finds this. If you include a font with the desired polygon as a glyph you can use the drawText function to draw your polygon.
老问题,但对任何发现此问题的人来说都是一个技巧。如果您包含具有所需多边形的字体作为字形,则可以使用 drawText 函数绘制多边形。
The downside is you have to know ahead of time what shapes you'll need. The upside it is if you do know ahead of time you can include a nice shape library. This code assumes you have a font called shapes in your assets/fonts folder of your project.
缺点是你必须提前知道你需要什么形状。好处是如果您提前知道,您可以包含一个不错的形状库。此代码假设您的项目的 assets/fonts 文件夹中有一个名为 shape 的字体。
TypeFace shapesTypeFace = Typeface.createFromAsset(getAssets(), "fonts/shapes.ttf");
Paint stopSignPaint = new Paint();
stopSignPaint.setColor(Color.RED);
//set anti-aliasing so it looks nice
stopSignPaint.setAntiAlias(true);
stopSignPaint.setTextSize(200);
stopSignPaint.setTypeface(shapesTypeFace);
//will show up as a box or question mark since
//the current display font doesn't have this glyph.
//open the shapes font in a tool like Character Map
//to copy and paste the glyph into your IDE
//saving it as a variable makes it much easier to work with
String hexagonGlyph = "["
String triangleGlyph = "["
....whatever code you got...
//arguments: text, x coordinate, y coordinate, paint
canvas.drawText(hexagonGlyph, 200, 100, stopSignPaint);
//make it into a go sign
stopSignPaint.setColor(Color.Green);
canvas.drawText(hexagonGlyph, 200, 100, stopSignPaint);
//make a tiny one
stopSignPaint.setTextSize(20);
stopSignPaint.setColor(Color.RED);
canvas.drawText(hexagonGlyph, 200, 100, stopSignPaint);
//make a triangle
canvas.drawText(triangleGlyph, 200, 100, stopSignPaint);
回答by Daniel Nyamasyo
Try this, or see the full demo
试试这个,或者看完整的演示
Paint paint = new Paint();
paint.setColor(Color.parseColor("#BAB399"));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
回答by Abed
This class can be used to draw any kind of polygons. Just call drawPolygonPath()
in onDraw() method.
此类可用于绘制任何类型的多边形。只需调用drawPolygonPath()
onDraw() 方法。
class PolygonView : View {
constructor(context: Context?) : super(context) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
init()
}
private lateinit var paint: Paint
private fun init() {
paint = Paint().apply {
color = Color.RED
isAntiAlias = true
style = Paint.Style.FILL
strokeWidth = 10f
}
}
override fun onDraw(canvas: Canvas) {
canvas.drawPath(drawPolygonPath(8, 150f), paint)
canvas.drawPath(drawPolygonPath(5, 120f), paint)
}
/**
* @param sides number of polygon sides
* @param radius side length.
* @param cx drawing x start point.
* @param cy drawing y start point.
* */
private fun drawPolygonPath(
sides: Int,
radius: Float,
cx: Float = radius,
cy: Float = radius
): Path {
val path = Path()
val x0 = cx + (radius * cos(0.0).toFloat())
val y0 = cy + (radius * sin(0.0).toFloat())
//2.0 * Math.PI = 2π, which means one circle(360)
//The polygon total angles of the sides must equal 360 degree.
val angle = 2 * Math.PI / sides
path.moveTo(x0, y0)
for (s in 1 until sides) {
path.lineTo(
cx + (radius * cos(angle * s)).toFloat(),
cy + (radius * sin(angle * s)).toFloat()
)
}
path.close()
return path
}
}