【大前端】【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 小时前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
别动我齐刘海4 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
志尊宝5 小时前
Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案
前端·css·笔记·vue·html·前端开发·软件开发
刘发财5 小时前
前端如何生成10000页PDF文件?
前端·javascript·开源
A接拉起0076 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户11481867894846 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界6 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
葡萄城技术团队6 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一6 小时前
优化修整算法
前端·javascript·算法
weifont7 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化