【大前端】【iOS】iOS 使用 Objective-C 绘制几大常见布局(UIKit / Core Graphics 实战)


iOS 使用 Objective-C 绘制几大常见布局(UIKit / Core Graphics 实战)

在 iOS 开发中,大多数 UI 都是通过 AutoLayout、Frame 或 SwiftUI 构建的。但在一些性能敏感高度定制化 的场景(如图表、卡片背景、占位骨架、营销组件)中,直接绘制 UI 反而更高效、可控。

本文将系统讲解:
如何使用 Objective-C 手动绘制常见布局
每种布局的适用场景 + 完整示例代码


一、为什么还要用"绘制布局"?

适合使用绘制的场景

  • 📊 图表 / 统计视图(折线图、柱状图)

  • 🧩 高度定制化卡片背景

  • ⚡ 列表性能优化(减少 View 层级)

  • 🦴 Skeleton 骨架屏

  • 🎨 渐变 / 圆角 / 不规则形状

不适合的场景

  • 表单类 UI

  • 强交互控件(按钮 / 输入框)

  • 动态约束频繁变化的页面


二、基础知识:drawRect 与 Core Graphics

1️⃣ 自定义 View

复制代码
@interface CustomLayoutView : UIView
@end

@implementation CustomLayoutView

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef ctx = UIGraphicsGetCurrentContext();
}
@end

⚠️ drawRect: 由系统调用,不要手动调用

通过 setNeedsDisplay 触发重绘


三、常见布局一:矩形卡片布局(最常见)

适用场景

  • 首页卡片

  • 营销 Banner

  • 模块背景

示例效果

  • 圆角矩形

  • 阴影 / 描边

绘制代码

复制代码
- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGRect cardRect = CGRectInset(rect, 16, 16);
    UIBezierPath *path =
        [UIBezierPath bezierPathWithRoundedRect:cardRect
                                    cornerRadius:12];

    [[UIColor whiteColor] setFill];
    [path fill];

    [[UIColor lightGrayColor] setStroke];
    path.lineWidth = 1;
    [path stroke];
}

优点

  • 无子 View

  • 性能极高

  • 样式统一


四、常见布局二:九宫格布局(Grid)

适用场景

  • 功能入口

  • 九宫格菜单

  • 轻量展示页

绘制思路

  • 计算行 / 列

  • 循环绘制 cell

  • 可点击:结合 touchesBegan

示例代码

复制代码
- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    int column = 3;
    CGFloat padding = 10;
    CGFloat itemW = (rect.size.width - padding * (column + 1)) / column;
    CGFloat itemH = itemW;

    for (int i = 0; i < 9; i++) {
        int row = i / column;
        int col = i % column;

        CGFloat x = padding + col * (itemW + padding);
        CGFloat y = padding + row * (itemH + padding);

        CGRect itemRect = CGRectMake(x, y, itemW, itemH);
        UIBezierPath *path =
            [UIBezierPath bezierPathWithRoundedRect:itemRect cornerRadius:8];

        [[UIColor colorWithWhite:0.95 alpha:1] setFill];
        [path fill];
    }
}

五、常见布局三:列表布局(模拟 Table)

适用场景

  • 骨架屏

  • 轻量列表占位

  • 加载态 UI

绘制代码

复制代码
- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGFloat itemH = 60;
    int count = rect.size.height / itemH;

    for (int i = 0; i < count; i++) {
        CGRect rowRect = CGRectMake(16, i * itemH + 8,
                                    rect.size.width - 32, 44);

        UIBezierPath *path =
            [UIBezierPath bezierPathWithRoundedRect:rowRect cornerRadius:6];

        [[UIColor colorWithWhite:0.9 alpha:1] setFill];
        [path fill];
    }
}

📌 性能优势

UITableView + Skeleton View 更轻


六、常见布局四:分割线 & 虚线布局

普通分割线

复制代码
CGContextSetStrokeColorWithColor(ctx, [UIColor lightGrayColor].CGColor);
CGContextSetLineWidth(ctx, 0.5);
CGContextMoveToPoint(ctx, 16, y);
CGContextAddLineToPoint(ctx, rect.size.width - 16, y);
CGContextStrokePath(ctx);

虚线

复制代码
CGFloat dash[] = {4, 2};
CGContextSetLineDash(ctx, 0, dash, 2);

七、常见布局五:不规则布局(气泡 / 标签)

适用场景

  • 聊天气泡

  • 标签角标

  • 引导浮层

示例:气泡背景

复制代码
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10, 0)];
[path addLineToPoint:CGPointMake(rect.size.width - 10, 0)];
[path addQuadCurveToPoint:CGPointMake(rect.size.width, 10)
             controlPoint:CGPointMake(rect.size.width, 0)];
// ... 省略
[path closePath];

八、交互怎么做?(重点)

绘制 View 默认没有子控件,交互需自己处理:

复制代码
- (void)touchesBegan:(NSSet<UITouch *> *)touches
           withEvent:(UIEvent *)event {

    CGPoint point = [[touches anyObject] locationInView:self];

    if (CGRectContainsPoint(self.itemRects[index], point)) {
        NSLog(@"点击了第 %d 个", index);
    }
}

九、性能与注意事项

✅ 优点

  • 极少 View 层级

  • 内存占用低

  • 滚动流畅

⚠️ 注意事项

  • 避免频繁 setNeedsDisplay

  • 复杂动画建议用 CAShapeLayer

  • 文本多时结合 CoreText


十、总结

布局类型 是否推荐绘制
卡片背景 ✅ 强烈推荐
骨架屏 ✅ 推荐
图表 ✅ 必须
表单 ❌ 不推荐
输入控件 ❌ 不推荐
相关推荐
再学一点就睡3 小时前
前端网络实战手册:15个高频工作场景全解析
前端·网络协议
C_心欲无痕4 小时前
有限状态机在前端中的应用
前端·状态模式
C_心欲无痕4 小时前
前端基于 IntersectionObserver 更流畅的懒加载实现
前端
candyTong4 小时前
深入解析:AI 智能体(Agent)是如何解决问题的?
前端·agent·ai编程
柳杉4 小时前
建议收藏 | 2026年AI工具封神榜:从Sora到混元3D,生产力彻底爆发
前端·人工智能·后端
weixin_462446234 小时前
使用 Puppeteer 设置 Cookies 并实现自动化分页操作:前端实战教程
运维·前端·自动化
CheungChunChiu4 小时前
Linux 内核动态打印机制详解
android·linux·服务器·前端·ubuntu
GIS之路5 小时前
GDAL 创建矢量图层的两种方式
前端
小目标一个亿6 小时前
Windows平台Nginx配置web账号密码验证
linux·前端·nginx
rocky1916 小时前
网页版时钟
前端·javascript·html