iOS 自定义控件开发(上)
工作需要,最近在进行iOS方面的图表工作。找了很多第三方库都无法实现效果,所以决定自己写一个控件。
#0 目标
希望可以写一个通用的图表控件(仅针对此项目),虽然开发难度增大,但是可以学习到很多知识。并且控件使用简单,可以自适应大小,支持屏幕旋转。
#1 准备工作
- 网上各种查资料
- 研究了一下系统自带控件,全部基于UIView
- 开发过程中使用storyboard,在页面中加入一个View来控制大小,自定义控件放入此view中并且填充满,让程序可以自适应屏幕尺寸。
#2 开始自定义
创建自定义控件,继承自UIView。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // // LGChartView.h // // Created by Luna Gao on 15/10/29. // Copyright © 2015年 All rights reserved. // #import <UIKit/UIKit.h> @interface LGChartView : UIView - (instancetype)initWithParentView:(UIView*) view; @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | // // LGChartView.m // // Created by Luna Gao on 15/10/29. // Copyright © 2015年 All rights reserved. // #import "LGChartView.h" @implementation LGChartView UIView *parentView; - (instancetype)initWithParentView:(UIView*) view { parentView = view; return [ self init]; } - (instancetype)init { return [ self initWithFrame: CGRectZero]; } - (instancetype)initWithFrame:(CGRect)frame { frame = CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height); self = [ super initWithFrame:frame]; if ( self ) { self .backgroundColor = [UIColor clearColor]; self .autoresizesSubviews = YES ; self .autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; } return self ; } -( void )layoutSubviews { [ self setNeedsDisplay]; } - ( void )drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(context, 0.0f, 0.0f, 0.0f, 1); //线条颜色 CGContextMoveToPoint(context, CGRectGetMinX( self .frame), CGRectGetMaxY( self .frame) - 16); CGContextAddLineToPoint(context, CGRectGetMaxX( self .frame), CGRectGetMaxY( self .frame) - 16); CGContextStrokePath(context); CGContextSetLineWidth(context, 1.0); } @end |
其中initWithParentView方法将父View传入进来,通过父View的大小来确定我们自定义控件的大小。我对于此处感觉有点怪怪的,虽然是我想到的解决方案···
其中
1 2 | self .autoresizesSubviews = YES ; self .autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; |
这两句尤为重要,这两句代码保证了在页面横屏竖屏切换时,控件会随着屏幕中父View的大小改变而我们的自定义控件跟着改变。
下面这个方法
1 2 3 | -( void )layoutSubviews { [ self setNeedsDisplay]; } |
保证了在页面横屏竖屏切换时,自定义控件可以跟随刷新。
最后的drawRect方法,我将所有的绘制图形的功能全部交给了它。
#3 在controller中引用
这一步已经非常的简单了。
在storyboard创建一个ViewController,在其中放入一个UIView,这个UIView决定了自定义控件在界面中的显示位置和大小,并在其相关联的ChartViewController中获取。至此,storyboard的工作完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // // ChartViewController.h // // Created by Luna Gao on 15/10/29. // Copyright © 2015年 All rights reserved. // #import <UIKit/UIKit.h> #import "LGChartView.h" @interface ChartViewController : UIViewController @property (weak, nonatomic ) IBOutlet UIView *chartView; @end |
下一步,在此controller中引用我们写的自定义控件,并且将自定义控件的父类交给刚刚引用的UIView中。
1 2 3 4 5 6 | - ( void )viewDidLoad { [ super viewDidLoad]; LGChartView *chartControl = [[LGChartView alloc] initWithParentView: self .chartView]; [ self .chartView addSubview:chartControl]; } |
剩下的,就什么都不用搞了···
直接跑项目看效果即可。至此,自定义控件的demo就完成了,剩下的工作就是逐步完善自定义控件,在其中加入委托等等等等。
#4 遇到的一些报错和坑
1. 自定义控件出现所绘制内容被拉伸,模糊等情况,请检查是否在drawRect此方法中修改了自定义控件的frame.size的大小,当然,也有可能是由于下面一条引起的。
2. 不要在自定义控件中的drawRect中调用[self setNeedsDisplay]方法,之前出现了众多奇奇葩葩的报错和问题,就是因为调用了这玩意···重要的事情说3便
3. 不要在自定义控件中的drawRect中调用[self setNeedsDisplay]方法,之前出现了众多奇奇葩葩的报错和问题,就是因为调用了这玩意···重要的事情说3便
4. 不要在自定义控件中的drawRect中调用[self setNeedsDisplay]方法,之前出现了众多奇奇葩葩的报错和问题,就是因为调用了这玩意···重要的事情说3便
#5 其他
如有问题,或不正确的地方,或有更好的实现方法,请不要吝啬,在下面留言吧···么么哒···
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?