android: 一次自绘控件的体验

一个盆友在 qq 上面给我一个截图,问我有没有见过这种效果。我一看,貌似不太难,虽然我并不熟悉自定义控件,但是网上的教程很多,于是决定实现一下。

android: 一次自绘控件的体验_第1张图片

这个就是给我的截图。不是很清晰,也不完整。但是重点突出出来了。

于是,我看了看 HenCoder 的教程1,决定实现一下。(当然,实现期间,也翻阅了一下其他人的博客)

我实现的效果如下:

android: 一次自绘控件的体验_第2张图片

大体实现贴一下:

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        this.mWidth = w;
        this.mHeight = h;

        min = Math.min(mWidth, mHeight);
        tableList = DynamicData.getViewSource();
        paint = new Paint();
        LogUtils.w(tableList);

        oval = new RectF(0, 0, min, min);
        icon = new RectF();

        diffLeft = min / 10;
        diffRight = diffLeft;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawLeft(canvas);

        iconLength = 1f * min / 17;
        int height = (int) (iconLength / 2);
        for (Table t : tableList) {
            float left = min + diffLeft;
            float right = left + iconLength;
            float top = 0;
            float bottom = top + iconLength;
            paint.setColor(t.color);
            icon.set(left, height + top, right, height + bottom);
            canvas.drawRect(icon, paint);

            paint.setTextSize(iconLength);
            paint.setColor(Color.BLACK);
            canvas.drawText(t.name + "\t" + (int) t.percent + "%",
                    right + diffRight, height + bottom, paint);
            height += iconLength * 3;
        }
    }

    private void drawLeft(Canvas canvas) {
        paint.setColor(Color.parseColor("#dbdbdb"));
        canvas.drawRect(oval, paint);
        int start = 180;
        for (Table t : tableList) {
            float angle = (float) t.percent / 100 * 360;
            paint.setColor(t.color);
            paint.setStrokeCap(Paint.Cap.ROUND);

            scaleOval(t.scale);
            canvas.drawArc(oval, start, angle,
                    true, paint);
            start += angle;
        }
        paint.setColor(Color.WHITE);
        canvas.drawCircle(1f * min / 2, 1f * min / 2, min * 1f / 12, paint);
        scaleOval(1); // 要加这一句,不然 onStop 后再进来就变小了
    }

    private void scaleOval(float scale) {
        oval.set(0, 0, min, min);
        float left = 1f * min * (1 - scale) / 2;
        float top = 1f * min * (1 - scale) / 2;
        float right = 1f * min * scale + left;
        float bottom = 1f * min * scale + top;
        oval.set(left, top, right, bottom);
    }

嗯,里面的逻辑不复杂,主要是对系统 api 的调用,然后计算一下,每次画的起始位置。

其实,这种东西,我之前看到也会害怕,但是,真的很一般,不难的。


不过,这里还是有需要优化的地方,比如最小尺寸,如果设置成 wrap_conent 怎么处理,等等。我这里的逻辑全部是 onDraw()需要的,其他的,我没有去实现。

如果想看完整源码:献丑了,戳我。。。

你可能感兴趣的:(android)