先看效果
Paste_Image.png做起来很简单。就是用三角函数,算出五边形五个定点的坐标,然后根据左边连线就行了。根据看图。
images.png具体代码如下:
class FiveDimensionView extends View {
private Paint pentagonPaint;
private Paint coverPaint;
private TextPaint textPaint;
private Path path;
private Entity entity;
private float distance;
private Path coverPath;
public FiveDimensionView(Context context) {
this(context,null);
}
public FiveDimensionView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public FiveDimensionView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.FiveDimensionView);
//五边形边的宽度
float pentagonWidth=array.getDimension(R.styleable.FiveDimensionView_pentagon_width,dp2px(1));
//五边形边的颜色
int pentagonColor=array.getColor(R.styleable.FiveDimensionView_pentagon_color, Color.RED);
//覆盖区域的颜色
int coverColor=array.getColor(R.styleable.FiveDimensionView_cover_color,Color.BLUE);
//字体颜色
int textColor=array.getColor(R.styleable.FiveDimensionView_text_color,Color.BLACK);
//字体大小
float textSize=array.getDimension(R.styleable.FiveDimensionView_text_size,13);
//字体距离五边形顶点的长度
distance = array.getDimension(R.styleable.FiveDimensionView_text_distance,dp2px(5));
array.recycle();
//正五边形
pentagonPaint = new Paint();
pentagonPaint.setAntiAlias(true);
pentagonPaint.setColor(pentagonColor);
pentagonPaint.setStyle(Paint.Style.STROKE);
pentagonPaint.setStrokeWidth(pentagonWidth);
//覆盖区域
coverPaint = new Paint();
coverPaint.setAntiAlias(true);
coverPaint.setStyle(Paint.Style.FILL_AND_STROKE);
coverPaint.setColor(coverColor);
//文字
textPaint = new TextPaint();
textPaint.setColor(textColor);
textPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,textSize,context.getResources().getDisplayMetrics()));
textPaint.setAntiAlias(true);
path = new Path();
coverPath = new Path();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int width=0,height=0;
if(widthMode==MeasureSpec.AT_MOST){
width=dp2px(250);
}else{
width=widthSize;
}
if(heightMode==MeasureSpec.AT_MOST){
height=dp2px(250);
}else{
height=heightSize;
}
setMeasuredDimension(width,height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//半径
float radius=Math.min(getWidth(),getHeight())/2*0.8f;
canvas.save();
//原点移至当前view的中心
canvas.translate(getWidth()/2,getHeight()/2);
List<PointF> points = getPoints(radius);
//绘制五边形边
for(int i = 0; i< points.size(); i++){
PointF pointF = points.get(i);
if(i==0){
path.moveTo(pointF.x,pointF.y);
}else{
path.lineTo(pointF.x,pointF.y);
}
}
path.close();
canvas.drawPath(path,pentagonPaint);
//绘制圆心和顶点的连线
for(PointF pointF:points){
path.moveTo(0,0);
path.lineTo(pointF.x,pointF.y);
canvas.drawPath(path,pentagonPaint);
path.reset();
}
if(entity==null){
entity=new Entity();
entity.setTotal(1);
List<DisEntity>list=new ArrayList<>();
list.add(new DisEntity("第一",0));
list.add(new DisEntity("第二",0));
list.add(new DisEntity("第三",0));
list.add(new DisEntity("第四",0));
list.add(new DisEntity("第五",0));
entity.setList(list);
}
List<DisEntity> list = entity.getList();
//绘制覆盖区域
for(int i = 0; i< points.size(); i++){
PointF pointF = points.get(i);
float rate=list.get(i).getScore()*1.0f/entity.getTotal();
if(i==0){
coverPath.moveTo(pointF.x*rate,pointF.y*rate);
}else{
coverPath.lineTo(pointF.x*rate,pointF.y*rate);
}
}
coverPath.close();
canvas.drawPath(coverPath,coverPaint);
//绘制文字
for (int i=0;i<points.size();i++){
PointF pointF = points.get(i);
String title = list.get(i).getTitle();
Rect bounds = new Rect();
//获取字体宽高
textPaint.getTextBounds(title,0,title.length(),bounds);
float textWidth = bounds.width();
int textHeight= bounds.height();
switch (i){
case 0:
canvas.drawText(title,pointF.x-textWidth/2,pointF.y-distance,textPaint);
break;
case 1:
canvas.drawText(title,pointF.x+distance,pointF.y+textHeight/2,textPaint);
break;
case 2:
canvas.drawText(title,pointF.x+distance-textWidth/2,pointF.y+distance+textHeight,textPaint); break;
case 3:
canvas.drawText(title,pointF.x-distance-textWidth/2,pointF.y+textHeight+distance,textPaint);
break;
case 4:
canvas.drawText(title,pointF.x-distance-textWidth,pointF.y+textHeight/2,textPaint);
break;
}
}
canvas.restore();
}
//获取正五边形五个顶点
private List<PointF> getPoints(float radius){
List<PointF>points=new ArrayList<>();
points.add(new PointF(0,-radius));//第0个点
//第1个点
points.add(new PointF((float)(radius*Math.cos(Math.toRadians(18))),-(float)(radius*Math.sin(Math.toRadians(18)))));
//第2个点
points.add(new PointF((float)(radius*Math.sin(Math.toRadians(36))),(float)(radius*Math.cos(Math.toRadians(36)))));
//第3个点
points.add(new PointF((float)(-radius*Math.sin(Math.toRadians(36))),(float)(radius*Math.cos(Math.toRadians(36)))));
//第4个点
points.add(new PointF((float)(-radius*Math.cos(Math.toRadians(18))),-(float)(radius*Math.sin(Math.toRadians(18)))));
return points;
}
public Entity getEntity() {
return entity;
}
public void setEntity(Entity entity) {
this.entity = entity;
invalidate();
}
private int dp2px(int dp){
return (int) (getContext().getResources().getDisplayMetrics().density*dp+0.5);
}
}
代码中用到的实体类
public class Entity {
//集合中是顶点上文字和文字所对应的分数
private List<DisEntity> list;
//total是总分,根据分数和总分的比值,得到覆盖区域的顶点
private int total;
public List<DisEntity> getList() {
return list;
}
public void setList(List<DisEntity> list) {
this.list = list;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
public class DisEntity {
private String title;
private int score;
public DisEntity(String title, int score) {
this.title = title;
this.score = score;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
自定义控件在布局中的使用
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="example.com.dimensionview.MainActivity">
<example.com.dimensionview.FiveDimensionView
android:id="@+id/five"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FiveDimensionView five= (FiveDimensionView)findViewById(R.id.five);
Entity entity=new Entity();
entity.setTotal(10);
List<DisEntity>list=new ArrayList<>();
list.add(new DisEntity("第1",4));
list.add(new DisEntity("第2",5));
list.add(new DisEntity("第3",6));
list.add(new DisEntity("第4",7));
list.add(new DisEntity("第5",8));
entity.setList(list);
five.setEntity(entity); }}
自定义属性
<declare-styleable name="FiveDimensionView">
<attr name="pentagon_width" format="dimension"></attr>
<attr name="pentagon_color" format="color"></attr>
<attr name="cover_color" format="color"></attr>
<attr name="text_size" format="dimension"></attr>
<attr name="text_color" format="color"></attr>
<attr name="text_distance" format="dimension"></attr>
</declare-styleable>
网友评论