您的位置:首页 > 移动开发 > Android开发

Android自定义view,ShapeView,多边形

2017-03-27 17:59 162 查看

童鞋们,你还在为绘制常用的多边形而烦恼吗?不用怕,小福利,有需要的尽管拿去!

ShapeView,支持圆、三角形、正方形、五边形、五角星、六边形。


效果图:



代码

attr.xml

<declare-styleable name="ShapeView">
<attr name="sv_color" format="color|reference" />
<attr name="sv_stroke_width" format="dimension" />
<attr name="sv_style">
<enum name="fill" value="0" />
<enum name="stroke" value="1" />
</attr>
<attr name="sv_shape">
<enum name="circle" value="0" />
<enum name="triangle" value="1" />
<enum name="rectangle" value="2" />
<enum name="pentagon" value="3" />
<enum name="pentagram" value="4" />
<enum name="sexangle" value="5" />
</attr>
</declare-styleable>


view源码:

ShapeView.java

package exam.org.jsc.password.view;

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

import exam.org.jsc.password.R;

/**
* Created by Justin Qin on 3/25/2017.
*/

public class ShapeView extends View {
Paint mPaint;
int color;
int strokeWidth;
int viewShape;
int paintStyle;

private static final ViewShape[] sShapeArray = {
ViewShape.CIRCLE,
ViewShape.TRIANGLE,
ViewShape.RECTANGLE,
ViewShape.PENTAGON,
ViewShape.PENTAGRAM,
ViewShape.SEXANGLE,
};

private static final PaintStyle[] sStyleArray = {
PaintStyle.FILL,
PaintStyle.STROKE
};

enum ViewShape {
/**圆*/
CIRCLE (0),
/**三角形*/
TRIANGLE (1),
/**四边形*/
RECTANGLE (2),
/**五边形*/
PENTAGON (3),
/**五角星*/
PENTAGRAM (4),
/**六边形*/
SEXANGLE (5);

ViewShape(int shape) {
this.shape = shape;
}
final int shape;
}

enum PaintStyle {
FILL (0),
STROKE (1);

PaintStyle(int style) {
this.style = style;
}
final int style;
}

public ShapeView(Context context) {
this(context, null);
}

public ShapeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ShapeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ShapeView);
color = array.getColor(R.styleable.ShapeView_sv_color, Color.TRANSPARENT);
strokeWidth = array.getDimensionPixelSize(R.styleable.ShapeView_sv_stroke_width, 2);
viewShape = array.getInt(R.styleable.ShapeView_sv_shape, 0);
paintStyle = array.getInt(R.styleable.ShapeView_sv_style, 0);
array.recycle();
init();
}

private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(color);
mPaint.setStrokeWidth(strokeWidth);
mPaint.setStyle(sStyleArray[paintStyle] == PaintStyle.STROKE ? Paint.Style.STROKE : Paint.Style.FILL);
}

public void setViewShape(int viewShape) {
this.viewShape = viewShape;
postInvalidate();
}

public void setViewShape(ViewShape shape) {
for (int i = 0; i < sShapeArray.length; i++) {
if (shape == sShapeArray[i]){
this.viewShape = i;
break;
}
}
postInvalidate();
}

public void setPaintStyle(int paintStyle) {
this.paintStyle = paintStyle;
mPaint.setStyle(sStyleArray[paintStyle] == PaintStyle.STROKE ? Paint.Style.STROKE : Paint.Style.FILL);
postInvalidate();
}

public void setPaintStyle(PaintStyle style) {
for (int i = 0; i < sStyleArray.length; i++) {
if (style == sStyleArray[i])
this.paintStyle = i;
}
mPaint.setStyle(style == PaintStyle.STROKE ? Paint.Style.STROKE : Paint.Style.FILL);
postInvalidate();
}

public void setColor(int color) {
this.color = color;
mPaint.setColor(color);
postInvalidate();
}

public void setColor(String color) {
this.color = Color.parseColor(color);
mPaint.setColor(this.color);
postInvalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
int widthSize = getMeasuredWidth();
int heightSize = getMeasuredHeight();
//宽度等同
heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onSizeChanged(int w, int h, i
f6fc
nt oldw, int oldh) {
h = w;
super.onSizeChanged(w, h, oldw, oldh);
}

Path path = new Path();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();

float halfStrokeWidth = strokeWidth / 2.0f;
switch (sShapeArray[viewShape]){
case CIRCLE://圆
if (paintStyle == 1){
canvas.drawCircle(width / 2.0f, width / 2.0f, width / 2.0f - halfStrokeWidth, mPaint);
} else {
canvas.drawCircle(width / 2.0f, width / 2.0f, width / 2.0f, mPaint);
}
break;
case TRIANGLE://三角形
if (paintStyle == 1){
path.moveTo(width / 2.0f, strokeWidth);
path.lineTo(strokeWidth, height - halfStrokeWidth);
path.lineTo(width - strokeWidth, height - halfStrokeWidth);
} else {
path.moveTo(width / 2.0f, 0);
path.lineTo(0, height);
path.lineTo(width, height);
}
path.close();
canvas.drawPath(path, mPaint);
break;
case RECTANGLE://正方形
if (paintStyle == 1){
canvas.drawRect(halfStrokeWidth, halfStrokeWidth, width - halfStrokeWidth, height - halfStrokeWidth, mPaint);
} else {
canvas.drawRect(0, 0, width, height, mPaint);
}
break;
case PENTAGON://五边形
drawPentagon(canvas, width / 2, height / 2, width / 2, halfStrokeWidth);
break;
case PENTAGRAM://五角星
drawPentagram(canvas, width / 2, height / 2, width / 2, halfStrokeWidth);
break;
case SEXANGLE://六边形
drawSexangle(canvas, width / 2, height / 2, width / 2, halfStrokeWidth);
break;
}
}

/**
*
* @param canvas
* @param x0    圆心X坐标
* @param y0    圆心y坐标
* @param r
*/
public void drawPentagon(Canvas canvas, int x0, int y0, float r, float halfStrokeWidth) {
double ch = 72 * Math.PI / 180;// 圆心角的弧度数

if (paintStyle == 1)
r = r - halfStrokeWidth;

float x1 = x0;
float x2 = (float) (x0 - Math.sin(ch) * r);
float x3 = (float) (x0 + Math.sin(ch) * r);
float x4 = (float) (x0 - Math.sin(ch / 2) * r);
float x5 = (float) (x0 + Math.sin(ch / 2) * r);

float y1 = y0 - r;
float y2 = (float) (y0 - Math.cos(ch) * r);
float y3 = y2;
float y4 = (float) (y0 + Math.cos(ch / 2) * r);
float y5 = y4;

path.moveTo(x1, y1);
path.lineTo(x2, y2);
path.lineTo(x4, y4);
path.lineTo(x5, y5);
path.lineTo(x3, y3);
path.close();

canvas.drawPath(path, mPaint);
}

/**
*
* @param canvas
* @param x0    圆心X坐标
* @param y0    圆心y坐标
* @param r
*/
public void drawPentagram(Canvas canvas, int x0, int y0, float r, float halfStrokeWidth) {
double ch = 72 * Math.PI / 180;// 圆心角的弧度数

if (paintStyle == 1)
r = r - halfStrokeWidth;

float x1 = x0;
float x2 = (float) (x0 - Math.sin(ch) * r);
float x3 = (float) (x0 + Math.sin(ch) * r);
float x4 = (float) (x0 - Math.sin(ch / 2) * r);
float x5 = (float) (x0 + Math.sin(ch / 2) * r);

float y1 = y0 - r;
float y2 = (float) (y0 - Math.cos(ch) * r);
float y3 = y2;
float y4 = (float) (y0 + Math.cos(ch / 2) * r);
float y5 = y4;

if (paintStyle == 1){
path.moveTo(x1, y1 + strokeWidth);
path.lineTo(x4, y4 + strokeWidth);
path.lineTo(x3 - halfStrokeWidth, y3 + halfStrokeWidth);
path.lineTo(x2 + halfStrokeWidth, y2 + halfStrokeWidth);
path.lineTo(x5, y5 + strokeWidth);
} else {
path.moveTo(x1, y1);
path.lineTo(x4, y4);
path.lineTo(x3, y3);
path.lineTo(x2, y2);
path.lineTo(x5, y5);
}
path.close();

canvas.drawPath(path, mPaint);
}

/**
*
* @param canvas
* @param x0    圆心X坐标
* @param y0    圆心y坐标
* @param r
*/
public void drawSexangle(Canvas canvas, int x0, int y0, float r, float halfStrokeWidth) {
double ch = 60 * Math.PI / 180;// 圆心角的弧度数

if (paintStyle == 1)
r = r - halfStrokeWidth;

float x1 = x0;
float x2 = (float) (x0 - Math.sin(ch) * r);
float x3 = x2;
float x4 = x1;
float x5 = (float) (x0 + Math.sin(ch) * r);
float x6 = x5;

float y1 = y0 - r;
float y2 = (float) (y0 - Math.cos(ch) * r);
float y3 = (float) (y0 + Math.cos(ch) * r);
float y4 = y0 + r;
float y5 = y3;
float y6 = y2;

path.moveTo(x1, y1);
path.lineTo(x2, y2);
path.lineTo(x3, y3);
path.lineTo(x4, y4);
path.lineTo(x5, y5);
path.lineTo(x6, y6);
path.close();

canvas.drawPath(path, mPaint);
}
}


分解图:

五边形分解图



五角星分解图



六边形分解图



使用:

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="exam.org.jsc.password.activity.AboutActivity">

<include layout="@layout/title_bar" />

<TextView
android:id="@+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_marginTop="40dp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="circle"
app:sv_style="stroke"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="circle"
app:sv_style="fill"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="triangle"
app:sv_style="stroke"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="triangle"
app:sv_style="fill"/>

</LinearLayout>

<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_marginTop="40dp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="rectangle"
app:sv_style="stroke"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="rectangle"
app:sv_style="fill"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="pentagon"
app:sv_style="stroke"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="pentagon"
app:sv_style="fill"/>

</LinearLayout>

<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_marginTop="40dp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content">

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="pentagram"
app:sv_style="stroke"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="pentagram"
app:sv_style="fill"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="sexangle"
app:sv_style="stroke"/>

<exam.org.jsc.password.view.ShapeView
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
app:sv_color="@color/colorAccent"
app:sv_stroke_width="2px"
app:sv_shape="sexangle"
app:sv_style="fill"/>

</LinearLayout>

</LinearLayout>


谢谢您的惠顾,code有不足的地方请在评论里回复(或者联系我)。

QQ1006368252
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 绘制多边形