
嘿,兄弟萌,打开手机瞧瞧,哪个App界面不是由一堆矩形、圆形、三角形堆出来的?按钮是圆角矩形,头像是个圈,进度条是粗线,连弹窗都是带圆角的矩形套矩形……(此处省略200字对现代UI的吐槽)
但问题来了:为啥不全部让设计师切图,非要程序员手撸代码?
答案很现实:
动态适配:图片放大变马赛克,代码画的图形放大后依然丝滑!灵活变色:产品经理说“按钮今晚想穿紫色蕾丝边”,你改个颜色值就能交差,不用求设计师重新出图。性能优化:减少图片资源,安装包瘦身,用户手机感谢你!所以,学好几何绘制,等于掌握“界面变装魔术”——用代码画一切!
想象一下:
Canvas(画布):你家客厅的白墙,负责定义“能画在哪”和“画什么形状”。Paint(画笔):你手里的马克笔,决定“颜色多骚”“线条多粗”“要不要填充”。举个栗子:
你想画个红色实心圆,流程是:
他俩的关系,就像火锅和毛肚——缺了谁都不完整!
代码示例:
// 初始化画笔(Paint)
Paint paint = new Paint();
paint.setColor(Color.RED); // 颜色:红
paint.setStyle(Paint.Style.FILL); // 样式:填充(实心)
// 在画布上画圆(Canvas)
canvas.drawCircle(500, 500, 100, paint); // (x坐标, y坐标, 半径, 画笔)
参数解读:
(500, 500):圆心坐标(想象成定位钉)
100:半径(决定圆的大小)
Paint.Style.FILL:实心模式,改成
STROKE就变空心圆!
实战段子:
产品经理要求“头像带金色光环”,你只需要:
代码示例:
// 高级玩法:用RectF定义矩形区域(支持浮点数,更精准!)
RectF rect = new RectF(100, 100, 400, 300);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE); // 空心模式
paint.setStrokeWidth(10); // 边框厚度:10像素
canvas.drawRect(rect, paint);
避坑指南:
直接传
left, top, right, bottom坐标也行,但用
RectF更专业!设置
StrokeWidth前记得切到
STROKE模式,否则看不见边框!
代码示例:
// 画一条从(50,50)到(600,50)的绿色粗线
paint.setColor(Color.GREEN);
paint.setStrokeWidth(20); // 线的粗细(像素)
canvas.drawLine(50, 50, 600, 50, paint);
// 批量画线(高效装逼必备)
float[] points = {x1, y1, x2, y2, x3, y3, x4, y4}; // 多组点坐标
canvas.drawLines(points, paint);
使用场景:
进度条、分割线、图表轴线……一切“直男审美”元素!代码示例:
RectF rect = new RectF(100, 100, 500, 300);
paint.setColor(Color.MAGENTA);
paint.setStyle(Paint.Style.FILL);
// 后两个参数:圆角横向半径、圆角纵向半径
canvas.drawRoundRect(rect, 30, 15, paint);
设计师暗语:
当她说“要弥散感圆角”,其实是想让你调大圆角半径!半径值越大,矩形越像“胶囊”,极大值直接变椭圆!代码示例:
RectF oval = new RectF(100, 100, 500, 500); // 弧所在的椭圆边界
paint.setColor(Color.CYAN);
// 参数:椭圆区域、起始角度、扫过角度、是否连接圆心、画笔
canvas.drawArc(oval, 0, 90, true, paint); // 画一个90度的扇形
角度科普:
0度在钟表3点位置,顺时针增加(和数学课本相反!)设置
false不连接圆心,就变成“圆弧饼干的缺口”!
下面是一个可直接粘贴运行的代码,会在屏幕上同时展示圆、方、线、弧:
public class GeometryView extends View {
private Paint paint;
public GeometryView(Context context) {
super(context);
initPaint();
}
// 初始化画笔配置
private void initPaint() {
paint = new Paint();
paint.setAntiAlias(true); // 开启抗锯齿(边缘更丝滑)
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1. 画红色实心圆
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(200, 200, 100, paint);
// 2. 画蓝色空心矩形
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
canvas.drawRect(400, 100, 700, 300, paint);
// 3. 画绿色粗线
paint.setColor(Color.GREEN);
paint.setStrokeWidth(15);
canvas.drawLine(100, 500, 600, 500, paint);
// 4. 画粉色圆角矩形
paint.setColor(Color.MAGENTA);
paint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(100, 600, 500, 800, 30, 30, paint);
// 5. 画青色扇形
paint.setColor(Color.CYAN);
RectF oval = new RectF(600, 600, 900, 900);
canvas.drawArc(oval, 0, 90, true, paint);
}
}
// 在Activity中使用:
// setContentView(new GeometryView(this));
运行效果:
屏幕上会同时出现:
静态图形太无聊?试试在
onDraw里动态改变坐标:
// 在View类中声明变量
private float circleX = 100;
// 在onDraw中使用变量
canvas.drawCircle(circleX, 200, 100, paint);
// 在外部调用方法改变位置
public void moveCircle() {
circleX += 10;
invalidate(); // 触发重绘(灵魂所在!)
}
原理:
每次调用
invalidate(),系统会重新调用
onDraw(),图形位置更新——动画成了!
记住三句真言:
Canvas是舞台,Paint是演员,缺了谁戏都唱不成。坐标计算是灵魂,多练才能摆脱“布局靠蒙”的尴尬。动起来才是王道,静态图形最多算“素描”,动态效果才是“科幻大片”。最后送各位一句鸡汤:每个Android程序员都是隐藏的灵魂画手,只是暂时被需求埋没了才华。从画好一个圆开始,逐步征服2D绘图、3D渲染、游戏开发……(此处脑补《海贼王》BGM)