拿到美工效果图。咱们程序猿就得画得一模一样。

为了不被老板喷,仅仅能多练啊。

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

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

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

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

自我感觉整体效果还不错。至少大概画得一样了。

上一个动态图:

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

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

首先自己定义属性  构造函数,測量什么的 你肯定已经非常熟练 直接贴代码了,凝视写的非常清楚

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);

画出来是这种效果。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

由于大圆和里面粗弧的长短不一致,这里使用百分比来计算 所以会造成指针偏差,那么这里把 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

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

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

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

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

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

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

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

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

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

  6. Android 自己定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...

  7. Android 自己定义View须要重写ondraw()等方法

    Android  自己定义View须要重写ondraw()等方法.这篇博客给大家说说自己定义View的写法,须要我们继承View,然后重写一些 方法,方法多多,看你须要什么方法 首先写一个自己定义的V ...

  8. 【Android自己定义View实战】之自己定义超简单SearchView搜索框

    [Android自己定义View实战]之自己定义超简单SearchView搜索框 这篇文章是对之前文章的翻新,至于为什么我要又一次改动这篇文章?原因例如以下 1.有人举报我抄袭,原文链接:http:/ ...

  9. Android 自己定义View学习(2)

    上一篇学习了基本使用方法,今天学一下略微复杂一点的.先看一下效果图 为了完毕上面的效果还是要用到上一期开头的四步 1,属性应该要有颜色,要有速度 <?xml version="1.0& ...

随机推荐

  1. ZH奶酪:PHP抓取网页方法总结

    From:http://www.jb51.net/article/24343.htm 在做一些天气预报或者RSS订阅的程序时,往往需要抓取非本地文件,一般情况下都是利用php模拟浏览器的访问,通过ht ...

  2. https调试

    我们知道https通信在开始时会发送一个METHOD为CONNECT的请求,让服务器将证书以及相关的信息返回给浏览器,在没有得到这些信息之前,浏览器是不会信任服务器发来的任何数据的.So现在我们要让F ...

  3. hibernate的入门crud

    package com.test; import com.demo.User; import org.hibernate.HibernateException; import org.hibernat ...

  4. Code Review学习笔记

    一:Code Review的必要性 代码审查,可以帮助他人发现不足,也可以促进自己培养良好的编程习惯. 自我代码审查,可以在编码完成之后,对自己的代码进行整理,发现“味道不好”的代码,作进一步的调整. ...

  5. [转发]jquery获取当前页面的URL信息

    以前在做网站的时候,经常会遇到当前页的分类高亮显示,以便让用户了解当前处于哪个页面.之前一直是在每个不同页面写方法.工程量大,也不便于修改.一直在想有什么简便的方法实现.后来在网上查到可以用获取当前U ...

  6. cocos2d-js Shader系列3:多重纹理 multiple textures multiple samplers

    上一篇,我们学习了怎么便捷的控制sprite的颜色,而这个都是默认一个texture的,如果要实现类似mask的效果,或者更个性化的多纹理效果,怎么实现呢? 这就是这一节需要介绍的内容. 例如上图的效 ...

  7. 洛谷 P2335 [SDOI2005]位图

    OJ检测链接:https://www.luogu.org/problem/show?pid=2335 题目描述 现在我们给出一个n*m的单色位图,且该图中至少含有一个白色的像素.我们用(i, j)来代 ...

  8. 输出前 k 大的数

    总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB 描述 给定一个数组,统计前k大的数并且把这k个数从大到小输出. 输入 第一行包含一个整数n,表示数组的大小 ...

  9. Spring-security-Oauth2.0

    上周,我想开发OAuth 2.0的一个实例.我检查了Spring-security-Oauth2.0的样例,OAuth 2提供商sparklr2和OAuth 2客户端TONR .我探索在互联网上了一下 ...

  10. los中预览文件

    #import <UIKit/UIKit.h> #import <QuickLook/QuickLook.h> @interface ViewController : UIVi ...