自定义View英雄联盟七星图
前两篇做了一下准备工作,现在开始正式进入我们的自定义View,采用第二种可动态计算多边形坐标的方案
一、观察及拆分UI图(假设是你们的UI设计师给你们的设计图?)
万事开头难,为了更好下手,我们先将其拆分,找最基础的开始着手
- 我们可以根据最前显示效果来拆分此view,我们先舍去文字、线条及红色线条,从它的正七边形背景来开始,从图中可以看出,此View相当于是四个不同的正七边形叠加而来,我们可以先绘制最大的正七边形,然后依次到最小的正七边形,当然要保证他们的中心点为同一个中心点,这样我们的正七边形背景就绘制好了;
- 绘制完我们的七边形背景后,根据绘制最前来反转绘制的话,现在应该来绘制不同的线条,由前两篇文章我们可以计算得到七边形的每个定点坐标,然后分别绘制中心点和七个顶点的连线,这样我们的简单连线就会治好来;
- 接下来我们可以绘制红色不规则七边形,我们可以把当作是一个正七边形来计算每个顶点坐标,只是每个顶点坐标的对应的正七边形外接圆的半径需要根据我们提供的能力占比来动态计算,然后在将这些顶点坐标连接起来就行来;
- 最后我们可以绘制对应能力的描述,当然此步骤可以在最外层的七边形坐标确定后即可绘制,或者是最外层七边形绘制完后进行绘制;
二、定义颜色和相关Power的字符串资源:
在上面我们确定来大致绘制流程后,接下来要准备一下我们需要用到的一些颜色和文字资源,我们可以使用AndroidStudio中自带的取色器来吸取4层七边形和线条对应的颜色:
-
从最外层的正七边形到最内层最小的七边形颜色分别为:
<color name="powerInfoViewInnerColor1">#D8EFF3</color> <color name="powerInfoViewInnerColor2">#A6DAE2</color> <color name="powerInfoViewInnerColor3">#70BEC4</color> <color name="powerInfoViewInnerColor4">#468690</color>
-
七条线条从最外侧到最内层的颜色为:
<color name="powerInfoViewLineColor1">#9CE1EA</color> <color name="powerInfoViewLineColor2">#A3E3EE</color> <color name="powerInfoViewLineColor3">#A3E3EE</color> <color name="powerInfoViewLineColor4">#A3E3EE</color>
-
对应的字符串资源我们可以在View类中直接定义:
private final String[] powerStr = {"击杀", "生存", "助攻", "物理", "魔法", "防御", "金钱"};
三、编写代码
到此我们正式进入我们的编码工作,按照上面定制的流程来编码;
-
创建我们的自定View类-PowerInfoView继承View
public class PowerInfoView extends View { public PowerInfoView(Context context) { super(context); } public PowerInfoView(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs) { super(context, attrs); } public PowerInfoView(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
-
根据view的绘制流程,我们下一步要对view的宽高来进行测量,重写view的onMeasure方法,对于:wrap_content 测量模式,暂不进行相关逻辑的设计,本人比较懒,还是将重点偏向于view的绘制渲染,如下:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec); int heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMeasureMode == MeasureSpec.EXACTLY) { viewWidth = MeasureSpec.getSize(widthMeasureSpec); } else { viewWidth = MeasureSpec.getSize(widthMeasureSpec); } if (heightMeasureMode == MeasureSpec.EXACTLY) { viewHeight = MeasureSpec.getSize(heightMeasureSpec); } else { viewHeight = MeasureSpec.getSize(heightMeasureSpec); } setMeasuredDimension(viewWidth, viewHeight); }
-
在测量完我们的view的宽高,我们可以对view进行绘制工作来,重写我们的onDraw()方法:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); }
-
按照上面定制分离的绘制流程来进行绘制,现在我们开始绘制七边形背景,要绘制七边形我们先要计算处每个七边形的对应的坐标,根据前两篇文章介绍,我们需要知道对应的七边形外接圆的半径,因此我们先要计算出最外层的正七边形的外接圆的半径,然后取其对应的3/4、1/2/、1/4来计算出递减的正七边形外接圆半径,考虑到对应的文字的宽高和对应的padding属性分别影响我们七边的绘制位置(当然我们可以不计算padding属性,这样我们在设置padding属性的时候,就不会起作用),由于我们的对应的文字都是两个字,且文字距离距离七边形有一点段距离,我们取文字所占的宽高要稍微宽些,下面我们来初始化和计算目前用到的相关数值:
private int viewWidth; //view宽 private int viewHeight;//view高 private int heptagonRadio;//最外层外接圆半径 private TextPaint mTextPaint;//绘制文字的画笔 private double averageAngle;//对应准备工作中计算公式中的 β //七边形背景对应颜色 private int[] powerInfoViewInnerColors = { //七边形背景对应颜色 R.color.powerInfoViewInnerColor1, R.color.powerInfoViewInnerColor2, R.color.powerInfoViewInnerColor3, R.color.powerInfoViewInnerColor4 }; //线条对应颜色 private int[] powerInfoViewLineColors = { R.color.powerInfoViewLineColor1, R.color.powerInfoViewLineColor2, R.color.powerInfoViewLineColor3, R.color.powerInfoViewLineColor4 }; //对应能力文字 private final String[] powerStr = {"击杀", "生存", "助攻", "物理", "魔法", "防御", "金钱"}; //实际测量文字宽高 private int textWidth, textHeight; public PowerInfoView(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs) { super(context, attrs); this.init(context, attrs);//初始化相关属性 } public PowerInfoView(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.init(context, attrs);//初始化相关属性 } private void init(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs) { this.mTextPaint = new TextPaint(); this.mTextPaint.setTextSize(50); this.mTextPaint.setAntiAlias(true); this.averageAngle = 2 * Math.PI / heptagonSideNum; }
接下来,初始化现阶段对应的属性后,开始计算我们最外层的半径,先测量文字原始的宽高:
Rect rect = new Rect(); this.mTextPaint.getTextBounds(powerStr[0], 0, powerStr[0].length(), rect); this.textHeight = rect.height(); this.textWidth = rect.width();
我们取对应文字宽度的5/4(this.textWidth * 5 / 4)作为文字绘制的宽度,文字高度为原始高度加上原始文字宽度的1/4(this.textHeight + this.textWidth * 1 / 4),然后我们分别用view的宽高减去对应的文字所占的宽高度,在减去对应的padding值,然后取最小值的一半来作为我们最外层外接圆半径:
this.heptagonRadio = Math.min(viewWidth - getPaddingLeft() - getPaddingRight() - textWidth * 5 / 2, viewHeight - getPaddingTop() - getPaddingBottom() - textHeight * 2 + textWidth / 2) >> 1;
这样我们最外层外接圆半径就计算出来来,结下分别取其对应的3/4、1/2、1/4即可,然后就是计算顶点坐标,在前两篇准备工作中,在计算坐标时,我们都需要对其进行平移,也就是加上对应的Δx 和 Δy,所以我们还需要计算出这两个值,其分别由paddingLeft 和 对应方位文字所占空间组成,所以得出:
this.deltaX = getPaddingLeft() + textWidth * 5 / 4; this.deltaY = getPaddingTop() + textHeight + textWidth / 4;
为了更好的计算和以面对对象的思维来进行编程,我们将对应的顶点封装成我们的多边形类如下:
public class Polygon implements Serializable { private List<DoublePoint> mPointList; private final int polygonSideNum; public Polygon(int polygonSideNum) { this.polygonSideNum = polygonSideNum; mPointList = new ArrayList<>(polygonSideNum); } public Polygon(List<DoublePoint> pointList, int polygonSideNum) { if (pointList.size() != polygonSideNum) { throw new IllegalArgumentException("多边形参数异常!"); } mPointList = pointList; this.polygonSideNum = polygonSideNum; } public List<DoublePoint> getPointList() { return mPointList; } public void setPointList(List<DoublePoint> pointList) { mPointList = pointList; } public int getPolygonSideNum() { return polygonSideNum; } /** * 从定义的定点逆时针旋转分别填充 * * @param point */ public void addPoint(DoublePoint point) { if (polygonSideNum == mPointList.size()) { throw new IllegalArgumentException("超过预定的多边形定点坐标!"); } mPointList.add(point); } public DoublePoint getPoint(int position) { if (position >= polygonSideNum || position < 0 || mPointList.isEmpty()) { return null; } return mPointList.get(position); } public void clearPoint() {//清除坐标集合 this.mPointList.clear(); } }
和double数据类型的Point类:
public class DoublePoint { private double x; private double y; public DoublePoint() { } public DoublePoint(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } }
接下来创建一个几何来存储4个对应的七边形类,在init方法中初始化:
this.mPolygons = new ArrayList<>(); this.mPolygons.add(new Polygon(heptagonSideNum)); this.mPolygons.add(new Polygon(heptagonSideNum)); this.mPolygons.add(new Polygon(heptagonSideNum)); this.mPolygons.add(new Polygon(heptagonSideNum)); this.dataPolygon = new Polygon(heptagonSideNum);
做了这么工作终于到了计算对应七边形坐标了,创建 completeHeptagonPoint()方法来计算如下:
private void completeHeptagonPoint() { double currentRadio; double currentAngle; for (int i = 0; i < heptagonNum; i++) { Polygon polygon = mPolygons.get(i); polygon.clearPoint();//每次绘制要清空坐标,防止集合溢出异常 currentRadio = (heptagonNum - i) * 1.0d / heptagonNum * heptagonRadio; for (int j = 0; j < heptagonSideNum; j++) { currentAngle = -Math.PI / 2 + j * averageAngle; polygon.addPoint( new DoublePoint( Math.cos(currentAngle) * currentRadio + heptagonRadio + deltaX, Math.sin(currentAngle) * currentRadio + heptagonRadio + deltaY) ); } }
计算就不再讲解,前两篇文章已经讲过了,现在我们就开始绘制七边形背景了,创建绘制画笔,并在init方法中初始化(此处略,最后贴出最终代码),创建绘制方法,drawHeptagonBackground(canvas)代码为:
private void drawHeptagonBackground(Canvas canvas) { Path path = new Path(); for (int i = 0; i < heptagonNum; i++) { mPaint.setColor(ContextCompat.getColor(getContext(), powerInfoViewInnerColors[i]));//变更颜色 List<DoublePoint> pointList = mPolygons.get(i).getPointList(); for (int j = 0; j < heptagonSideNum; j++) { DoublePoint doublePoint = pointList.get(j); if (j == 0) { path.moveTo((float) doublePoint.getX(), (float) doublePoint.getY()); } else { path.lineTo((float) doublePoint.getX(), (float) doublePoint.getY()); } } path.close(); canvas.drawPath(path, mPaint);//绘制每一层七边形 path.reset();//重置路径 } }
到此我们先来看一下运行效果吧,期待已久:
-
-
在七边形背景绘制完成后我们来绘制,对应的线条,创建线条绘制方法:drawHeptagonLine(canvas)代码为:
private void drawHeptagonLine(Canvas canvas) { float ox = heptagonRadio + deltaX; float oy = heptagonRadio + deltaY; for (int i = 0; i < heptagonNum; i++) { mPaint.setColor(ContextCompat.getColor(getContext(), powerInfoViewLineColors[i])); List<DoublePoint> pointList = mPolygons.get(i).getPointList(); for (int j = 0; j < heptagonSideNum; j++) { DoublePoint doublePoint = pointList.get(j); canvas.drawLine(ox, oy, (float) doublePoint.getX(), (float) doublePoint.getY(), mPaint); } } }
再次运行看一下效果:
-
绘制文字,我们取文字宽度的1/4来作为文字和七边形的距离,分别绘制对应的文字,创建文字绘制方法drawHeptagonPowerStr(canvas)代码为:
private void drawHeptagonPowerStr(Canvas canvas) { List<DoublePoint> pointList = mPolygons.get(0).getPointList(); DoublePoint doublePoint = pointList.get(0); canvas.drawText(powerStr[0], (float) (doublePoint.getX() - textWidth / 2), (float) (doublePoint.getY() - textWidth / 4), mTextPaint); doublePoint = pointList.get(1); canvas.drawText(powerStr[1], (float) (doublePoint.getX() + textWidth / 4), (float) (doublePoint.getY() - mTextPaint.descent()), mTextPaint); doublePoint = pointList.get(2); canvas.drawText(powerStr[2], (float) (doublePoint.getX() + textWidth / 4), (float) (doublePoint.getY() + textHeight / 2), mTextPaint); doublePoint = pointList.get(3); canvas.drawText(powerStr[3], (float) (doublePoint.getX() + textWidth / 4), (float) (doublePoint.getY() - mTextPaint.ascent()), mTextPaint); doublePoint = pointList.get(4); canvas.drawText(powerStr[4], (float) (doublePoint.getX() - textWidth * 5 / 4), (float) (doublePoint.getY() - mTextPaint.ascent()), mTextPaint); doublePoint = pointList.get(5); canvas.drawText(powerStr[5], (float) (doublePoint.getX() - textWidth * 5 / 4), (float) (doublePoint.getY() + textHeight / 2), mTextPaint); doublePoint = pointList.get(6); canvas.drawText(powerStr[6], (float) (doublePoint.getX() - textWidth * 5 / 4), (float) (doublePoint.getY() - mTextPaint.descent()), mTextPaint); }
在运行来看一下运行结果:
-
最终绘制对应数据能力所占的百分比,创建double型集合存储对应的数据占比
private List<Double> dataPercents;
,我们并不对其进行初始化,通过set方法来动态的初始化数据,然后重新绘制:public void setDataPercents(List<Double> dataPercents) { this.dataPercents = dataPercents; invalidate(); }
在得到对应能力百分比值时,我们开始计算我们的每个能力值所对应的的坐标,在方法completeHeptagonPoint添加代码:
if (dataPercents != null) { dataPolygon.clearPoint();//清除上次对应的坐标防止集合溢出异常 for (int j = 0; j < heptagonSideNum; j++) { currentRadio = dataPercents.get(j) * heptagonRadio; currentAngle = -Math.PI / 2 + j * averageAngle; dataPolygon.addPoint( new DoublePoint( Math.cos(currentAngle) * currentRadio + heptagonRadio + deltaX, Math.sin(currentAngle) * currentRadio + heptagonRadio + deltaY)); } }
而在ondraw方法中绘制时,我们要对数据源进行判断,若没有初始化(判空)则不进行绘制,创建我们的数据绘制方法drawPercentHeptagon(canvas),具体代码如下:
private void drawPercentHeptagon(Canvas canvas) { Path path = new Path(); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(10); List<DoublePoint> pointList = dataPolygon.getPointList(); for (int j = 0; j < heptagonSideNum; j++) { DoublePoint doublePoint = pointList.get(j); if (j == 0) { path.moveTo((float) doublePoint.getX(), (float) doublePoint.getY()); } else { path.lineTo((float) doublePoint.getX(), (float) doublePoint.getY()); } } path.close(); canvas.drawPath(path, mPaint); } ```
在此运行:
红色的不规则七边形呢?别着急我们还没对其进行初始化呢,我们在MainActivity中创建数据源,使用随机double方法,然后对其动态赋值:
List<Double> list = new ArrayList<>();
for (int i = 0; i < 7; i++) {
list.add(Math.random());
}
mPowerInfoView2.setDataPercents(list);
再次运行(随机了一个相对好看相对规则的哈哈):
至此,我们自定义View(英雄联盟七星图)就完成,如果什么不对或者更好的方法理解可以留言给我谢谢!下面贴出整个代码:
public class PowerInfoView extends View {
private int viewWidth;
private int viewHeight;
private int heptagonRadio;
private Paint mPaint;
private TextPaint mTextPaint;
private final int heptagonSideNum = 7;
private final int heptagonNum = 4;
private List<Polygon> mPolygons;
private Polygon dataPolygon;
private double averageAngle;
private int[] powerInfoViewInnerColors = {
R.color.powerInfoViewInnerColor1,
R.color.powerInfoViewInnerColor2,
R.color.powerInfoViewInnerColor3,
R.color.powerInfoViewInnerColor4
};
private int[] powerInfoViewLineColors = {
R.color.powerInfoViewLineColor1,
R.color.powerInfoViewLineColor2,
R.color.powerInfoViewLineColor3,
R.color.powerInfoViewLineColor4
};
private List<Double> dataPercents;
private final String[] powerStr = {"击杀", "生存", "助攻", "物理", "魔法", "防御", "金钱"};
private int textWidth, textHeight;
private int deltaX, deltaY;
public PowerInfoView(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs) {
super(context, attrs);
this.init(context, attrs);
}
public PowerInfoView(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.init(context, attrs);
}
private void init(Context context, @Nullable @android.support.annotation.Nullable AttributeSet attrs) {
this.mPaint = new Paint();
this.mPaint.setAntiAlias(true);
this.mPaint.setColor(Color.BLUE);
this.mTextPaint = new TextPaint();
this.mTextPaint.setTextSize(50);
this.mTextPaint.setAntiAlias(true);
this.mPolygons = new ArrayList<>();
this.mPolygons.add(new Polygon(heptagonSideNum));
this.mPolygons.add(new Polygon(heptagonSideNum));
this.mPolygons.add(new Polygon(heptagonSideNum));
this.mPolygons.add(new Polygon(heptagonSideNum));
this.dataPolygon = new Polygon(heptagonSideNum);
this.averageAngle = 2 * Math.PI / heptagonSideNum;
}
@Override
protected void onDraw(Canvas canvas) {
Rect rect = new Rect();
this.mTextPaint.getTextBounds(powerStr[0], 0, powerStr[0].length(), rect);
this.textHeight = rect.height();
this.textWidth = rect.width();
this.deltaX = getPaddingLeft() + textWidth * 5 / 4;
this.deltaY = getPaddingTop() + textHeight + textWidth / 4;
this.heptagonRadio = Math.min(viewWidth - getPaddingLeft() - getPaddingRight() - textWidth * 5 / 2, viewHeight - getPaddingTop() - getPaddingBottom() - textHeight * 2 + textWidth / 2) >> 1;
//completeHeptagonPoint
completeHeptagonPoint();
//绘制七边形背景
drawHeptagonBackground(canvas);
//绘制七边形Line
drawHeptagonLine(canvas);
drawHeptagonPowerStr(canvas);
//绘制数据显示的七边形
if (dataPercents != null) {
drawPercentHeptagon(canvas);
}
}
/**
* 绘制powerStr
*
* @param canvas
*/
private void drawHeptagonPowerStr(Canvas canvas) {
List<DoublePoint> pointList = mPolygons.get(0).getPointList();
DoublePoint doublePoint = pointList.get(0);
canvas.drawText(powerStr[0], (float) (doublePoint.getX() - textWidth / 2), (float) (doublePoint.getY() - textWidth / 4), mTextPaint);
doublePoint = pointList.get(1);
canvas.drawText(powerStr[1], (float) (doublePoint.getX() + textWidth / 4), (float) (doublePoint.getY() - mTextPaint.descent()), mTextPaint);
doublePoint = pointList.get(2);
canvas.drawText(powerStr[2], (float) (doublePoint.getX() + textWidth / 4), (float) (doublePoint.getY() + textHeight / 2), mTextPaint);
doublePoint = pointList.get(3);
canvas.drawText(powerStr[3], (float) (doublePoint.getX() + textWidth / 4), (float) (doublePoint.getY() - mTextPaint.ascent()), mTextPaint);
doublePoint = pointList.get(4);
canvas.drawText(powerStr[4], (float) (doublePoint.getX() - textWidth * 5 / 4), (float) (doublePoint.getY() - mTextPaint.ascent()), mTextPaint);
doublePoint = pointList.get(5);
canvas.drawText(powerStr[5], (float) (doublePoint.getX() - textWidth * 5 / 4), (float) (doublePoint.getY() + textHeight / 2), mTextPaint);
doublePoint = pointList.get(6);
canvas.drawText(powerStr[6], (float) (doublePoint.getX() - textWidth * 5 / 4), (float) (doublePoint.getY() - mTextPaint.descent()), mTextPaint);
}
/**
* 绘制对应数据形成的七边形
*
* @param canvas
*/
private void drawPercentHeptagon(Canvas canvas) {
Path path = new Path();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
List<DoublePoint> pointList = dataPolygon.getPointList();
for (int j = 0; j < heptagonSideNum; j++) {
DoublePoint doublePoint = pointList.get(j);
if (j == 0) {
path.moveTo((float) doublePoint.getX(), (float) doublePoint.getY());
} else {
path.lineTo((float) doublePoint.getX(), (float) doublePoint.getY());
}
}
path.close();
canvas.drawPath(path, mPaint);
}
/**
* 计算对应七边形的定点坐标
*/
private void completeHeptagonPoint() {
double currentRadio;
double currentAngle;
for (int i = 0; i < heptagonNum; i++) {
Polygon polygon = mPolygons.get(i);
polygon.clearPoint();
currentRadio = (heptagonNum - i) * 1.0d / heptagonNum * heptagonRadio;
for (int j = 0; j < heptagonSideNum; j++) {
currentAngle = -Math.PI / 2 + j * averageAngle;
polygon.addPoint(
new DoublePoint(
Math.cos(currentAngle) * currentRadio + heptagonRadio + deltaX,
Math.sin(currentAngle) * currentRadio + heptagonRadio + deltaY)
);
}
}
if (dataPercents != null) {
dataPolygon.clearPoint();
for (int j = 0; j < heptagonSideNum; j++) {
currentRadio = dataPercents.get(j) * heptagonRadio;
currentAngle = -Math.PI / 2 + j * averageAngle;
dataPolygon.addPoint(
new DoublePoint(
Math.cos(currentAngle) * currentRadio + heptagonRadio + deltaX,
Math.sin(currentAngle) * currentRadio + heptagonRadio + deltaY));
}
}
}
/**
* 绘制七边形Line
*
* @param canvas
*/
private void drawHeptagonLine(Canvas canvas) {
float ox = heptagonRadio + deltaX;
float oy = heptagonRadio + deltaY;
for (int i = 0; i < heptagonNum; i++) {
mPaint.setColor(ContextCompat.getColor(getContext(), powerInfoViewLineColors[i]));
List<DoublePoint> pointList = mPolygons.get(i).getPointList();
for (int j = 0; j < heptagonSideNum; j++) {
DoublePoint doublePoint = pointList.get(j);
canvas.drawLine(ox, oy, (float) doublePoint.getX(), (float) doublePoint.getY(), mPaint);
}
}
}
/**
* 绘制七边形背景
*
* @param canvas
*/
private void drawHeptagonBackground(Canvas canvas) {
Path path = new Path();
for (int i = 0; i < heptagonNum; i++) {
mPaint.setColor(ContextCompat.getColor(getContext(), powerInfoViewInnerColors[i]));
List<DoublePoint> pointList = mPolygons.get(i).getPointList();
for (int j = 0; j < heptagonSideNum; j++) {
DoublePoint doublePoint = pointList.get(j);
if (j == 0) {
path.moveTo((float) doublePoint.getX(), (float) doublePoint.getY());
} else {
path.lineTo((float) doublePoint.getX(), (float) doublePoint.getY());
}
}
path.close();
canvas.drawPath(path, mPaint);
path.reset();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMeasureMode == MeasureSpec.EXACTLY) {
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
} else {
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
}
if (heightMeasureMode == MeasureSpec.EXACTLY) {
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
} else {
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
}
setMeasuredDimension(viewWidth, viewHeight);
}
public void setDataPercents(List<Double> dataPercents) {
this.dataPercents = dataPercents;
invalidate();
}
}