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有不足的地方请在评论里回复(或者联系我)。
QQ:1006368252
相关文章推荐
- Android自定义View——多边形网格属性图
- Android 自定义View PolygonsView多边形能力分析控件
- android自定义View创建一个Path绘制多边形,贝塞尔曲线,
- Android 自定义View 仿蚂蚁信用分析(正多边形)
- Android自定义View实现多边形统计图示例代码
- Android自定义View【实战教程】4⃣️----BitmapShader详解及圆形、圆角、多边形实现
- android菜鸟测试之Aj_02的Android 中自定义View的应用,在main.xml中嵌入自己写的view
- Android高手进阶教程(三)之----Android 中自定义View的应用
- 自定义Android组件之带图像的TextView(转)
- android 自定义view的样式
- Android游戏开发之旅(六)自定义View
- Android 中自定义View的应用.
- Android\OPhone自定义视图(View) 推荐
- Android自定义View实例AnalogClock源码
- Android高手进阶教程(三)之----Android 中自定义View的应用
- Android 自定义 View
- 【Android日记】自定义View及其布局问题
- (转)自定义Android组件之带图像的TextView
- Android开发中自定义View设定到FrameLayout布局中实现多组件显示
- 自定义Android组件之带图像的TextView