自定义View - 简单的成绩条
2016-10-19 15:36
204 查看
效果图
处理
根据进度条终点的X坐标,计算对应于第几个刻度里程碑
要加上
在代码使用属性动画
欢迎指教, Demo下载请戳
ScoreView的要求
0-60,
60-70,
70-80,
80-90,
90-120这几段对应不同颜色
处理
padding,
<0或>120的特殊值,
match_parent 和 wrap_content
具体步骤
1.在attrs.xml文件中定义属性
<attr name="score" format="integer" /> <attr name="scoreColor" format="color" /> <attr name="baseLineColor" format="color" /> <declare-styleable name="ScoreView"> <attr name="score" /> <attr name="scoreColor" /> <attr name="baseLineColor" /> </declare-styleable>
2.在自定义View中获取这些属性
public ScoreView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray ta = context.getTheme(). obtainStyledAttributes(attrs, R.styleable.ScoreView, defStyleAttr, 0); int count = ta.getIndexCount(); for (int i = 0; i < count; i++) { int attr = ta.getIndex(i); switch (attr) { case R.styleable.ScoreView_baseLineColor: baselineColor = ta.getColor(attr, Color.GRAY); break; case R.styleable.ScoreView_scoreColor: scoreColor = ta.getColor(attr, Color.RED); break; case R.styleable.ScoreView_score: //应该加上 StringToInteger 的检测 mScore = Integer.parseInt(ta.getString(attr)); break; } } ta.recycle(); mScore = Math.min(mScore, 120); mScore = Math.max(0, mScore); mScoreFraction = (float) (mScore / 10.0); paint = new Paint(); }
3.重写onMeasure
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int mWidth = MeasureSpec.getSize(widthMeasureSpec); int mHeight = MeasureSpec.getSize(heightMeasureSpec); int mWidthMode = MeasureSpec.getMode(widthMeasureSpec); int mHeightMode = MeasureSpec.getMode(heightMeasureSpec); int lineWidth = 0;//基准线的长度 Paint paint = new Paint(); Rect boundScore = new Rect(); paint.setTextSize(30); paint.getTextBounds("120", 0, "120".length(), boundScore); //所得分数对应的Rect Rect boundDial = new Rect(); paint.setTextSize(20); paint.getTextBounds("120", 0, "120".length(), boundDial);//分数刻度对应的Rect if (mWidthMode == MeasureSpec.EXACTLY) { width = mWidth; lineWidth = width - boundScore.width() - getPaddingLeft() - getPaddingRight(); } else { width = DensityUtils.getScreenWidth(ScoreApplication.getScoreApplicationContext()) / 2; lineWidth = width - (boundScore.width()) - getPaddingLeft() - getPaddingRight(); } if (mHeightMode == MeasureSpec.EXACTLY) { //该情况不进行处理,即如果指定具体高度,不可过小 height = mHeight; } else { int baseHeight = DensityUtils.getScreenHeight(ScoreApplication.getScoreApplicationContext()) / 5; int minHeight = Math.max(boundScore.height(), 2 * stepY) + 4 * stepY; height = Math.min(baseHeight, minHeight); height += (getPaddingTop() + getPaddingBottom()); } baseLineWidth = (int) (lineWidth * 0.9); baseLineStart = (int) (lineWidth * 0.05); //计算出 刻度线各里程碑对应的x坐标,即DialStonesX[i]的值 for (int i = 0; i < DialStones.length; i++) { DialStonesX[i] = (int) ((float) (DialStones[i] / 120.0) * baseLineWidth + baseLineStart); } setMeasuredDimension(width, height); }
4.重写onDraw
@Override protected void onDraw(Canvas canvas) { paint.setStrokeWidth(mDialWidth);//paint线条宽度 paint.setColor(baselineColor); paint.setTextSize(20); //绘制水平基线 canvas.drawLine(baseLineStart, height / 2, baseLineWidth + baseLineStart, height / 2, paint); int baseX = baseLineStart + baseLineWidth / 2; int baseY = height / 2; int stepX = baseLineWidth / 12; //绘制第一个刻度 0 canvas.drawLine(baseLineStart + mDialWidth / 2, baseY, baseLineStart + mDialWidth / 2, baseY + stepY, paint); canvas.drawText("0", baseLineStart, baseY + stepY * 3, paint); //绘制刻度 60 70 80 90 100 120 for (int i = 0; i < 7; i++) { if (i == 5) continue; canvas.drawLine(baseX + i * stepX + mDialWidth / 2, baseY, baseX + i * stepX + mDialWidth / 2, baseY + stepY, paint); canvas.drawText(DialNumbers[i] + "", baseX + i * stepX - stepY, baseY + 3 * stepY, paint); } //绘制进度 int destX = (int) (baseLineStart + stepX * mScoreFraction + mDialWidth); int indexBetweenDialStonesX = getIndexInDialStonesX(destX); //如果成绩<=60 if (indexBetweenDialStonesX == 0) { paint.setColor(getResources().getColor(progressRes[0])); canvas.drawRect(baseLineStart, baseY - stepY * 3, destX, baseY - stepY, paint); } else { //除去最后一部分,之前的部分可以通过 刻度里程碑的X坐标确定起止X位置 for (int i = 0; i < indexBetweenDialStonesX; i++) { paint.setColor(getResources().getColor(progressRes[i])); if (i == 0) { canvas.drawRect(baseLineStart, baseY - stepY * 3, DialStonesX[i], baseY - stepY, paint); } else { canvas.drawRect(DialStonesX[i - 1], baseY - stepY * 3, DialStonesX[i], baseY - stepY, paint); } } //绘制最后一段,起始点X坐标为对应刻度里程碑的X坐标,终止点坐标为destX paint.setColor(getResources().getColor(progressRes[indexBetweenDialStonesX])); canvas.drawRect(DialStonesX[indexBetweenDialStonesX - 1], baseY - stepY * 3, destX, baseY - stepY, paint); } //绘制分数 paint.setColor(scoreColor); paint.setTextSize(30); paint.setTypeface(Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD)); canvas.drawText("" + mScore, (int) (baseLineStart + stepX * mScoreFraction + stepY), (int) (baseY - stepY * 1.3), paint); super.onDraw(canvas); }
根据进度条终点的X坐标,计算对应于第几个刻度里程碑
private int getIndexInDialStonesX(int dest) { for (int i = DialStonesX.length - 1; i >= 0; i--) { if (dest > DialStonesX[i] + mDialWidth) return i + 1; } return 0; }
5.支持属性动画
public void setScore(int score) { mScore = Math.min(score,120); mScore = Math.max(mScore,0); mScoreFraction = (float) (mScore / 10.0); invalidate(); }
6.引用ScoreView并调用属性动画
<org.issme.gh.scoreviewdemo.View.ScoreView android:id="@+id/acScore_scrollView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" hyzhang:baseLineColor="@color/baseLine" hyzhang:score="98" hyzhang:scoreColor="@color/score" />
要加上
xmlns:hyzhang="http://schemas.android.com/apk/res-auto"
在代码使用属性动画
public void setScore(View view) { int random = new Random().nextInt(61) + 60; ObjectAnimator.ofInt(scoreView, "Score", random).setDuration(random * 10).start(); }
欢迎指教, Demo下载请戳
相关文章推荐
- Android自定义简单的View
- 创建一个简单的表视图&自定义UITableView的表单元格
- AutoCompleteTextView 简单用法 实现自定义list adapter
- 简单自定义View
- 简单自定义View圆形呼吸效果
- Asp.net MVC 自定义ViewEngine的简单实现
- 自定义view的简单使用
- 用自定义view实现的简单画图板
- android自定义View之(二)------简单进度条显示样例篇
- 猫猫学iOS(四十四)之网易彩票自定义图片在右边的Button_弹出view_ios6,7简单适配
- 自定义的带tab的可左右滑动的viewpager之一 简单实现
- 自定义一个view,并实现最简单的手势识别功能(下)
- 自定义一个view,并实现最简单的手势识别功能(上)
- 自定义view 开始 简单的写个TextView
- 简单代码使用nib自定义的view
- Android自定义简单的View
- Android自定义简单的View
- 【Android自定义View实战】之自定义超简单SearchView搜索框
- android基础学习之自定义view的简单原理
- 猫猫学iOS(四十四)之网易彩票自定义图片在右边的Button_弹出view_ios6,7简单适配