自定义 View 之小试牛刀

3,685 阅读2分钟

自定义View对于Android程序猿来说都应该了解的,或者说一定要掌握。虽然Google提供的控件可以满足日常开发需求,但是总有些奇葩需求肯定是满足不了的,所以对于自定义View的开发,就必不可少了。

关于自定义View的基础学习推荐GcsSloop自定义View系列

首先看下面效果图

check

实现上图的效果参考这篇文章

再来这个效果图

zombie

上面效果图是根据第一个Demo的扩展,具体源码会在文章结尾提供链接

最后一个效果图

sport

这个自定义View是模仿QQ运动的那个界面

下面具体对模仿QQ运动这个View实现步骤

1.初始化所需参数

//数据初始化
private void init(Context context){
    //圆弧所需的矩形
    mRect = new RectF();
    //其他字的画笔
    textGrayPaint = new Paint();
    textGrayPaint.setAntiAlias(true);
    textGrayPaint.setStyle(Paint.Style.FILL);
    textGrayPaint.setColor(0xFFC6C1C3);
    textGrayPaint.setTextAlign(Paint.Align.CENTER);
    //排名的画笔
    textSmallPaint = new Paint();
    textSmallPaint.setAntiAlias(true);
    textSmallPaint.setStyle(Paint.Style.FILL);
    textSmallPaint.setColor(textColor);
    textSmallPaint.setTextAlign(Paint.Align.CENTER);
    //总步数的画笔
    textBigPaint = new Paint();
    textBigPaint.setAntiAlias(true);
    textBigPaint.setStyle(Paint.Style.FILL);
    textBigPaint.setColor(textColor);
    textBigPaint.setTextAlign(Paint.Align.CENTER);
    //外圆弧的画笔
    outSideLinePaint = new Paint();
    outSideLinePaint.setAntiAlias(true);
    outSideLinePaint.setStyle(Paint.Style.STROKE);
    outSideLinePaint.setColor(outCircleColor);
    outSideLinePaint.setStrokeCap(Paint.Cap.ROUND);
    //内圆弧的画笔
    inSideLinePaint = new Paint();
    inSideLinePaint.setAntiAlias(true);
    inSideLinePaint.setStyle(Paint.Style.STROKE);
    inSideLinePaint.setColor(inCircleColor);
    inSideLinePaint.setStrokeCap(Paint.Cap.ROUND);
    //竖条画笔
    barPaint = new Paint();
    barPaint.setAntiAlias(true);
    barPaint.setStyle(Paint.Style.FILL);
    barPaint.setColor(outCircleColor);
    barPaint.setStrokeCap(Paint.Cap.ROUND);
    //背景画笔
    backgroundPaint = new Paint();
    barPaint.setAntiAlias(true);
    barPaint.setStyle(Paint.Style.FILL);
    //虚线画笔
    dashLinePaint = new Paint();
    dashLinePaint.setAntiAlias(true);
    dashLinePaint.setColor(Color.parseColor("#C1C1C1"));
    dashLinePaint.setStyle(Paint.Style.STROKE);
    dashLinePaint.setPathEffect(new DashPathEffect(new float[]{8, 4}, 0));//画虚线
    //头像
    headBitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.icon_head);
}

2.测量View的宽高

//测量高度
private int getHeightMeasure(int measureSpec){
    int result = getSuggestedMinimumHeight();
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    switch (specMode){
        case MeasureSpec.UNSPECIFIED:
            break;
        case MeasureSpec.EXACTLY:
        case MeasureSpec.AT_MOST:
            result = (int) (specSize*0.7);
            break;
    }
    return result;
}

//测量宽度
private int getWidthMeasure(int measureSpec){
    int result = getSuggestedMinimumWidth();
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    switch (specMode){
        case MeasureSpec.UNSPECIFIED:
            break;
        case MeasureSpec.EXACTLY:
        case MeasureSpec.AT_MOST:
            result = (int) (specSize*0.9);
            break;
    }
    return result;
}

//计算所需各个数值大小
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = w;
    height = h;
    centerX = 0;
    centerY = -height*heightScale;
    mRect = new RectF(-width*widthScale,-width*widthScale+centerY,width*widthScale,width*widthScale+centerY);
    arcStrokeWidth = width/200f*6;
    textGraySize = width/200f*7;
    textSmallSize = width/200f*8;
    textBigSize = textSmallSize*3;
}

3.最后就是把界面画出来

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //设置各个paint所需的大小
    textGrayPaint.setTextSize(textGraySize);
    textSmallPaint.setTextSize(textSmallSize);
    textBigPaint.setTextSize(textBigSize);
    outSideLinePaint.setStrokeWidth(arcStrokeWidth);
    inSideLinePaint.setStrokeWidth(arcStrokeWidth);
    barPaint.setStrokeWidth(arcStrokeWidth);

    paintBelowBackground(canvas);//画下层背景
    paintUpBackground(canvas);//画上层背景
    paintDashLine(canvas);//画虚线
    paintBar(canvas);//画近七天的竖条
    paintBottom(canvas);

    canvas.translate(width/2,height/2); //移动坐标原点到中间
    //画圆弧
    Path path = new Path();
    path.addArc(mRect,120,300);
    canvas.drawPath(path,inSideLinePaint);
    path.reset();
    path.addArc(mRect,120,300*percent);
    canvas.drawPath(path,outSideLinePaint);
    //圆弧间的文字
    textGrayPaint.setTextAlign(Paint.Align.CENTER);
    textGrayPaint.setTextSize(textGraySize);
    canvas.drawText("截至"+nowTime+"已走",0,-textBigSize+centerY,textGrayPaint);
    canvas.drawText(totalText+"",0,textSmallSize/2+centerY,textBigPaint);
    canvas.drawText("好友平均"+freAvgText+"步",0,textBigSize+centerY,textGrayPaint);
    canvas.drawText("第",-textSmallSize/2*3+centerX,width*widthScale+centerY,textGrayPaint);
    canvas.drawText(rankText+"",0+centerX,width*widthScale+centerY,textSmallPaint);
    canvas.drawText("名",textSmallSize/2*3+centerX,width*widthScale+centerY,textGrayPaint);
}

上面只放了部分代码,完整代码地址

PS:模仿QQ运动这个只画出了界面,没有给出点击事件,有兴趣的同学可以自行浏览体验