需求千奇百怪,对于登录后账户的头像,要求圆形、多边形、带描边、带 VIP 标示等等,所以实现一个 N 边形玩玩,效果和代码如下。
多边形各顶点计算公式如下:
(1)正多边形的中心点为(0,0)
for (i = 0; i < n; i++) {
printf("%f %f\n", r * Math.cos(2 * Math.PI * i / n), r * Math.sin(2 * Math.PI * i / n));
}
x轴坐标为 r * Math.cos(2 * Math.PI * i / n)
y轴坐标为 r * Math.sin(2 * Math.PI * i / n)
(2)正多边形的中心点为(a,b)
for (i = 0; i < n; i++) {
printf("%f %f\n",a + r * Math.cos(2 * Math.PI * i / n), b+ r * Math.sin(2 * Math.PI * i / n));
}
x轴坐标为 a + r * Math.cos(2 * Math.PI * i / n)
y轴坐标为 b + r * Math.sin(2 * Math.PI * i / n)
算法原文链接:https://blog.csdn.net/wuprogrammer/article/details/108903244
![](https://i-blog.csdnimg.cn/blog_migrate/c1485a56edd9f619756c9484681d3aa7.jpeg)
12 边形
public class TestView extends View {
private static final int DEF_SIDE_LENGTH = 6;
private static final int DEF_SIZE = 66;
private int sideLength;
private Paint paint;
private Context context;
private Path path;
private int bgRes;
private int radius;
public TestView(Context context) {
super(context);
init(context, null);
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, @Nullable AttributeSet attrs) {
this.context = context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TestView);
sideLength = typedArray.getInt(R.styleable.TestView_side_length, DEF_SIDE_LENGTH);
bgRes = typedArray.getResourceId(R.styleable.TestView_bg_res, 0);
typedArray.recycle();
if(bgRes != 0){
initPaint();
}
}
private void initPaint() {
paint = new Paint();
paint.setColor(ContextCompat.getColor(context, android.R.color.black));
paint.setStrokeWidth(10f);
paint.setAntiAlias(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), bgRes);
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader) ;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(bgRes == 0){
return;
}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if(widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY){
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
radius = Math.min(width, height) / 2;
}else {
float scale = context.getResources().getDisplayMetrics().density;
int size = (int) (DEF_SIZE * scale + 0.5f);
radius = size / 2;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
initPoint();
}
public void setSideLength(int sideLength) {
this.sideLength = sideLength;
initPoint();
invalidate();
}
private void initPoint() {
if(null == path){
path = new Path();
}
path.reset();
for (int i = 1; i <= sideLength; i++) {
float x = (float)(radius * Math.cos(2 * Math.PI * i / sideLength)) + radius;
float y = (float)(radius * Math.sin(2 * Math.PI * i / sideLength)) + radius;
if(i == 1){
path.moveTo(x, y);
}else {
path.lineTo(x, y);
}
}
path.close();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(bgRes != 0){
canvas.drawPath(path, paint);
}
}
}
自定义属性如下
<declare-styleable name="TestView">
<attr name="side_length" format="integer" />
<attr name="bg_res" format="reference" />
</declare-styleable>