总是想尝试各种自定义控件,来熟悉谷歌提供的一些自定绘图的方法,那就画一个小黄人吧。我在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);
}
}
当然这会花很多时间,其实做完之后就会发现这些都是值得的。爱学习的爱技术的人都是值得尊重的。