自定义蜘蛛网图 NetView

概述

写论文忙里偷闲写了一个蜘蛛网图的自定义view,支持多重属性
有图才能有真相,下面先上图
自定义蜘蛛网图 NetView_第1张图片

主要支持网格颜色、tag文本、覆盖区域颜色、透明度的属性改变,具体使用可以参见我的githubgithub完整下载,求互粉求start,下面主要介绍一下实现这个自定义控件的几个关键点。

确定属性

首先要知道这个控件需要暴露出哪些属性,创建一个attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="netView">
        <attr name="netColor" format="color"/>
        <attr name="overlayColor" format="color"/>
        <attr name="textColor" format="color"/>
        <attr name="overlayAlpha" format="integer"/>
        <attr name="tagsize" format="integer"/>
    </declare-styleable>

</resources>

通常是在自定义view中通过TypedArray 来获取属性,使用完后之后使用recycle回收,如果属性较多的话写到一个文件中会显得过于臃肿,个人比较喜欢单独用一个类来处理,然后在自定义view中new一个出来这样会显得很简洁,具体可以参见我的代码。

onDraw

  • 画网
  • 画文本
  • 画显示区域
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawNet(canvas);
        drawText(canvas);
        drawRegion(canvas);
    }

画网主要分为俩大部分,画六边形和径线,
画六边形,每次先移动到圆心位置,A点,然后使用lineTo划线,如下图所示
自定义蜘蛛网图 NetView_第2张图片
使用到了一点正余弦的数学知识比较简单。

画文本需要自己做一下微调,要是不微调就会出现下图所示的问题
自定义蜘蛛网图 NetView_第3张图片
首先我们要获取字符的宽和高
宽比较简单

 float dis = textPaint.measureText(titles[i]);//获取文本长度

高就涉及到一些比较生僻的api的使用

  Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
  float fontHeight = fontMetrics.descent - fontMetrics.ascent; //文字的高度

关于文字的更详细的讲解可以参阅android详细的文字操作

最后就是画区域同样是利用path的moveTo和lineTo俩个属性来画线,然后path.close闭合曲线比较简单

onMeasure

一开始没有写这个发现wrap_content无法使用(使用了还是出现match_parent的效果),这是由于使用wrap_content时候此时sepcMode为AT_MOST,此时宽高为parentSizes即父容器的大小,因此跟使用match_parent效果一致,做了如下改写:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize =MeasureSpec.getSize(widthMeasureSpec);
        int heighSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heighSpecSize =MeasureSpec.getSize(heightMeasureSpec);
        if(widthSpecMode==MeasureSpec.AT_MOST&&heighSpecMode==MeasureSpec.AT_MOST){
            setMeasuredDimension(200,200);
        }else if(widthSpecMode==MeasureSpec.AT_MOST){
            setMeasuredDimension(200,heighSpecSize);
        }else if(heighSpecMode==MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSpecSize,200);

        }
    }

这样就可以避免这个问题了。
总的看来这个自定义控件比较基础,看在码这么多字也不容易的份上,git互粉点个start吧

你可能感兴趣的:(控件,网格,蜘蛛网图)