拿到美工效果图,咱们程序员就得画得一模一样。 为了不被老板喷,只能多练啊。

听说你觉得前面几篇都so easy,那今天就带你做个相对比较复杂的。

转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50468674

注意:每一篇博客都是建立在之前博客的基础知识上的,如果你刚接触自定义view。可以来说说自定义view简单学习的方式这里看我以前的文章。记录了我学习自定义view的过程,而且前几篇博客或多或少犯了一些错误(重复绘制,onDraw里new对象等等)。这里我并不想改正博文中的错误,因为些错误是大家经常会犯的,后来的博客都有指出这些错误,以及不再犯,这是一个学习的过程。所以我想把错误的经历记录下来。等成为高手
回头看看当年的自己是多么菜。。也会有成就感。。

今天的效果图如下(左边是ui图 右边是实现图):

自我感觉总体效果还不错,至少大概画得一样了。上一个动态图:

其实这个效果实现起来也不是很难,就是计算坐标,弧度之类的可能会比较麻烦,这里分享写这个其中一张手稿,请无视掉很丑的字,其实做自定义view 还是要在纸上多画。所以希望大家也能这么画画,思路会很顺。

好的了,废话不多说,快开始。

首先自定义属性  构造函数,测量什么的 你肯定已经很熟练 直接贴代码了,注释写的很清楚

public class PanelView extends View {
private int mWidth;
private int mHeight; private int mPercent; //刻度宽度
private float mTikeWidth; //第二个弧的宽度
private int mScendArcWidth; //最小圆的半径
private int mMinCircleRadius; //文字矩形的宽
private int mRectWidth; //文字矩形的高
private int mRectHeight; //文字内容
private String mText = ""; //文字的大小
private int mTextSize; //设置文字颜色
private int mTextColor;
private int mArcColor; //小圆和指针颜色
private int mMinCircleColor; //刻度的个数
private int mTikeCount; private Context mContext; public PanelView(Context context) {
this(context, null);
} public PanelView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public PanelView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.PanelView,defStyleAttr,0);
mArcColor = a.getColor(R.styleable.PanelView_arcColor, Color.parseColor("#5FB1ED"));
mMinCircleColor = a.getColor(R.styleable.PanelView_pointerColor,Color.parseColor("#C9DEEE"));
mTikeCount = a.getInt(R.styleable.PanelView_tikeCount,12);
mTextSize = a.getDimensionPixelSize(PxUtils.spToPx(R.styleable.PanelView_android_textSize,mContext),24);
mText = a.getString(R.styleable.PanelView_android_text);
mScendArcWidth = 50;
} @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);
if (widthMode == MeasureSpec.EXACTLY) {
mWidth = widthSize;
}else {
mWidth = PxUtils.dpToPx(200,mContext);
} if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
}else {
mHeight = PxUtils.dpToPx(200,mContext);
}
Log.e("wing",mWidth+"");
setMeasuredDimension(mWidth, mHeight);
}

自定义属性attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="PanelView">
<attr name="arcColor" format="color"/>
<attr name="arcWidth" format="dimension"/>
<attr name="android:text"/>
<attr name="tikeCount" format="integer"/>
<attr name="pointerColor" format="color"/>
<attr name="android:textSize"/>
</declare-styleable>
</resources>

之后来重头戏,也就是绘制。就像画画一样,再复杂的view也是一笔一笔画出来的。所以我们把这个view分解。

大概分解成如下:1.最外面的弧   2.里面的粗弧   3.中间小圆   4.最小的圆  5.刻度   6.指针  7.矩形  8.文字

相信让你分开画一定难不倒你。那组合在一起 就是这个view啦。下面开始我们的ondraw()

按照这个分解来:

1.绘制最外面的弧   这里需要注意的一点是,如果想让这个圆在view里 记得减去画笔宽度的一半  因为半径是从圆心到画笔宽度的中间算的,所以这里画弧的矩形是  new RectF(strokeWidth, strokeWidth, mWidth - strokeWidth, mHeight - strokeWidth)

     Paint p = new Paint();
int strokeWidth = 3;
p.setStrokeWidth(strokeWidth);
p.setAntiAlias(true);
p.setStyle(Paint.Style.STROKE);
p.setColor(mArcColor);
//最外面线条
canvas.drawArc(new RectF(strokeWidth, strokeWidth, mWidth - strokeWidth, mHeight - strokeWidth), 145, 250, false, p);

画出来是这样的效果。

2.绘制里面的粗弧,这里比较麻烦的就是需要分为四段,看图:

因为大圆和里面粗弧的长短不一致,这里使用百分比来计算 所以会造成指针偏差,那么这里把 1、2两个部分固定来画,然后是3 充满的部分,用百分比来计算需要画多少度,最后是4 空白的部分。

首先把粗弧的矩形画出来,这里固定了比大弧半径少50(这里其实可以改进,你可以改成动态的让他更灵活),然后计算出百分比。

RectF secondRectF = new RectF(strokeWidth + 50, strokeWidth + 50, mWidth - strokeWidth - 50, mHeight - strokeWidth - 50);
float secondRectWidth = mWidth - strokeWidth - 50 - (strokeWidth + 50);
float secondRectHeight = mHeight - strokeWidth - 50 - (strokeWidth + 50);
float percent = mPercent / 100f;

接下来绘制1弧,先算出fill充满部分的度数,因为是突出的,所以如果百分比为0,突出左端为白色 如果不为零,则和充满颜色统一。

        //充满的圆弧的度数    -5是大小弧的偏差
float fill = 250 * percent ; //空的圆弧的度数
float empty = 250 - fill;
// Log.e("wing", fill + ""); if(percent==0){
p.setColor(Color.WHITE);
}
//画粗弧突出部分左端 canvas.drawArc(secondRectF,135,11,false,p);

然后绘制2弧 也就是fill充满的弧,

canvas.drawArc(secondRectF, 145, fill, false, p);

接下来是3弧,也就是empty未充满的弧,是白色的

 p.setColor(Color.WHITE);
//画弧胡的未充满部分
canvas.drawArc(secondRectF, 145 + fill, empty, false, p);

最后,画出右边突出的4弧, 如果百分比为100 那么和充满的颜色一致,否则为白色

 //画粗弧突出部分右端
if(percent == 1){
p.setColor(mArcColor);
}
canvas.drawArc(secondRectF,144+fill+empty,10,false,p);

这样粗弧也就画完了 来看看效果,就画了两条弧线(实际是5条),就成型了。

3.中间的小圆外圈,他的圆心不用多说 是整个view的中心

        p.setColor(mArcColor);

        //绘制小圆外圈
p.setStrokeWidth(3);
canvas.drawCircle(mWidth / 2, mHeight / 2, 30, p);

4.绘制内圆,圆心一样的,半径和画笔粗度改变一下

        //绘制小圆内圈

        p.setColor(mMinCircleColor);
p.setStrokeWidth(8);
mMinCircleRadius = 15;
canvas.drawCircle(mWidth / 2, mHeight / 2, mMinCircleRadius, p);

5.刻度  刻度处理起来可能比较麻烦,用三角函数算坐标啊 循环画出来。。 这里提供一种比较简单的方法:旋转画布。

首先引入一个概念,什么叫旋转画布呢,就是把你的画布旋转。。经过测试,旋转以后,整个坐标轴都会对应旋转,一张图举例说明下。

大概就是这个意思,画布旋转之后 坐标系也就旋转了,但是原来的图像还在,所以说你比如这个点 x,y旋转前在这个位置, 那么旋转后就是另外一个位置了,但是他们的坐标是相同的。 所以刻度也可以考这种方法画。我们只要画出最顶端的刻度 然后旋转就可以了。

绘制第一段刻度, 然后总共是250的弧度  计算出每个刻度的度数     用250除以刻度数mTikeCount,就是每次旋转的度数。接下来把画布逐步旋转,按照原坐标绘制,即可绘制出右半部分刻度。  注意:为了让之后的绘制正常,务必把画布转回原来的位置

        //绘制刻度!

        p.setColor(mArcColor);
//绘制第一条最上面的刻度
mTikeWidth = 20;
p.setStrokeWidth(3); canvas.drawLine(mWidth / 2, 0, mWidth / 2, mTikeWidth, p);
//旋转的角度
float rAngle = 250f / mTikeCount;
//通过旋转画布 绘制右面的刻度
for (int i = 0; i < mTikeCount / 2; i++) {
canvas.rotate(rAngle, mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, 0, mWidth / 2, mTikeWidth, p);
} //现在需要将将画布旋转回来
canvas.rotate(-rAngle * mTikeCount / 2, mWidth / 2, mHeight / 2);

左半部分同理,需要改变的度数为负 就好了

        //通过旋转画布 绘制左面的刻度
for (int i = 0; i < mTikeCount / 2; i++) {
canvas.rotate(-rAngle, mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, 0, mWidth / 2, mTikeWidth, p);
} //现在需要将将画布旋转回来
canvas.rotate(rAngle * mTikeCount / 2, mWidth / 2, mHeight / 2);

6.指针   指针的绘制和刻度相似,先算出来百分比所占的度数 然后根据 是否大于50%来旋转画布。

指针的起终点是 总view高度的一半 粗弧矩形的一半 加上小圆,前面坐标讲解了那么,这个也一样,自己拿起笔算一算。

注意这里画布旋转我通过计算得出一个公式 250 * percent - 250/2。

如果小于50% 则为负   如果大于50%则为正,然后进行旋转。

切忌最后一定要将画布转回来。

        //绘制指针

        p.setColor(mMinCircleColor);
p.setStrokeWidth(4); //按照百分比绘制刻度
canvas.rotate(( 250 * percent - 250/2), mWidth / 2, mHeight / 2); canvas.drawLine(mWidth / 2, (mHeight / 2 - secondRectHeight / 2) + mScendArcWidth / 2 + 2, mWidth / 2, mHeight / 2 - mMinCircleRadius, p); //将画布旋转回来
canvas.rotate(-( 250 * percent - 250/2), mWidth / 2, mHeight / 2);

接下来就是画矩形和文字。没什么好说的了,坐标也是X周围mWidth/2   y轴自己根据圆心微调一个距离

    //绘制矩形
p.setStyle(Paint.Style.FILL);
p.setColor(mArcColor);
mRectWidth = 60;
mRectHeight = 25; //文字矩形的最底部坐标
float rectBottomY = mHeight/2 + secondRectHeight/3+mRectHeight;
canvas.drawRect(mWidth/2-mRectWidth/2,mHeight/2 + secondRectHeight/3,mWidth/2+mRectWidth/2,rectBottomY,p); p.setTextSize(mTextSize);
mTextColor = Color.WHITE;
p.setColor(mTextColor);
float txtLength = p.measureText(mText);
canvas.drawText(mText,(mWidth-txtLength)/2,rectBottomY + 40,p); super.onDraw(canvas);

这样完成了整个view的绘制。



下面要做的就是为了方便使用者,提供一些设置属性的方法。

 /**
* 设置百分比
* @param percent
*/
public void setPercent(int percent) {
mPercent = percent;
invalidate();
} /**
* 设置文字
* @param text
*/
public void setText(String text){
mText = text;
invalidate();
} /**
* 设置圆弧颜色
* @param color
*/ public void setArcColor(int color){
mArcColor = color; invalidate();
} /**
* 设置指针颜色
* @param color
*/
public void setPointerColor(int color){
mMinCircleColor = color; invalidate();
} /**
* 设置文字大小
* @param size
*/
public void setTextSize(int size){
mTextSize = size; invalidate();
} /**
* 设置粗弧的宽度
* @param width
*/
public void setArcWidth(int width){
mScendArcWidth = width; invalidate();
}

大功告成!!!一个看似复杂的view  经过我们一步一步绘制遍完成了。

其实技术的养成也是这样,只要一步一步脚踏实地的去练习,我相信总有一天我能成为大神。

本项目地址 :PanelView   求关注  求评论  求star!!!!!!

手把手带你画一个 时尚仪表盘 Android 自定义View的更多相关文章

  1. 手把手带你画一个动态错误提示 Android自定义view

    嗯..再差1篇就可以获得持之以恒徽章了,今天带大家画一个比较简单的view. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/504771 ...

  2. 手把手带你画一个 时尚仪表盘 Android 自己定义View

    拿到美工效果图.咱们程序猿就得画得一模一样. 为了不被老板喷,仅仅能多练啊. 听说你认为前面几篇都so easy,那今天就带你做个相对照较复杂的. 转载请注明出处:http://blog.csdn.n ...

  3. 手把手带你画一个漂亮蜂窝view Android自定义view

    上一篇做了一个水波纹view  不知道大家有没有动手试试呢点击打开链接 这个效果做起来好像没什么意义,如果不加监听回调 图片就能直接替代.写这篇博客的目的是锻炼一下思维能力,以更好的面多各种自定义vi ...

  4. 简单说说Android自定义view学习推荐的方式

    这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧.  以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...

  5. 手把手带你做一个超炫酷loading成功动画view Android自定义view

    写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...

  6. Android自定义View 画弧形,文字,并增加动画效果

    一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类   B ...

  7. 手把手教你画一个 逼格满满圆形水波纹loadingview Android

    才没有完结呢o( ̄︶ ̄)n .大家好,这里是番外篇. 拜读了爱哥的博客,又学到不少东西.爱哥曾经说过: 要站在巨人的丁丁上. 那么今天,我们就站在爱哥的丁丁上来学习制作一款自定义view(开个玩笑,爱 ...

  8. 我的Android进阶之旅------>Android自定义View实现带数字的进度条(NumberProgressBar)

    今天在Github上面看到一个来自于 daimajia所写的关于Android自定义View实现带数字的进度条(NumberProgressBar)的精彩案例,在这里分享给大家一起来学习学习!同时感谢 ...

  9. [原] Android 自定义View步骤

    例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...

随机推荐

  1. Android Design Support Library使用详解——Snackbar

    Google在2015 I/O大会上,给我们带来了更加详细的Material Design规范,同时也引入了Android Design Support Library,为我们提供了基于Materia ...

  2. RDO Stack: Install newton in the dashboard can't create images

    Issue: When you want to create an image in RDO stack newton version, you may encounter following err ...

  3. 初识Spring Boot框架(二)之DIY一个Spring Boot的自动配置

    在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个Spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单 ...

  4. Scheme r5rs letrec的用法

    说明,这是r5rs的用法. (letrec ((<variable> <init>) ...) <body>) 假设((<variable> <i ...

  5. 排查Full GC

    我们的Java应用因频繁FULL GC导致性能降低很多,经过多人的定位也没有结论,于是我自主请命,经过一天的研究终于搞定了,现把经验与大家共享,相关的gc日志如下: 4.758: [Full GC [ ...

  6. Dubbo框架应用之(四)--Dubbo基于Zookeeper实现分布式实例

    上三篇文章主要是解决了概念性的补充和学习,充分结合实战来深入理解 入门实例解析 第一:provider-提供服务和相应的接口 创建DemoService接口 package com.unj.dubbo ...

  7. 在Ubuntu12.04上安装图形化配置与window共享的samba服务器

    1.安装samba图形化配置界面 sudo apt-get install system-config-samba 2.启动图形化配置界面 3.添加用户,最好是要用adduser命令去添加 具体配置可 ...

  8. Java安全管理器——SecurityManager

    总的来说,Java安全应该包括两方面的内容,一是Java平台(即是Java运行环境)的安全性:二是Java语言开发的应用程序的安全性.由于我们不是Java本身语言的制定开发者,所以第一个安全性不需要我 ...

  9. [linux RedHat]windows下使用putty远程连接linux 下载JDK和tomcat

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/43154543 本文作者:sushengmiyan ------------------ ...

  10. 移动开发测试工具——Bugtags的集成

    移动开发测试工具--Bugtags 官网:https://bugtags.com/ 注册开发者账号 注册账号并激活邮箱,都会就不多做介绍了. 创建应用 创建完账号以后会提示添加应用,点击添加 添加应用 ...