博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AndroidUI系列 - 自定义View手绘小黄人
阅读量:4166 次
发布时间:2019-05-26

本文共 32184 字,大约阅读时间需要 107 分钟。

总是想尝试各种自定义控件,来熟悉谷歌提供的一些自定绘图的方法,那就画一个小黄人吧。我在git上找到一个小换人的源码。它是按照比例计算的,有一定的公式,我觉得太麻烦了。就用自己的理解画了一个写死大小的小黄人。先给大家看看效果。

git上的小黄人是这样的。
这里写图片描述

我用代码画出来的是这样的。

这里写图片描述

其实有很多地方是不一样的,我会把两套代码都贴出来,有兴趣的朋友可以自己去研究研究。画完之后对Path和canvas有了很多新的认识。以后自定义什么复杂控件,这些都是扎实的基础。

那么在来整理一下,思路。从哪开始画,需要使用一些什么方法来进行绘制。

这里写图片描述

具体方法都有注释,想要研究的就要自己去花时间看代码了。

git上的代码。

import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.CornerPathEffect;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.os.Build;import android.util.AttributeSet;import android.view.View;class MinionView extends View{    private static final int DEFAULT_SIZE = 200; //View默认大小    private int mWidthUnspecified;    private int mHeightUnspecified;    private Paint mPaint;    private float mBodyWidth;    private float mBodyHeight;    private static final float BODY_SCALE = 0.6f;//身体主干占整个view的比重    private static final float BODY_WIDTH_HEIGHT_SCALE = 0.6f; //        身体的比例设定为 w:h = 3:5    private float mStrokeWidth = 4;//描边宽度    private float mOffset;//计算时,部分需要 考虑找边偏移    private float mRadius;//身体上下半圆的半径    private int mColorClothes = Color.rgb(32, 116, 160);//衣服的颜色    private int mColorBody = Color.rgb(249, 217, 70);//衣服的颜色    private int mColorStroke = Color.BLACK;    private RectF mBodyRect;    private float mHandsHeight;//计算出吊带的高度时,可以用来做手的高度    private float mFootHeight;//脚的高度,用来画脚部阴影时用    public MinionView(Context context) {        super(context);    }    public MinionView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MinionView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public MinionView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));    }    /**     * @param origin     * @param isWidth 是否在测量宽     * @return     */    private int measure(int origin, boolean isWidth) {        int result;        int specMode = MeasureSpec.getMode(origin);        int specSize = MeasureSpec.getSize(origin);        switch (specMode) {            case MeasureSpec.EXACTLY:            case MeasureSpec.AT_MOST:                result = specSize;                if (isWidth) {                    mWidthUnspecified = result;                } else {                    mHeightUnspecified = result;                }                break;            case MeasureSpec.UNSPECIFIED:            default:                if (isWidth) {//宽或高未指定的情况下,可以由另一端推算出来 - -如果两边都没指定就用默认值                    result = (int) (mHeightUnspecified * BODY_WIDTH_HEIGHT_SCALE);                } else {                    result = (int) (mWidthUnspecified / BODY_WIDTH_HEIGHT_SCALE);                }                if (result == 0) {                    result = DEFAULT_SIZE;                }                break;        }        return result;    }    @Override    protected void onDraw(Canvas canvas) {        initParams();        initPaint();        drawFeetShadow(canvas);//脚下的阴影        drawFeet(canvas);//脚        drawHands(canvas);//手        drawBody(canvas);//身体        drawClothes(canvas);//衣服        drawEyesMouth(canvas);//眼睛,嘴巴        drawBodyStroke(canvas);//最后画身体的描边,可以摭住一些过渡的棱角    }    private void initParams() {        mBodyWidth = Math.min(getWidth(), getHeight() * BODY_WIDTH_HEIGHT_SCALE) * BODY_SCALE;        mBodyHeight = Math.min(getWidth(), getHeight() * BODY_WIDTH_HEIGHT_SCALE) / BODY_WIDTH_HEIGHT_SCALE * BODY_SCALE;        mStrokeWidth = Math.max(mBodyWidth / 50, mStrokeWidth);        mOffset = mStrokeWidth / 2;        mBodyRect = new RectF();        mBodyRect.left = (getWidth() - mBodyWidth) / 2;        mBodyRect.top = (getHeight() - mBodyHeight) / 2;        mBodyRect.right = mBodyRect.left + mBodyWidth;        mBodyRect.bottom = mBodyRect.top + mBodyHeight;        mRadius = mBodyWidth / 2;        mFootHeight = mRadius * 0.4333f;        mHandsHeight =  (getHeight() + mBodyHeight) / 2   + mOffset - mRadius * 1.65f ;    }    private void drawBody(Canvas canvas) {        initPaint();        mPaint.setColor(mColorBody);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawRoundRect(mBodyRect, mRadius, mRadius, mPaint);    }    private void drawBodyStroke(Canvas canvas) {        initPaint();        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawRoundRect(mBodyRect, mRadius, mRadius, mPaint);    }    private void drawClothes(Canvas canvas) {        initPaint();        RectF rect = new RectF();        rect.left = (getWidth() - mBodyWidth) / 2 + mOffset;        rect.top = (getHeight() + mBodyHeight) / 2 - mRadius * 2 + mOffset;        rect.right = rect.left + mBodyWidth - mOffset * 2;        rect.bottom = rect.top + mRadius * 2 - mOffset * 2;        mPaint.setColor(mColorClothes);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setStrokeWidth(mStrokeWidth);        canvas.drawArc(rect, 0, 180, true, mPaint);        int h = (int) (mRadius * 0.5);        int w = (int) (mRadius * 0.3);        rect.left += w;        rect.top = rect.top + mRadius - h;        rect.right -= w;        rect.bottom = rect.top + h;        canvas.drawRect(rect, mPaint);        //画横线        initPaint();        mPaint.setColor(mColorStroke);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setStrokeWidth(mStrokeWidth);        float[] pts = new float[20];//5条线        pts[0] = rect.left - w;        pts[1] = rect.top + h;        pts[2] = pts[0] + w;        pts[3] = pts[1];        pts[4] = pts[2];        pts[5] = pts[3] + mOffset;        pts[6] = pts[4];        pts[7] = pts[3] - h;        pts[8] = pts[6] - mOffset;        pts[9] = pts[7];        pts[10] = pts[8] + (mRadius - w) * 2;        pts[11] = pts[9];        pts[12] = pts[10];        pts[13] = pts[11] - mOffset;        pts[14] = pts[12];        pts[15] = pts[13] + h;        pts[16] = pts[14] - mOffset;        pts[17] = pts[15];        pts[18] = pts[16] + w;        pts[19] = pts[17];        canvas.drawLines(pts, mPaint);        //画左吊带        initPaint();        mPaint.setColor(mColorClothes);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.FILL);        Path path = new Path();        path.moveTo(rect.left - w - mOffset, mHandsHeight);        path.lineTo(rect.left + h / 4, rect.top + h / 2);        final float smallW = w / 2 * (float) Math.sin(Math.PI / 4);        path.lineTo(rect.left + h / 4 + smallW, rect.top + h / 2 - smallW);        final float smallW2 = w / (float) Math.sin(Math.PI / 4) / 2;        path.lineTo(rect.left - w - mOffset, mHandsHeight - smallW2);        canvas.drawPath(path, mPaint);        initPaint();        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path, mPaint);        initPaint();        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawCircle(rect.left + h / 5, rect.top + h / 4, mStrokeWidth*0.7f, mPaint);        //画右吊带        initPaint();        mPaint.setColor(mColorClothes);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.FILL);        path.reset();        path.moveTo(rect.left - w + 2 * mRadius - mOffset, mHandsHeight);        path.lineTo(rect.right - h / 4, rect.top + h / 2);        path.lineTo(rect.right - h / 4 - smallW, rect.top + h / 2 - smallW);        path.lineTo(rect.left - w + 2 * mRadius - mOffset, mHandsHeight - smallW2);        canvas.drawPath(path, mPaint);        initPaint();        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path, mPaint);        initPaint();        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawCircle(rect.right - h / 5, rect.top + h / 4, mStrokeWidth*0.7f, mPaint);        //中间口袋        initPaint();        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        path.reset();        float radiusBigPokect = w / 2.0f;        path.moveTo(rect.left + 1.5f * w, rect.bottom - h / 4);        path.lineTo(rect.right - 1.5f * w, rect.bottom - h / 4);        path.lineTo(rect.right - 1.5f * w, rect.bottom + h / 4);        path.addArc(rect.right - 1.5f * w - radiusBigPokect * 2, rect.bottom + h / 4 - radiusBigPokect,                rect.right - 1.5f * w, rect.bottom + h / 4 + radiusBigPokect, 0, 90);        path.lineTo(rect.left + 1.5f * w + radiusBigPokect, rect.bottom + h / 4 + radiusBigPokect);        path.addArc(rect.left + 1.5f * w, rect.bottom + h / 4 - radiusBigPokect,                rect.left + 1.5f * w + 2 * radiusBigPokect, rect.bottom + h / 4 + radiusBigPokect, 90, 90);        path.lineTo(rect.left + 1.5f * w, rect.bottom - h / 4 - mOffset);        canvas.drawPath(path, mPaint);//        下边一竖,分开裤子        canvas.drawLine(mBodyRect.left + mBodyWidth / 2, mBodyRect.bottom - h * 0.8f, mBodyRect.left + mBodyWidth / 2, mBodyRect.bottom, mPaint);//      左边的小口袋        float radiusSamllPokect = w * 1.2f;        canvas.drawArc(mBodyRect.left - radiusSamllPokect, mBodyRect.bottom - mRadius - radiusSamllPokect,                mBodyRect.left + radiusSamllPokect, mBodyRect.bottom - mRadius + radiusSamllPokect, 80, -60, false, mPaint);//      右边小口袋        canvas.drawArc(mBodyRect.right - radiusSamllPokect, mBodyRect.bottom - mRadius - radiusSamllPokect,                mBodyRect.right + radiusSamllPokect, mBodyRect.bottom - mRadius + radiusSamllPokect, 100, 60, false, mPaint);//        canvas.drawArc(left + w/5,);    }    private void drawEyesMouth(Canvas canvas) {        float eyesOffset = mRadius * 0.1f;//眼睛中心处于上半圆直径 往上的高度偏移        mPaint.setStrokeWidth(mStrokeWidth * 5);//        计算眼镜带弧行的半径 分两段,以便眼睛中间有隔开的效果        float radiusGlassesRibbon = (float) (mRadius / Math.sin(Math.PI / 20));        RectF rect = new RectF();        rect.left = mBodyRect.left + mRadius - radiusGlassesRibbon;        rect.top = mBodyRect.top + mRadius - (float) (mRadius / Math.tan(Math.PI / 20)) - radiusGlassesRibbon - eyesOffset;        rect.right = rect.left + radiusGlassesRibbon * 2;        rect.bottom = rect.top + radiusGlassesRibbon * 2;        canvas.drawArc(rect, 81, 3, false, mPaint);        canvas.drawArc(rect, 99, -3, false, mPaint);//眼睛半径        float radiusEyes = mRadius / 3;        initPaint();        mPaint.setColor(Color.WHITE);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 - radiusEyes - mOffset, mBodyRect.top + mRadius - eyesOffset, radiusEyes, mPaint);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 + radiusEyes + mOffset, mBodyRect.top + mRadius - eyesOffset, radiusEyes, mPaint);        mPaint.setColor(mColorStroke);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 - radiusEyes - mOffset, mBodyRect.top + mRadius - eyesOffset, radiusEyes, mPaint);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 + radiusEyes + mOffset, mBodyRect.top + mRadius - eyesOffset, radiusEyes, mPaint);        final float radiusEyeballBlack = radiusEyes / 3;        mPaint.setStyle(Paint.Style.FILL);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 - radiusEyes - mOffset, mBodyRect.top + mRadius - eyesOffset, radiusEyeballBlack, mPaint);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 + radiusEyes + mOffset, mBodyRect.top + mRadius - eyesOffset, radiusEyeballBlack, mPaint);        mPaint.setColor(Color.WHITE);        final float radiusEyeballWhite = radiusEyeballBlack / 2;        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 - radiusEyes + radiusEyeballWhite - mOffset * 2,                mBodyRect.top + mRadius - radiusEyeballWhite + mOffset - eyesOffset,                radiusEyeballWhite, mPaint);        canvas.drawCircle(mBodyRect.left + mBodyWidth / 2 + radiusEyes + radiusEyeballWhite,                mBodyRect.top + mRadius - radiusEyeballWhite + mOffset - eyesOffset,                radiusEyeballWhite, mPaint);//        画嘴巴,因为位置和眼睛有相对关系,所以写在一块        mPaint.setColor(mColorStroke);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth(mStrokeWidth);        float radiusMonth = mRadius;        rect.left = mBodyRect.left;        rect.top = mBodyRect.top - radiusMonth / 2.5f;        rect.right = rect.left + radiusMonth * 2;        rect.bottom = rect.top + radiusMonth * 2;        canvas.drawArc(rect, 95, -20, false, mPaint);    }    private void drawFeet(Canvas canvas) {        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setColor(mColorStroke);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        float radiusFoot = mRadius / 3 * 0.4f;        float leftFootStartX = mBodyRect.left + mRadius - mOffset * 2;        float leftFootStartY = mBodyRect.bottom - mOffset;        float footWidthA = mRadius * 0.5f;//脚宽度大-到半圆结束        float footWidthB = footWidthA / 3;//脚宽度-比较细的部分        //      左脚        Path path = new Path();        path.moveTo(leftFootStartX, leftFootStartY);        path.lineTo(leftFootStartX, leftFootStartY + mFootHeight);        path.lineTo(leftFootStartX - footWidthA + radiusFoot, leftFootStartY + mFootHeight);        RectF rectF = new RectF();        rectF.left = leftFootStartX - footWidthA;        rectF.top = leftFootStartY + mFootHeight - radiusFoot * 2;        rectF.right = rectF.left + radiusFoot * 2;        rectF.bottom = rectF.top + radiusFoot * 2;        path.addArc(rectF, 90, 180);        path.lineTo(rectF.left + radiusFoot + footWidthB, rectF.top);        path.lineTo(rectF.left + radiusFoot + footWidthB, leftFootStartY);        path.lineTo(leftFootStartX, leftFootStartY);        canvas.drawPath(path, mPaint);//      右脚        float rightFootStartX = mBodyRect.left + mRadius + mOffset * 2;        float rightFootStartY = leftFootStartY;        path.reset();        path.moveTo(rightFootStartX, rightFootStartY);        path.lineTo(rightFootStartX, rightFootStartY + mFootHeight);        path.lineTo(rightFootStartX + footWidthA - radiusFoot, rightFootStartY + mFootHeight);        rectF.left = rightFootStartX + footWidthA - radiusFoot * 2;        rectF.top = rightFootStartY + mFootHeight - radiusFoot * 2;        rectF.right = rectF.left + radiusFoot * 2;        rectF.bottom = rectF.top + radiusFoot * 2;        path.addArc(rectF, 90, -180);        path.lineTo(rectF.right - radiusFoot - footWidthB, rectF.top);        path.lineTo(rectF.right - radiusFoot - footWidthB, rightFootStartY);        path.lineTo(rightFootStartX, rightFootStartY);        canvas.drawPath(path, mPaint);    }    private void drawFeetShadow(Canvas canvas) {        mPaint.setColor(getResources().getColor(android.R.color.darker_gray));        canvas.drawOval(mBodyRect.left + mBodyWidth * 0.15f, mBodyRect.bottom - mOffset + mFootHeight,                mBodyRect.right - mBodyWidth * 0.15f, mBodyRect.bottom - mOffset + mFootHeight + mStrokeWidth * 1.3f, mPaint);    }    private void drawHands(Canvas canvas) {        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        mPaint.setColor(mColorBody);//        左手        Path path = new Path();        float hypotenuse = mBodyRect.bottom - mRadius - mHandsHeight;        float radiusHand = hypotenuse / 6;        mPaint.setPathEffect(new CornerPathEffect(radiusHand));        path.moveTo(mBodyRect.left, mHandsHeight);        path.lineTo(mBodyRect.left - hypotenuse / 2, mHandsHeight + hypotenuse / 2);        path.lineTo(mBodyRect.left + mOffset, mBodyRect.bottom - mRadius + mOffset);        path.lineTo(mBodyRect.left  , mHandsHeight);//增加兼容性,path没闭合在一起机子上会使手的下面的点没办法与裤子重合        canvas.drawPath(path, mPaint);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setColor(mColorStroke);        canvas.drawPath(path, mPaint);//        右手        path.reset();        mPaint.setStyle(Paint.Style.FILL);        mPaint.setColor(mColorBody);        path.moveTo(mBodyRect.right, mHandsHeight);        path.lineTo(mBodyRect.right + hypotenuse / 2, mHandsHeight + hypotenuse / 2);        path.lineTo(mBodyRect.right  - mOffset, mBodyRect.bottom - mRadius + mOffset);        path.lineTo(mBodyRect.right, mHandsHeight);        canvas.drawPath(path, mPaint);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setColor(mColorStroke);        canvas.drawPath(path, mPaint);//        一个慢动作  - -||| 拐点内侧        path.reset();        mPaint.setStyle(Paint.Style.FILL);        path.moveTo(mBodyRect.left, mHandsHeight + hypotenuse / 2 - mStrokeWidth);        path.lineTo(mBodyRect.left - mStrokeWidth * 2, mHandsHeight + hypotenuse / 2 + mStrokeWidth * 2);        path.lineTo(mBodyRect.left, mHandsHeight + hypotenuse / 2 + mStrokeWidth);        path.lineTo(mBodyRect.left, mHandsHeight + hypotenuse / 2 - mStrokeWidth);        canvas.drawPath(path, mPaint);        path.reset();        path.moveTo(mBodyRect.right, mHandsHeight + hypotenuse / 2 - mStrokeWidth);        path.lineTo(mBodyRect.right + mStrokeWidth * 2, mHandsHeight + hypotenuse / 2 + mStrokeWidth * 2);        path.lineTo(mBodyRect.right, mHandsHeight + hypotenuse / 2 + mStrokeWidth);        path.lineTo(mBodyRect.right, mHandsHeight + hypotenuse / 2 - mStrokeWidth);        canvas.drawPath(path, mPaint);    }    private void initPaint() {        if (mPaint == null) {            mPaint = new Paint();        } else {            mPaint.reset();        }        mPaint.setAntiAlias(true);//边缘无锯齿    }    /*public void randomBodyColor() {        Random random = new Random();        mColorBody = Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255));        invalidate();    }*/}

那么在看看我的代码与他的代码的区别。

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.view.View;/** * Created by ShuWen on 2017/6/27. */public class MinionViewNew extends View {    private static final int DEFAULT_SIZE = 200; //View默认大小    private int mWidthUnspecified;    private int mHeightUnspecified;    private Paint mPaint;    private float mBodyWidth;    private float mBodyHeight;    private static final float BODY_SCALE = 0.6f;//身体主干占整个view的比重    private static final float BODY_WIDTH_HEIGHT_SCALE = 0.6f; //        身体的比例设定为 w:h = 3:5    private float mStrokeWidth = 10;//描边宽度    private float mOffset;//计算时,部分需要 考虑找边偏移    private float mRadius;//身体上下半圆的半径    private int mColorClothes = Color.rgb(32, 116, 160);//衣服的颜色    private int mColorBody = Color.rgb(249, 217, 70);//衣服的颜色    private int mColorStroke = Color.BLACK;    private RectF mBodyRect;    private float mHandsHeight;//计算出吊带的高度时,可以用来做手的高度    private float mFootHeight;//脚的高度,用来画脚部阴影时用    public MinionViewNew(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public MinionViewNew(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MinionViewNew(Context context) {        super(context);    }    @Override    protected void onDraw(Canvas canvas) {        initParams();        initPaint();        drawFeetShadow(canvas);        drawFeet(canvas);//脚        drawBody(canvas);//身体        drawEyesMouth(canvas);//眼睛,嘴巴        drawHands(canvas);//手        drawClothes(canvas);//衣服    }    private void drawClothes(Canvas canvas) {        initPaint();        //肚子颜色        mPaint.setColor(mColorClothes);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setStrokeWidth(mStrokeWidth);        RectF rectF = new RectF();        rectF.left = getWidth()/2 - 246;  //x        rectF.top = getHeight()/2 - 110; //y        rectF.right = rectF.left + 492;        rectF.bottom = rectF.top + 505;        canvas.drawArc(rectF,0,180,true,mPaint);        Path path = new Path();        path.moveTo(getWidth()/2-250,getHeight()/2+144);        path.lineTo(getWidth()/2-150,getHeight()/2+144);        path.lineTo(getWidth()/2-150,getHeight()/2+50);        path.lineTo(getWidth()/2+150,getHeight()/2+50);        path.lineTo(getWidth()/2+150,getHeight()/2+144);        path.lineTo(getWidth()/2+250,getHeight()/2+144);        mPaint.setColor(mColorClothes);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawPath(path,mPaint);        mPaint.setColor(Color.BLACK);        mPaint.setStrokeWidth(8);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path,mPaint);        //左吊带        path.moveTo(getWidth()/2 - 250,getHeight()/2 - 50);        path.lineTo(getWidth()/2 - 110,getHeight()/2 + 70);        path.lineTo(getWidth()/2 - 130,getHeight()/2 + 100);        path.lineTo(getWidth()/2 - 250,getHeight()/2 - 10);        mPaint.setColor(mColorClothes);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawPath(path,mPaint);        mPaint.setColor(Color.BLACK);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path,mPaint);        //右吊带        path.moveTo(getWidth()/2 + 250,getHeight()/2 - 50);        path.lineTo(getWidth()/2 + 110,getHeight()/2 + 70);        path.lineTo(getWidth()/2 + 130,getHeight()/2 + 100);        path.lineTo(getWidth()/2 + 250,getHeight()/2 - 10);        mPaint.setColor(mColorClothes);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawPath(path,mPaint);        mPaint.setColor(Color.BLACK);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path,mPaint);        //画衣服口袋        path.moveTo(getWidth()/2-80,getHeight()/2+144);        path.lineTo(getWidth()/2+80,getHeight()/2+144);        rectF.left = getWidth()/2-80;        rectF.top = getHeight()/2+44;        rectF.right = rectF.left + 160;        rectF.bottom = rectF.top + 200;        path.addArc(rectF,0,180);        canvas.drawPath(path,mPaint);        //裤子线        path.moveTo(getWidth()/2,getHeight()/2+314);        path.lineTo(getWidth()/2,getHeight()/2+394);        canvas.drawPath(path,mPaint);        //裤子口袋        path.moveTo(getWidth()/2-218,getHeight()/2+254);        path.lineTo(getWidth()/2-170,getHeight()/2+184);        canvas.drawPath(path,mPaint);        path.moveTo(getWidth()/2+218,getHeight()/2+254);        path.lineTo(getWidth()/2+170,getHeight()/2+184);        canvas.drawPath(path,mPaint);    }    private void drawEyesMouth(Canvas canvas) {        //眼眶        initPaint();        mPaint.setColor(Color.WHITE);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawCircle(getWidth() / 2 - 75,getHeight() / 2 - 180,70,mPaint); //左眼眶        canvas.drawCircle(getWidth() / 2 + 75,getHeight() / 2 - 180,70,mPaint); //右眼眶        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setColor(Color.BLACK);        canvas.drawCircle(getWidth() / 2 - 75,getHeight() / 2 - 180,70,mPaint);        canvas.drawCircle(getWidth() / 2 + 75,getHeight() / 2 - 180,70,mPaint);        //眼珠子        initPaint();        mPaint.setColor(Color.BLACK);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawCircle(getWidth() / 2 - 75,getHeight() / 2 - 180,40,mPaint);        canvas.drawCircle(getWidth() / 2 + 75,getHeight() / 2 - 180,40,mPaint);        //眼睛        initPaint();        mPaint.setColor(Color.WHITE);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        canvas.drawCircle(getWidth() / 2 - 60,getHeight() / 2 - 195,20,mPaint);        canvas.drawCircle(getWidth() / 2 + 90,getHeight() / 2 - 195,20,mPaint);        //画嘴巴        initPaint();        mPaint.setColor(Color.BLACK);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        mPaint.setStrokeWidth(mStrokeWidth);        RectF rectF = new RectF();        rectF.left = getWidth() / 2 - 70;        rectF.top = getHeight() / 2 - 100;        rectF.right = rectF.left + 140;        rectF.bottom = rectF.top + 80;        canvas.drawArc(rectF, 105, -60, false, mPaint);        //画眼带        initPaint();        mPaint.setColor(Color.BLACK);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        mPaint.setStrokeWidth(50);        //左眼带        rectF.left = getWidth() / 2 - 300;        rectF.top = getHeight() / 2 - 280;        rectF.right = rectF.left + 300;        rectF.bottom = rectF.top + 100;        canvas.drawArc(rectF, 88, 40, false, mPaint);        //右眼带        rectF.left = getWidth() / 2 ;        rectF.top = getHeight() / 2 - 280;        rectF.right = rectF.left + 300;        rectF.bottom = rectF.top + 100;        canvas.drawArc(rectF, 92, -42, false, mPaint);    }    private void drawBody(Canvas canvas) {        initPaint();        mPaint.setColor(mColorBody);        mPaint.setStyle(Paint.Style.FILL);        RectF rectF = new RectF();        rectF.left = getWidth() / 2 - 250;  //x        rectF.top = getHeight() / 2 - 400; //y        rectF.right = rectF.left + 500;        rectF.bottom = rectF.top + 800;        mRadius = 250;        canvas.drawRoundRect(rectF, mRadius, mRadius, mPaint);        initPaint();        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawRoundRect(rectF, mRadius, mRadius, mPaint);    }    private void drawHands(Canvas canvas) {        initPaint();        //左手        Path path = new Path();        path.moveTo(getWidth()/2 - 250,getHeight()/2 - 10);        path.lineTo(getWidth() / 2 - 350,getHeight() / 2 + 60);        path.lineTo(getWidth()/2-250,getHeight()/2+130);        mPaint.setColor(mColorBody);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawPath(path,mPaint);        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(10);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path,mPaint);        path.moveTo(getWidth()/2 - 250,getHeight()/2 + 60);        path.lineTo(getWidth() / 2 - 265,getHeight() / 2 + 70);        canvas.drawPath(path,mPaint);        //右手        path.moveTo(getWidth()/2 + 250,getHeight()/2 - 10);        path.lineTo(getWidth() / 2 + 350,getHeight() / 2 + 60);        path.lineTo(getWidth()/2+250,getHeight()/2+130);        mPaint.setColor(mColorBody);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawPath(path,mPaint);        mPaint.setColor(mColorStroke);        mPaint.setStrokeWidth(8);        mPaint.setStyle(Paint.Style.STROKE);        canvas.drawPath(path,mPaint);        path.moveTo(getWidth()/2 + 250,getHeight()/2 + 60);        path.lineTo(getWidth() / 2 + 265,getHeight() / 2 + 70);        canvas.drawPath(path,mPaint);    }    private void test(Canvas canvas){        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setColor(mColorStroke);        mPaint.setStyle(Paint.Style.STROKE);        RectF rectF = new RectF(200,200,600,400);        canvas.drawArc(rectF,90,90,false,mPaint);    }    private void drawFeet(Canvas canvas) {        mPaint.setStrokeWidth(mStrokeWidth);        mPaint.setColor(mColorStroke);        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);        //画左脚        Path path = new Path();        float leftFootStartX = getWidth() / 2 - 10;        float leftFootstartY = mBodyRect.bottom -10;        path.moveTo(leftFootStartX,leftFootstartY);        path.lineTo(leftFootStartX - 100,leftFootstartY);        RectF rectF = new RectF();        rectF.left = leftFootStartX - 115;        rectF.top = leftFootstartY - 50;        rectF.right = rectF.left + 30;        rectF.bottom = rectF.top + 50;        path.addArc(rectF,90,180);        path.lineTo(leftFootStartX - 50,leftFootstartY - 50);        path.lineTo(leftFootStartX - 50,leftFootstartY - 100);        path.lineTo(leftFootStartX ,leftFootstartY - 100);        path.lineTo(leftFootStartX ,leftFootstartY);        canvas.drawPath(path, mPaint);        //画右脚        path.reset();        float rightFootStartX = getWidth() / 2 + 10;        float rightFootstartY = mBodyRect.bottom -10;        path.moveTo(rightFootStartX,rightFootstartY);        path.lineTo(rightFootStartX + 100,rightFootstartY);        RectF rectF1 = new RectF();        rectF1.left = rightFootStartX + 85;        rectF1.top = rightFootstartY - 50;        rectF1.right = rectF1.left + 30;        rectF1.bottom = rectF1.top + 50;        path.addArc(rectF1,90,-180);        path.lineTo(rightFootStartX + 50,rightFootstartY - 50);        path.lineTo(rightFootStartX + 50,rightFootstartY - 100);        path.lineTo(rightFootStartX ,rightFootstartY - 100);        path.lineTo(rightFootStartX ,rightFootstartY);        canvas.drawPath(path, mPaint);//        float radiusFoot = mRadius / 3 * 0.4f;//        float leftFootStartX = mBodyRect.left + mRadius - mOffset * 2;//        float leftFootStartY = mBodyRect.bottom - mOffset;//        float footWidthA = mRadius * 0.5f;//脚宽度大-到半圆结束//        float footWidthB = footWidthA / 3;//脚宽度-比较细的部分////        //      左脚//        Path path = new Path();//        path.moveTo(leftFootStartX, leftFootStartY);//        path.lineTo(leftFootStartX, leftFootStartY + mFootHeight);//        path.lineTo(leftFootStartX - footWidthA + radiusFoot, leftFootStartY + mFootHeight);////        RectF rectF = new RectF();//        rectF.left = leftFootStartX - footWidthA;//        rectF.top = leftFootStartY + mFootHeight - radiusFoot * 2;//        rectF.right = rectF.left + radiusFoot * 2;//        rectF.bottom = rectF.top + radiusFoot * 2;//        path.addArc(rectF, 90, 180);//        path.lineTo(rectF.left + radiusFoot + footWidthB, rectF.top);//        path.lineTo(rectF.left + radiusFoot + footWidthB, leftFootStartY);//        path.lineTo(leftFootStartX, leftFootStartY);//        canvas.drawPath(path, mPaint);//      右脚//        float rightFootStartX = mBodyRect.left + mRadius + mOffset * 2;//        float rightFootStartY = leftFootStartY;//        path.reset();//        path.moveTo(rightFootStartX, rightFootStartY);//        path.lineTo(rightFootStartX, rightFootStartY + mFootHeight);//        path.lineTo(rightFootStartX + footWidthA - radiusFoot, rightFootStartY + mFootHeight);////        rectF.left = rightFootStartX + footWidthA - radiusFoot * 2;//        rectF.top = rightFootStartY + mFootHeight - radiusFoot * 2;//        rectF.right = rectF.left + radiusFoot * 2;//        rectF.bottom = rectF.top + radiusFoot * 2;//        path.addArc(rectF, 90, -180);//        path.lineTo(rectF.right - radiusFoot - footWidthB, rectF.top);//        path.lineTo(rectF.right - radiusFoot - footWidthB, rightFootStartY);//        path.lineTo(rightFootStartX, rightFootStartY);//        canvas.drawPath(path, mPaint);    }    private void drawFeetShadow(Canvas canvas) {        mPaint.setColor(getResources().getColor(android.R.color.darker_gray));        canvas.drawOval(getWidth() / 2 - 200,mBodyRect.bottom - 10,getWidth() / 2 + 200,mBodyRect.bottom + 10,mPaint );    }    private void initParams() {//        mBodyWidth = Math.min(getWidth(), getHeight() * BODY_WIDTH_HEIGHT_SCALE) * BODY_SCALE;//        mBodyHeight = Math.min(getWidth(), getHeight() * BODY_WIDTH_HEIGHT_SCALE) / BODY_WIDTH_HEIGHT_SCALE * BODY_SCALE;////        mStrokeWidth = Math.max(mBodyWidth / 50, mStrokeWidth);//        mOffset = mStrokeWidth / 2;        int widthCenter = getWidth() / 2;        int heightCenter = getHeight() / 2;        mBodyRect = new RectF();        mBodyRect.left = widthCenter - 400;        mBodyRect.top = heightCenter - 500;        mBodyRect.right = mBodyRect.left + 800;        mBodyRect.bottom = mBodyRect.top + 1000;//        mRadius = mBodyWidth / 2;//        mFootHeight = mRadius * 0.4333f;//        mHandsHeight =  (getHeight() + mBodyHeight) / 2   + mOffset - mRadius * 1.65f ;    }    private void initPaint(){        if (mPaint == null){            mPaint = new Paint();        }else {            mPaint.reset();        }        mPaint.setAntiAlias(true);    }}

当然这会花很多时间,其实做完之后就会发现这些都是值得的。爱学习的爱技术的人都是值得尊重的。

你可能感兴趣的文章
嵌入式100题(042):为什么服务端易受到SYN攻击?
查看>>
嵌入式100题(043):什么是四次挥手
查看>>
嵌入式100题(044):为什么客户端最后还要等待2MSL?
查看>>
嵌入式100题(045):为什么建立连接是三次握手,关闭连接确是四次挥手呢?...
查看>>
嵌入式100题(028):static的用法(定义和用途)
查看>>
嵌入式100题(027):char和int之间的转换
查看>>
嵌入式100题(029):const常量和#define的区别(编译阶段、安全性、内存占用等)...
查看>>
嵌入式100题(030):volatile作用和用法
查看>>
嵌入式100题(033):TCP、UDP的优缺点
查看>>
嵌入式100题(035):TCP为什么是可靠连接
查看>>
嵌入式100题(034):TCP UDP适用场景
查看>>
嵌入式100题(70):一个程序从开始运行到结束的完整过程(四个过程)
查看>>
嵌入式100题(71):什么是堆,栈,内存泄漏和内存溢出?
查看>>
嵌入式100题(73):死锁的原因、条件 创建一个死锁,以及如何预防
查看>>
嵌入式100题(60):系统调用的作用
查看>>
C语言基本概念归纳
查看>>
初识单片机
查看>>
在单片机上点亮LED
查看>>
初学定时器
查看>>
数码管
查看>>