无限互联iOS开发之KYCircleMenu框架
- 格式:doc
- 大小:414.04 KB
- 文档页数:16
无限互联ios开发之mknetworkkitmknetworkkit 结合了ASIHTTPRequest和AFNetworking这两个类库的优点,也增加了自己的一点新特性,它使用像AFNetworking这么简单,而功能像ASIHTTPRequest(已经停止维护)那么强大.下载地址: https:///MugunthKumar/MKNetworkKit/将下载包中的MKNetWorkKit文件夹拖到你新建的工程中。
添加:SystemConfiguration.framework,CFNetwork.framework,Security.framework和ImageIO.framework。
目前网上的介绍全都是旧版的MKNetworkKit, 新版的MKNetworkKit需要ImageIO.framework, 否则会报错.首先介绍这个类库怎么用:get请求:[objc]view plaincopyprint?1.NSDictionary *dic = [NSDictionarydictionaryWithObject:@"2.00luajUCkXYcfDc0508709c0avmFCE"forKey:@"access_token"];2.MKNetworkEngine *engine = [[MKNetworkEngine alloc]init];3.MKNetworkOperation *operation = [engineoperationWithURLString:@"https:///2/statuses/home_timeline.json" params:dic httpMethod:@"GET"];4.[operation addCompletionHandler:^(MKNetworkOperation*completedOperation) {5.NSLog(@"%@",[completedOperation responseString]);6.} errorHandler:^(MKNetworkOperation *completedOperation,NSError *error) {7.NSLog(@"%@",[error localizedDescription]);8.}];9.10.[engine enqueueOperation:operation];首先床架引擎对象,在调用(MKNetworkOperation*) operationWithURLString:(NSString*) urlString params:(NSDictionary*) bodyhttpMethod:(NSString*)method这个方法,此方法返回一个mknetworkOperation对象,只要将此对象加入队列中即可。
【无限互联】ios开发之AFNetWorking一、介绍:AFNetWorking是IOS重要的框架之一,用于实现访问服务器,请求网络数据,上传数据等功能。
二、原理:三、使用:在使用AFNetWorking之前,需要去下载这个框架,个人推荐去/官网下载,目前最新版的是2.4.1版本。
下载之后打开,将里面的AFNetWorking 文件夹拷贝至你的程序中并且在在Supporting Files文件夹中添加以下代码:#import "AFNetworking.h"如图所示:四、实现:代码如下// 1.创建链接对象NSString *netString = _netText.text;// NSString *urlString = @"/";NSString *urlString = [NSStringstringWithFormat:@"http://%@/",netString];// 2.构造request// 1)请求参数的格式化对象AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializerserializer];// 2)创建requestNSMutableURLRequest *request = [serializerrequestWithMethod:@"GET"URLString:urlStringparameters:nilerror:nil];// 3.构造链接对象AFHTTPRequestOperation *operation = [[AFHTTPRequestOperationalloc] initWithRequest:request];// 4.设置返回数据类型为json// operation.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingMutableContainers];// 设置返回数据类型为xml// operation.responseSerializer = [AFXMLParserResponseSerializer serializer];// 5.创建调用成功或者失败的block[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation,id responseObject) {NSString *string = [[NSStringalloc]initWithData:responseObjectencoding:NSUTF8StringEncoding]; _textField.text = string;NSLog(@"欧耶我们成功了,responseObject=%@",string);} failure:^(AFHTTPRequestOperation *operation,NSError *error) { NSLog(@"天啦我们失败了,error=%@",error);}];// 6.添加到主进程queue = [[NSOperationQueuealloc] init];[queue addOperation:operation];[self.viewendEditing:YES];。
无限互联iOS视频教程详细介绍无限互联官网:淘宝购买链接:/item.htm?spm=a230r.1.14.104.27qCIC&id=173********&ns=1#detail 一、OC部分第一、二章(12课时)OC基础语法第三章(7课时)OC面向对象编程第四章(5课时)数组、字典和集合第五章(4课时)类的扩展——类目和协议第六章(6课时)内存管理第七章(3课时)文件管理第八章(8课时)复制对象、归档与单例第九章(6课时)KVC、KVO、谓词与通知二、UI基础部分第一章(10课时)iPhone开发入门第二章(7课时)窗口与视图详解(UIWindow与UIView详解)第三章(9课时)视图控制器的基本概念和用法第四章(12课时)常用UI控件和常用类第五章(10课时)导航控制器基本概念和用法第六章(10课时)分栏控制器的基本概念和用法三、UI高级部分第七课表视图一(13课时)1.表视图的基本概念2.创建基本表格实例13.表视图的常用属性和方法4.设置表视图属性实例25.表视图委托方法和数据源方法6.委托方法实例3-17.委托方法实例3-28.单元格的基本概念9.单元格的几种样式,如何修改单元格背景10.单选TableView实例511.计算表视图单元格的高度12.索引表视图实例713.作业第八课表视图二(10课时)1.表视图控制器的基本概念2.单元格的常用属性3.定制单元格的方式概念4.第一种定制cell的方式15.第二种定制cell的方式26.第三种定制cell的方式37.编辑表视图的基本概念8.编辑表视图的基本用法9.过滤表格的实例310.作业第九课触摸和手势(6课时)1.触摸的基本概念2.单击双击、移动视图3.捏合手势4.事件的传递的机制5.事件的传递演示6.手势识别器的使用第十课UIScrollview概念和用法(6课时)1.UIScrollview基本属性用法2.UIScrollView常用代理方法3.ScrollView和PageControl4.单张图片缩放5.实现简单的相册功能6.作业第十一课Block语法的使用(5课时)1. block语法的详解和使用2.block引用外部变量的机制,block作为参数传递调用3.详解block的内存管理4.block应用5.block回顾第十二课PickerView的使用(5课时)1.PickerView控件的使用讲解2.DatePicker控件的使用讲解3.简单访问网络资源图片,讲解如何将图片保存至相册4.讲解如何使用相册选取图片,使用摄像头拍照5.相册、pickerView使用的回顾第十三课iPad控件(3课时)1.iPad中分割窗口的讲解使用2.iPad中浮动窗口的讲解使用3.iPad中模态视图的讲解使用第十四课iOS动画和绘图(5课时)1.UIView基础动画讲解使用2.视图切换内置的几种动画效果,动画中的block语法的使用3.使用Transition动画效果4.第三方开源3D动画效果的讲解使用5.视图的绘制与核心动画的讲解使用第十五课多媒体(4课时)1.使用AVAudioPlayer播放本地音乐文件2.使用AVPlayer播放网络流媒体音乐3.如何使用后台音乐播放4.视频播放的讲解使用第十六课网络与多线程一(7课时)1.讲解多线程的概念与使用2.详细讲解OC中多种多线程的使用方式3.课堂练习,使用多线程加载网络图片4.讲解NSTimer如何在多线程的使用5.讲解HTTP协议的概念6.讲解NSURLConnection异步和同步请求网络7.使用NSURLConnection封装通用的网络请求工具类第十七课网络与多线程二(5课时)1.讲解开源网络请求库ASI如何请求网络资源2.讲解ASI缓存策略的使用3.讲解ASI的文件下载功能,下载进度监听4.讲解ASI的网络请求队列5.ASI的其他特性第十八课位置与地图(5课时)1.讲解如何使用位置服务,获取当前设备的经纬坐标2.讲解3种位置反编码的方式3.讲解地图的使用4.讲解如何往地图上添加大头针标注视图5. 讲解如何往地图上添加大头针标注视图第十九课SQLite数据库(8课时)1.数据库的介绍2.基础的SQL语句3.讲解使用SQLite创建表4.讲解使用SQLite插入数据5.讲解使用SQLite查询数据6.封装数据库操作基类7.实现操作用户数据管理类8.实现操作用户列表界面,完成对用户的添加和查询第二十课真机调试(6课时)1、真机调试流程概述2、请求开发证书3、注册设备4、创建App ID5、安装profile文件与真机调试6.真机调试注意事项第二十一课本地通知与远程推送(6课时)1.推送通知流程2.推送通知要求、内容以及局限3.制作证书4.NotificationDemo实例5.完善NotificationDemo实例6.制作PEM证书和小结视频截图【微博2.0更新内容】1.微博列表的优化,微博高度做缓存,链接解析使用多线程2.微博图片点击放大,显示加载进度3.DDProgressView控件的使用,显示进度4.BlocksKit开源框架的集成与介绍使用5.导航控制器实现时下流行的抽屉式导航,提高用户体验6.内存警告的处理7.iphone5的适配讲解8.讲解延长至14天,讲解更加细致【微博2.0内容大纲】第一天上午1.iOS产品的开发流程介绍2.介绍新浪微博开放平台、移动应用如何接入开发平台、如何创建移动应用3. OAthu认证的详细介绍,微博的相关术语下午4.介绍官方的微博功能、weico客户端的功能,我们完成之后的微博项目效果5.创建项目,搭建开发环境、添加第三方类库、工具类6.分析整体的视图结构、创建各个模块相关的控制器7.集成DDMenu左右菜单效果8.初始化子控制器、自定义tabbar工具栏9.介绍新浪微博SDK的使用10.今日作业:集成新浪微博SDK到项目中第二天上午1.集成微博SDK到项目中,测试是否可以访问微博的开发接口2.分析主题切换的实现思路3.实现主题管家类4.实现主题按钮ThemeButton类下午5.实现导航栏背景的主题切换6.实现主题图片视图ThemeImageView类7.重构、使用UIFactory工厂类创建主题视图,在控制器基类里创建返回按钮8.今日作业:考虑如何实现主题Label,不同的主题对应不同的字体颜色第三天上午1.分析主题Label的实现思路,定义字体配置文件2.创建实现主题字体ThemeLabel3.介绍学习RTLabel的使用4.查看微博列表接口说明,介绍返回json字段的含义,访问微博列表接口。
继续介绍一个有用的TableView中全选单元格的例子,里面的方法可以用在阅读器中用户对阅读内容来源的选择上,如图所示:核心代码如下:[objc]view plaincopy1.- (void)viewDidLoad2.{3. [super viewDidLoad];4.5.//创建表视图 _table6. _table = [[UITableView alloc]initWithFrame:CGRectMake(0, 64, 320, 500) style:UITableViewStylePlain];7. _table.delegate = self;8. _table.dataSource = self;9. [self.view addSubview:_table];10.11.//将字典 "NO"-> @"checked" 装入可变数组中,来控制单元格左边对勾视图12. _contacts = [NSMutableArray array];13.for (int i = 0; i <10; i++) {14.NSMutableDictionary *dic = [NSMutableDictionary dictionary];15. [dic setValue:@"NO" forKey:@"checked"];16. [_contacts addObject:dic];17. }18.19.//创建屏幕左上方的"全选"按钮20. _button = [UIButton buttonWithType:UIButtonTypeRoundedRect];21. [_button setTitle:@"全选" forState:UIControlStateNormal];22. _button.frame = CGRectMake(10, 10, 100, 50);23. [_button addTarget:self action:@selector(allSelect:) forControlEvents:UIControlEventTouchUpInside];24. [self.view addSubview:_button];25.}[objc]view plaincopy1.// 全选按钮的触发事件2.- (void)allSelect:(UIButton*)sender{3.4.//将表视图的所有的单元格放在数组里5.NSArray *anArrayOfIndexPath = [NSArray arrayWithArray:[_table indexPathsForVisibleRows]];6.7.for (int i = 0; i < [anArrayOfIndexPath count]; i++) {8.9.// 得到表视图的indexPath10.NSIndexPath *indexPath= [anArrayOfIndexPath objectAtIndex:i];11.//创建每个单元格,12.LTableViewCell *cell = (LTableViewCell*)[_table cellForRowAtIndexPath:indexPath];13. NSUInteger row = [indexPath row];14.NSMutableDictionary *dic = [_contacts objectAtIndex:row];15.16.// 判断当前按钮的状态是全选还是取消,设置不同的标记17.if ([[[(UIButton*)sender titleLabel] text] isEqualToString:@"全选"]) {18. [dic setObject:@"YES" forKey:@"checked"];19. [cell setChecked:YES];20. }else {21. [dic setObject:@"NO" forKey:@"checked"];22. [cell setChecked:NO];23. }24. }25.26.// 两种状态的切换27.if ([[[(UIButton*)sender titleLabel] text] isEqualToString:@"全选"]){28.for (NSDictionary *dic in _contacts) {29. [dic setValue:@"YES" forKey:@"checked"];30. }31.32. [(UIButton*)sender setTitle:@"取消" forState:UIControlStateNormal];33. }34.35.else{36.for (NSDictionary *dic in _contacts) {37. [dic setValue:@"NO" forKey:@"checked"];38. }39. [(UIButton*)sender setTitle:@"全选" forState:UIControlStateNormal];40. }41.}[objc]view plaincopy1.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{2.static NSString * identifier = @"Cell";3.4.// 创建单元格5.LTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];6.if (cell == nil) {7. cell = [[LTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];8. }9. NSUInteger row = [indexPath row];10.11.NSMutableDictionary *dic = [_contacts objectAtIndex:row];12.13.14.if ([[dic objectForKey:@"checked"] isEqualToString:@"NO"]) {15. [dic setObject:@"NO" forKey:@"checked"];16. [cell setChecked:NO];17.18. }else {19. [dic setObject:@"YES" forKey:@"checked"];20. [cell setChecked:YES];21. }22.return cell;23.}[objc]view plaincopy1.- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath2.{3. [tableView deselectRowAtIndexPath:indexPath animated:YES];4.5.LTableViewCell *cell = (LTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];6.7. NSUInteger row = [indexPath row];8.9.NSMutableDictionary *dic = [_contacts objectAtIndex:row];10.11.// 创建单元格左边的打钩视图12.if ([[dic objectForKey:@"checked"] isEqualToString:@"NO"]) {13. [dic setObject:@"YES" forKey:@"checked"];14. [cell setChecked:YES];15. }else {16. [dic setObject:@"NO" forKey:@"checked"];17. [cell setChecked:NO];18. }19.}在LTableViewCell中[objc]view plaincopy1.// 用 checked 来判断是否加上对勾视图2.- (void)setChecked:(BOOL)checked{3.4.5.if (checked)6. {7. m_checkImageView.image = [UIImage imageNamed:@"Selected.png"];8.self.backgroundView.backgroundColor = [UIColor colorWithRed:223.0/255.0 green:230.0/255.0 blue:250.0/255.0 alpha:1.0];9. }10.else11. {12. m_checkImageView.image = [UIImage imageNamed:@"Unselected.png"];13.self.backgroundView.backgroundColor = [UIColor whiteColor];14. }15. m_checked = checked;16.17.18.}代码的逻辑简单,通用性强,核心就是用字典来控制对勾视图的显示,对我们以后的视图设计有参考价值。
iOS SDK 悬浮球实现原理一、悬浮球介绍悬浮球是一种常见的用户界面组件,通常出现在移动应用程序中。
它是一个小型的圆形图标,用户可以通过点击它来展开一系列的操作按钮或菜单。
悬浮球的出现大大提高了用户操作的便捷性,因此受到了广泛的欢迎。
在iOS开发中,悬浮球的实现通常依赖于使用iOS SDK进行开发。
下面将介绍一下iOS SDK悬浮球的实现原理。
二、 iOS SDK悬浮球实现原理在iOS开发中,要实现一个悬浮球,通常需要完成以下几个步骤:1. 创建悬浮球视图首先需要创建一个悬浮球的视图,这个视图通常是一个圆形的按钮,可以使用UIButton或者自定义的UIView来实现。
这个视图会被添加到应用程序的窗口上,从而可以显示在屏幕的任意位置。
2. 添加手势为了实现悬浮球的拖动和点击功能,需要为悬浮球视图添加手势识别。
通过添加拖动手势和点击手势,可以实现用户对悬浮球视图的操作。
3. 设置悬浮球的位置在应用程序的窗口上添加悬浮球视图后,需要设置它在屏幕上的初始位置。
通常悬浮球会默认显示在屏幕的右下角,但也可以根据需求进行自定义位置的设置。
4. 添加悬浮菜单点击悬浮球后通常会展开一个菜单,包含一系列的操作按钮或者菜单项。
为了实现这个功能,需要在悬浮球视图的点击事件中添加展开菜单的逻辑。
菜单可以使用UITableView或者UICollectionView来实现,也可以使用自定义的视图来进行展示。
5. 实现悬浮球的拖动悬浮球通常允许用户进行拖动,从而改变它的位置。
为了实现这个功能,需要在悬浮球视图上添加拖动手势,并在手势的回调函数中实现悬浮球位置的更新。
6. 处理悬浮球的显示和隐藏在实际的应用中,通常需要根据一定的逻辑来控制悬浮球的显示和隐藏。
这可能涉及到用户的操作状态、页面的滚动状态等。
因此需要在适当的时机对悬浮球进行显示和隐藏的控制。
三、开发技巧与注意事项在开发iOS SDK悬浮球的过程中,有一些技巧和注意事项需要牢记在心:1. 性能优化悬浮球通常会始终显示在屏幕上,因此需要注意优化其性能,避免对应用程序的性能产生不良影响。
【无线互联】iOS开发第三框架之导航栏篇XHYScrollingNavBarVC 和NavigationMenu-master集成。
XHYScrollingNavBarVC 和NavigationMenu-master集成此框架结合了XHYScrollingNavBarVC 和 NavigationMenu-master,拥有如下功能和特点1、支持UIWebView以及UITableView和scrollView。
2、当视图上拉时,导航栏隐藏,避免了导航栏占用了多余的空间。
3、当视图下拉时,导航栏显示,导航栏功能出现可以使用。
4、在导航栏标题改为了一个按钮,点击打开(或关闭)菜单按钮。
具体用法和实现。
注意:要设置self.navigationController.navigationBar.barTintColor 属性导航栏的颜色属性不会被失真。
2.将对应的scrollView、tableview、WebView:调用方法[self followRollingScrollView:self.webView];//可以是scrollView或者tableview和WebView。
[self followRollingScrollView:_tabelView];对应属性如下:@property (weak, nonatomic) UIView *scrollView; //添加在控制器上的子视图@property (retain,nonatomic)UIPanGestureRecognizer *panGesture; //平滑手指@property (retain,nonatomic)UIView *overLay; //添加在导航栏上的覆盖视图@property (assign,nonatomic)BOOL isHidden; //记录导航栏的隐藏3.设置标题处的菜单按钮:将需要添加的菜单名字装在一个数组中赋值给self.items。
vue-circle-menu漂亮的圆形菜单废话不多说,先上图⼀, 安装npm install vue-circle-menu --save⼆, 引⼊若作为全局组件使⽤//main.js中import Vue from 'vue'import CircleMenu from 'vue-circle-menu'ponent('CircleMenu', CircleMenu)若作为局部组件//在某个组件中import CircleMenu from 'vue-circle-menu'export default {components: {CircleMenu}}三, 简单的例⼦<circle-menu type="middle" :number="4" animate="animated jello" mask='white' circle><button type="button" slot="item_btn"></button><a slot="item_1" class="fa fa-twitter fa-lg"></a><a slot="item_2" class="fa fa-weixin fa-lg"></a><a slot="item_3" class="fa fa-weibo fa-lg"></a><a slot="item_4" class="fa fa-github fa-lg"></a></circle-menu><circle-menu type="top" :number="3" mask='black' btn colors="[ 'rgb(255, 255, 102)', '#A7425C', '#FFE26F', 'F3825F', '#F19584' ]"> <a slot="item_1" class="fa fa-twitter fa-lg"></a><a slot="item_2" class="fa fa-weixin fa-lg"></a><a slot="item_3" class="fa fa-weibo fa-lg"></a></circle-menu>四, 组件参数名称类型默认值说明type String-菜单的类型,⽀持top,bottom,left,right,middle,middle-around number Number-菜单项的数量,⽀持2-5个animate String⾃定义的过渡动画mask String-是否显⽰遮罩,以及遮罩的颜⾊circle Boolean-菜单按钮是矩形或者圆形btn Boolean-菜单按钮是否显⽰按钮样式colors Array-每个菜单按钮的颜⾊Demo:。
【无限互联】IOS开发之下拉刷新控件本节要点:1.掌握下拉刷新、上拉加载控件的使用2.大概了解实现原理控件的使用:1.添加头部控件的方法[self.tableView addHeaderWithTarget:self action:@selector(headerRereshing)];或者[self.tableView addHeaderWithCallback:^{ }];2.添加尾部控件的方法[self.tableView addFooterWithTarget:self action:@selector(footerRereshing)];或者[self.tableView addFooterWithCallback:^{ }];3. 可以在MJRefreshConst.h和MJRefreshConst.m文件中自定义显示的文字内容和文字颜色4.自动进入刷新状态1> [self.tableView headerBeginRefreshing];2> [self.tableView footerBeginRefreshing];5.结束刷新1> [self.tableView headerEndRefreshing];2> [self.tableView footerEndRefreshing];实现原理:1.通过调用[self.tableView addHeaderWithTarget:self action:@selector(headerRereshing)];这个方法跳转到下面代码,MJRefreshHeaderView调用它的类方法header来创建一个新的header。
- (void)addHeaderWithTarget:(id)target action:(SEL)action{// 1.创建新的headerif (!self.header) {MJRefreshHeaderView *header = [MJRefreshHeaderView header];[self addSubview:header];self.header = header;}// 2.设置目标和回调方法self.header.beginRefreshingTaget = target;self.header.beginRefreshingAction = action;}2.控制控件的刷新状态,定义了一个枚举typedef enum {MJRefreshStatePulling =1,//松开就可以进行刷新的状态MJRefreshStateNormal =2,//普通状态MJRefreshStateRefreshing =3,//正在刷新中的状态MJRefreshStateWillRefreshing =4} MJRefreshState;3.改变枚举状态- (void)adjustStateWithContentOffset{// 当前的contentOffsetCGFloat currentOffsetY =self.scrollView.mj_contentOffsetY;// 头部控件刚好出现的offsetYCGFloat happenOffsetY = -self.scrollViewOriginalInset.top;//如果是向上滚动到看不见头部控件,直接返回if (currentOffsetY >= happenOffsetY)return;if (self.scrollView.isDragging) {// 普通和即将刷新的临界点CGFloat normal2pullingOffsetY = happenOffsetY -self.mj_height;if (self.state ==MJRefreshStateNormal && currentOffsetY < normal2pullingOffsetY) { //转为即将刷新状态self.state =MJRefreshStatePulling;}elseif (self.state ==MJRefreshStatePulling && currentOffsetY >= normal2pullingOffsetY) {//转为普通状态self.state =MJRefreshStateNormal;}} elseif (self.state ==MJRefreshStatePulling) {//即将刷新&&手松开//开始刷新self.state =MJRefreshStateRefreshing;}}4.当MJRefreshState的状态改变时通过一个switch语句,根据状态执行不同的操作switch (state) {case MJRefreshStateNormal://普通状态{if (self.state == MJRefreshStateRefreshing) {[UIView animateWithDuration:MJRefreshSlowAnimationDuration *0.6animations:^{self.activityView.alpha =0.0;}completion:^(BOOL finished) {//停止转圈圈[self.activityView stopAnimating];//恢复alphaself.activityView.alpha =1.0;}];dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(MJRefreshSlowAnimationDuration *NSEC_PER_SEC)),dispatch_get_main_queue(), ^{ //再次设置回normal_state =MJRefreshStatePulling;self.state =MJRefreshStateNormal;});//直接返回return;}else {//显示箭头self.arrowImage.hidden =NO;//停止转圈圈[self.activityView stopAnimating];}break;}case MJRefreshStatePulling:break;case MJRefreshStateRefreshing:{//开始转圈圈[self.activityView startAnimating];//隐藏箭头self.arrowImage.hidden = YES;//回调if ([self.beginRefreshingTaget respondsToSelector:self.beginRefreshingAction]) { objc_msgSend(self.beginRefreshingTaget,self.beginRefreshingAction,self);}if (self.beginRefreshingCallback) {self.beginRefreshingCallback();}break;}default:break;}5.改变文字的内容- (void)settingLabelText{switch (self.state) {case MJRefreshStateNormal://设置文字self.statusLabel.text =self.pullToRefreshText;break;case MJRefreshStatePulling://设置文字self.statusLabel.text =self.releaseToRefreshText;break;case MJRefreshStateRefreshing://设置文字self.statusLabel.text =self.refreshingText; break;default:break;}}。
iOS 系统框架概述iOS 操作系统是苹果为公司移动设备提供的操作系统,为方便应用开发者采用了先进的设计模式。
采用了经典的MVC 设计模式和框架模式。
本篇文章我们主要关注iOS 系统提供的框架,对MVC 设计模式不做过多的描述。
我们通常称呼iOS的框架为Cocoa Touch框架,Cocoa Touch 是一个框架的集合,里面包含了众多的子框架。
每一个子框架都是一个目录,包含了共享资源库,用于访问该资源库中储存的代码的头文件,以及图像、声音文件等其他资源,共享资源库定义应用程序可以调用的函数和方法。
框架中的类相互依赖构成一个整体,提供完善的某一方面的服务或解决方案,多个框架一起实现整个应用程序的结构。
由于应用程序的结构是通用的,开发者通过框架提供的函数和方法,做细致个性化的处理,从而满足不同应用的不同需求。
开发一个应用程序就是将需求细致化的代码插入到框架提供的设计中来组合成一个整体完成最终的应用设计。
框架的结构是泛型结构,为应用程序提供一个模板。
就像开发商开发好的毛坯房,你需要用应用程序代码来布置不同的家具地板门窗,这才让不同的房屋有不同的格调,不同的幸福。
当然,有时候,做装修的时候你需要简单的改装你的房屋,但承重墙是不能改造的。
就像我们之前说的,多个框架起实现了整个应用程序的结构,我们必须接受它所定义好的应用程序结构,设计的时候让我们的应用适合该结构。
在Android 开发中,采用模板模式来实现应用程序的一些特性行为,Android 提供了Activity,Service,Content providers,Broadcastreceivers 四大组件默认功能,应用通过继承这些组件根据需要覆盖组件的一些方法来完成应用程序开发。
在iOS 中则采用代理和协议模式来实现应用的特性行为。
例如Cocoa Touch 框架集合中的UIKit 框架的UIApplication 对象,它负责整个应用程序生命周期的事件分发。
【无线互联】IOS开发之KYCircleMenu框架KYCircleMenu框架的功能实现一种弹出菜单按钮,用户点击主按钮,会依次弹出一圈按钮,围绕主按钮圆环状排列,按钮数自定,但在此封装的类中,按钮数至多为6个。
点击其中一个弹出按钮,将通过动画进入到第二个界面,在第二个界面中,点击返回按钮通过动画返回到菜单界面中。
再次点击主按钮,弹出的按钮将收进主按钮中。
KYCircleMenu框架的实现原理1、自定义初始化为KYCircleMenu,通过外部将一些属性值传递进来,通过这些值计算出三角形的斜边、button的原点[html]view plaincopy1.- (instancetype)initWithButtonCount:(NSInteger)buttonCount2. menuSize:(CGFloat)menuSize3. buttonSize:(CGFloat)buttonSize4. buttonImageNameFormat:(NSString *)buttonImageNameFormat5. centerButtonSize:(CGFloat)centerButtonSize6. centerButtonImageName:(NSString *)centerButtonImageName7. centerButtonBackgroundImageName:(NSString *)centerButtonBackgroundImageName8.{9. if (self = [self init]) {10.buttonCount_ = buttonCount;11.menuSize_ = menuSize;12.buttonSize_ = buttonSize;13.buttonImageNameFormat_ = buttonImageNameFormat;14.centerButtonSize_ = centerButtonSize;15.centerButtonImageName_ = centerButtonImageName;16.centerButtonBackgroundImageName_ = centerButtonBackgroundImageName;17.18. // Defualt value for triangle hypotenuse 三角形19.defaultTriangleHypotenuse_ = (menuSize - buttonSize) * .5f; //三角形的斜边20.minBounceOfTriangleHypotenuse_ = defaultTriangleHypotenuse_ - 12.f;21.maxBounceOfTriangleHypotenuse_ = defaultTriangleHypotenuse_ + 12.f;22.maxTriangleHypotenuse_ = kKYCircleMenuViewHeight * .5f; //三角形的最大斜边23.24. // Buttons' origin frame 原点25. CGFloat originX = (menuSize_ - centerButtonSize_) * .5f;26.buttonOriginFrame_ =27. (CGRect){{originX, originX}, {centerButtonSize_, centerButtonSize_}};28. }29. return self;30.}2、在加载视图(loadView)中,计算出self.view的frame; 在计算self.view 的高度时,还判断了当前控制器是否隐藏了导航栏,如果隐藏了,则此视图的高度就为整个屏幕的高度,否则,就要减去导航栏的高度[html]view plaincopy1.- (void)loadView2.{3. CGFloat viewHeight =4. (self.navigationController.isNavigationBarHidden5. ? kKYCircleMenuViewHeight : kKYCircleMenuViewHeight - kKYCircleMenuNavigationBarHeight);6. CGRect frame = CGRectMake(0.f, 0.f, kKYCircleMenuViewWidth, viewHeight);7. UIView * view = [[UIView alloc] initWithFrame:frame];8.self.view = view;9.}3、在viewDidLoad方法中,作了以下操作<1>设置menu_视图,这个用来装载button菜单按钮的<2>根据buttonCount_外部传进来的值来确定button菜单按钮的个数,来创建button,并将这些button全都叠放在menu_视图的中间<3>并创建了中间的主按钮centerButton,用来控制是否显示菜单按钮,将centerButton添加到了当前视图的正中间,与菜单按钮的原始frame重叠<4>监听了菜单按钮关闭的通知[html]view plaincopy1.- (void)viewDidLoad2.{3. [super viewDidLoad];4.5. // Constants6. CGFloat viewHeight = CGRectGetHeight(self.view.frame);7. CGFloat viewWidth = CGRectGetWidth(self.view.frame);8.9. //菜单视图的frama10. CGRect centerMenuFrame =11.CGRectMake((viewWidth - menuSize_) * .5f, (viewHeight - menuSize_) * .5f, menuSize_, menuSize_);12. //menu_指菜单视图13.menu_ = [[UIView alloc] initWithFrame:centerMenuFrame];14. [menu_ setAlpha:0.f];15. [self.view addSubview:menu_];16.17. // Add buttons to |ballMenu_|, set it's origin frame to center18. //buttonCount_ 周围菜单按钮的个数19. NSString * imageName = nil;20. for (int i = 1; i <= buttonCount_; ++i) {21. UIButton * button = [[UIButton alloc] initWithFrame:buttonOriginFrame_];22. [button setOpaque:NO]; //NO 设置控件透明, YES 设置控件不透明,默认为YES23. [button setTag:i];24.imageName = [NSString stringWithFormat:self.buttonImageNameFormat, button.tag];25. [button setImage:[UIImage imageNamed:imageName]26. forState:UIControlStateNormal];27. [button addTarget:self action:@selector(runButtonActions:) forControlEvents:UIControlEventTouchUpInside];28. [self.menu addSubview:button];29. }30.31. // Main Button32. CGRect mainButtonFrame =33.CGRectMake((CGRectGetWidth(self.view.frame) - centerButtonSize_) * .5f,34. (CGRectGetHeight(self.view.frame) - centerButtonSize_) * .5f,35. centerButtonSize_, centerButtonSize_);36.37.centerButton_ = [[UIButton alloc] initWithFrame:mainButtonFrame];38. [centerButton_ setBackgroundImage:[UIImage imageNamed:self.centerButtonBackgroundImageName]39. forState:UIControlStateNormal];40. [centerButton_ setImage:[UIImage imageNamed:self.centerButtonImageName]41. forState:UIControlStateNormal];42. [centerButton_ addTarget:self43. action:@selector(_toggle:)44. forControlEvents:UIControlEventTouchUpInside];45. [self.view addSubview:centerButton_];46.47. // Setup notification observer48. //监听关闭menu_视图的通知49. [self _setupNotificationObserver];50.}4、在viewWillAppear视图将要显示时,隐藏导航栏,并判断它的子视图是否按下按钮,如果是则将菜单通过recoverToNormalStatus方法将其恢复到原始的位置由于此处使用的是ios7,所以当我们隐藏导航栏时,状态栏也会跟着隐藏,如果是ios6,则状态栏不会隐藏,所以应该进行版本的判断,对其做出相应的处理,则不会出现此处不兼容的情况(此处我作了相应的修改,代码如下:)[html]view plaincopy1.- (id)init2.{3. if (self = [super init]) {4.isInProcessing_ = NO;5.isOpening_ = NO;6.isClosed_ = YES;7.shouldRecoverToNormalStatusWhenViewWillAppear_ = NO;8.#ifndef KY_CIRCLEMENU_WITH_NAVIGATIONBAR9.10. //隐藏导航栏11. if (ios7) {12. [self setNeedsStatusBarAppearanceUpdate];13. }14. else {15.16. [[UIApplication sharedApplication] setStatusBarHidden:YES];17. }18. [self.navigationController setNavigationBarHidden:YES];19.#endif20. }21. return self;22.}到此时,视图已经显示出来,其效果为5、当我们点击主按钮centerButton,则会触发此按钮的事件[html]view plaincopy1.//循环切换菜单(关闭、打开)2.- (void)_toggle:(id)sender3.{4. (isClosed_ ? [self open] : [self _close:nil]);5.}通过此方法,循环切换菜单(关闭、打开)因为是第一次触发此按钮,isClosed_的初始值为YES,则会调用open方法6、open方法:此方法是用来打开菜单视图<1>通过动画效果来打开菜单视图,通过传递不同的三角形斜边的值来实现缩放的动画效果<2>通过调用_updateButtonsLayoutWithTriangleHypotenuse,将三角形的斜边值传递给此方法来改变菜单按钮的frame,实现过程:_updateButtonsLayoutWithTriangleHypotenuse根据三角形斜边的值来更新按钮的布局,通过三角函数计算出各个按钮的x、y坐标,将point值以及按钮的tag值传递给_setButtonWithTag:origin:此方法,<3>_setButtonWithTag:origin:此方法的作用:根据tag值取出menu视图中的button,再根据CGPoint设置其frame[html]view plaincopy1.- (void)open2.{3. if (isOpening_) return;4.5.isInProcessing_ = YES;6. // Show buttons with animation7. [UIView animateWithDuration:.3f8. delay:0.f9. options:UIViewAnimationCurveEaseInOut10. animations:^{11. //将menu视图透明度设为112. [self.menu setAlpha:1.f];13. // Compute buttons' frame and set for them, based on |buttonCount|14. //计算按钮的frame15. [self _updateButtonsLayoutWithTriangleHypotenuse:maxBounceOfTriangleHypotenuse_];16. }17. completion:^(BOOL finished) {18. [UIView animateWithDuration:.1f19. delay:0.f20. options:UIViewAnimationCurveEaseInOut21. animations:^{22. [self _updateButtonsLayoutWithTriangleHypotenuse:defaultTriangleHypotenuse_];23. }24. completion:^(BOOL finished) {25.isOpening_ = YES;26.isClosed_ = NO;27.isInProcessing_ = NO;28. }];29. }];30.}[html]view plaincopy1.- (void)_updateButtonsLayoutWithTriangleHypotenuse:(CGFloat)triangleHypotenuse2.{3. //4. // Triangle Values for Buttons' Position5. //6. // /| a: triangleA = c * cos(x)7. // c / | b b: triangleB = c * sin(x)8. // /)x| c: triangleHypotenuse9. // ----- x: degree10. // a11. //12. //通过设置按钮中心点来来更新按钮的布局13. //通过三角函数计算出各个按钮的中心点14. CGFloat centerBallMenuHalfSize = menuSize_ * .5f;15.// CGFloat buttonRadius = centerButtonSize_ * .5f;16.17. //triangleHypotenuse:三角形的斜边18. if (! triangleHypotenuse) triangleHypotenuse = defaultTriangleHypotenuse_;// Distance to Ball Center 距离球中心19.20.21. //22. // o o o o o o o o o o o o o23. // \|/ \|/ \|/ \|/ \|/ \|/24. // 1 --|-- 2 --|-- 3 --|-- 4 --|-- 5 --|-- 6 --|--25. // /|\ /|\ /|\ /|\ /|\ /|\26. // o o o o o o o o27. //28. switch (buttonCount_) {29. case 1:30. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize -buttonRadius,31. centerBallMenuHalfSize - triangleHypotenuse - buttonRadius)];32. break;33.34. case 2: {35. CGFloat degree = M_PI / 4.0f; // = 45 * M_PI / 18036. CGFloat triangleB = triangleHypotenuse * sinf(degree);37. CGFloat negativeValue = centerBallMenuHalfSize - triangleB - buttonRadius;38. CGFloat positiveValue = centerBallMenuHalfSize + triangleB - buttonRadius;39. [self _setButtonWithTag:1 origin:CGPointMake(negativeValue, negativeValue)];40. [self _setButtonWithTag:2 origin:CGPointMake(positiveValue, negativeValue)];41.42. break;43. }44.45. case 3: {46. // = 360.0f / self.buttonCount * M_PI / 180.0f;47. // E.g: if |buttonCount_ = 6|, then |degree = 60.0f * M_PI / 180.0f|;48. // CGFloat degree = 2 * M_PI / self.buttonCount;49. //50. CGFloat degree = M_PI / 3.0f; // = 60 * M_PI / 18051. CGFloat triangleA = triangleHypotenuse * cosf(degree);52. CGFloat triangleB = triangleHypotenuse * sinf(degree);53. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize -triangleB - buttonRadius,54. centerBallMenuHalfSize - triangleA - buttonRadius)];55. [self _setButtonWithTag:2 origin:CGPointMake(centerBallMenuHalfSize +triangleB - buttonRadius,56. centerBallMenuHalfSize - triangleA - buttonRadius)];57. [self _setButtonWithTag:3 origin:CGPointMake(centerBallMenuHalfSize -buttonRadius,58. centerBallMenuHalfSize + triangleHypotenuse - buttonRadius)];59.60. break;61. }62.63. case 4: {64. CGFloat degree = M_PI / 4.0f; // = 45 * M_PI / 18065. CGFloat triangleB = triangleHypotenuse * sinf(degree);66. CGFloat negativeValue = centerBallMenuHalfSize - triangleB - buttonRadius;67. CGFloat positiveValue = centerBallMenuHalfSize + triangleB - buttonRadius;68. [self _setButtonWithTag:1 origin:CGPointMake(negativeValue, negativeValue)];69. [self _setButtonWithTag:2 origin:CGPointMake(positiveValue, negativeValue)];70. [self _setButtonWithTag:3 origin:CGPointMake(negativeValue, positiveValue)];71. [self _setButtonWithTag:4 origin:CGPointMake(positiveValue, positiveValue)];72. break;73. }74.75. case 5: {76. CGFloat degree = M_PI / 2.5f; // = 72 * M_PI / 18077. CGFloat triangleA = triangleHypotenuse * cosf(degree);78. CGFloat triangleB = triangleHypotenuse * sinf(degree);79. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize -triangleB - buttonRadius,80. centerBallMenuHalfSize - triangleA - buttonRadius)];81. [self _setButtonWithTag:2 origin:CGPointMake(centerBallMenuHalfSize -buttonRadius,82. centerBallMenuHalfSize - triangleHypotenuse - buttonRadius)];83. [self _setButtonWithTag:3 origin:CGPointMake(centerBallMenuHalfSize +triangleB - buttonRadius,84. centerBallMenuHalfSize - triangleA - buttonRadius)];85.86. CGFloat centerX1 = centerBallMenuHalfSize - triangleB;87. CGFloat centerY1 = centerBallMenuHalfSize - triangleA;88. CGFloat centerX2 = centerBallMenuHalfSize + triangleB;89. CGFloat centerX3 = centerBallMenuHalfSize;90. CGFloat centerY3 = centerBallMenuHalfSize - triangleHypotenuse;91. [self _setButtonCenterWithTag:1 origin:CGPointMake(centerX1, centerY1)];92. [self _setButtonCenterWithTag:2 origin:CGPointMake(centerX2, centerY1)];93. [self _setButtonCenterWithTag:3 origin:CGPointMake(centerX3, centerY3)];94.95.96.degree = M_PI / 5.0f; // = 36 * M_PI / 18097.triangleA = triangleHypotenuse * cosf(degree);98.triangleB = triangleHypotenuse * sinf(degree);99. [self _setButtonWithTag:4 origin:CGPointMake(centerBallMenuHalfSize -triangleB - buttonRadius,100. centerBallMenuHalfSize + t riangleA - buttonRadius)];101. [self _setButtonWithTag:5 origin:CGPointMake(centerBallMenuHalfSize + triangleB - buttonRadius,102. centerBallMenuHalfSize + tr iangleA - buttonRadius)];103. break;104. }105.106. case 6: {107. CGFloat degree = M_PI / 3.0f; // = 60 * M_PI / 180108. CGFloat triangleA = triangleHypotenuse * cosf(degree);109. CGFloat triangleB = triangleHypotenuse * sinf(degree);110. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize - triangleB - buttonRadius,111. centerBallMenuHalfSize - t riangleA - buttonRadius)];112. [self _setButtonWithTag:2 origin:CGPointMake(centerBallMenuHalfSize - buttonRadius,113. centerBallMenuHalfSize - t riangleHypotenuse - buttonRadius)];114. [self _setButtonWithTag:3 origin:CGPointMake(centerBallMenuHalfSize + triangleB - buttonRadius,115. centerBallMenuHalfSize - t riangleA - buttonRadius)];116. [self _setButtonWithTag:4 origin:CGPointMake(centerBallMenuHalfSize - triangleB - buttonRadius,117. centerBallMenuHalfSize + t riangleA - buttonRadius)];118. [self _setButtonWithTag:5 origin:CGPointMake(centerBallMenuHalfSize - buttonRadius,119. centerBallMenuHalfSize + t riangleHypotenuse - buttonRadius)];120. [self _setButtonWithTag:6 origin:CGPointMake(centerBallMenuHalfSize + triangleB - buttonRadius,121. centerBallMenuHalfSize + tr iangleA - buttonRadius)];122.123. }124.125. default:126. break;127. }128.}此时,所有的菜单按钮都显示出来了7、当我们再次点击主按钮时,此时的isClosed的值为NO,则会调用_close方法,将所有的按钮的frame都设置为菜单按钮的初始值buttonOriginFrame_,并为其设置动画,这样所有的按钮将会回到原先最初始的frame[html]view plaincopy1.- (void)_close:(NSNotification *)notification2.{3. if (isClosed_)4. return;5.6.isInProcessing_ = YES;7. // Hide buttons with animation8. [UIView animateWithDuration:.3f9. delay:0.f10. options:UIViewAnimationCurveEaseIn11. animations:^{12. for (UIButton * button in [self.menu subviews]) {13. [button setFrame:buttonOriginFrame_];14. }15. [self.menu setAlpha:0.f];16. }17. completion:^(BOOL finished) {18.isClosed_ = YES;19.isOpening_ = NO;20.isInProcessing_ = NO;21. }];22.}8、当我们点击菜单按钮时,则会触发此按钮的事件方法:runButtonActionsrunButtonActions:此方法可以通过使用此框架的用户自己调用此方法来设置其所要跳转的页面,此处演示是跳转到导航控制器,在runButtonActions中通过此方法pushiViewController 跳转到另一个控制器,并设置按钮的动画消失效果,实现过程就是将三角形的斜边设为最大的三角形斜边maxTriangleHypotenuse_,再通过_updateButtonsLayoutWithTriangleHypotenuse方法计算出按钮的frame[html]view plaincopy1.- (void)pushViewController:(id)viewController2.{3. [UIView animateWithDuration:.3f4. delay:0.f5. options:UIViewAnimationOptionCurveEaseInOut6. animations:^{7. // Slide away buttons in center view & hide them8. [self _updateButtonsLayoutWithTriangleHypotenuse:maxTriangleHypotenuse_];9. [self.menu setAlpha:1.f];10.11. /*/ Show Navigation Bar12. [self.navigationController setNavigationBarHidden:NO];13. CGRect navigationBarFrame = self.navigationController.navigationBar.frame;14. if (navigationBarFrame.origin.y <0) {15.navigationBarFrame.origin.y = 0;16. [self.navigationController.navigationBar setFrame:navigationBarFrame];17. }*/18. }19. completion:^(BOOL finished) {20. [self.navigationController pushViewController:viewController animated:YES];21. }];22.}9、从跳转的控制器返回到菜单页面时,再将按钮通过动画返回到原先的位置,将三角形斜边从最大值到默认三角形斜边,_updateButtonsLayoutWithTriangleHypotenuse方法根据给定的三角形斜边,计算出按钮的frame,也就是回到了如下的效果图KYCircleMenu框架的使用KYCircleMenu框架的使用其实很简单,首先需要创建一个KYCircleMenu的控制器,将此控制器显示在window上,再根据用户的需求,设置菜单按钮的个数,按钮的大小,以及点击菜单按钮后所要push到的页面等等,部分实现代码如下:[html]view plaincopy1.UINavigationController * navigationController = [UINavigationController alloc];2.3. // Setup circle menu with basic configuration4. CircleMenuViewController * circleMenuViewController;5.circleMenuViewController = [CircleMenuViewController alloc];6. (void)[circleMenuViewController initWithButtonCount:kKYCCircleMenuButtonsCount7. menuSize:kKYCircleMenuSize8. buttonSize:kKYCircleMenuButtonSize9. buttonImageNameFormat:kKYICircleMenuButtonImageNameFormat10. centerButtonSize:kKYCircleMenuCenterButtonSize11. centerButtonImageName:kKYICircleMenuCenterButton12. centerButtonBackgroundImageName:kKYICircleMenuCenterButtonBackground];13.14. // Set the cricle menu vc as the root vc15. (void)[navigationController initWithRootViewController:circleMenuViewController];16. [navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];17.18. // Set navigation controller as the root vc19. [self.window setRootViewController:navigationController];[html]view plaincopy1.- (void)runButtonActions:(id)sender2.{3. [super runButtonActions:sender];4.5. // Configure new view & push it with custom |pushViewController:| method6. UIViewController * viewController = [[UIViewController alloc] init];7. [viewController.view setBackgroundColor:[UIColor blackColor]];8. [viewController setTitle:[NSString stringWithFormat:@"View %d", [sender tag]]];9. // Use KYCircleMenu's |-pushViewController:| to push vc10. [self pushViewController:viewController];11.}。
【无线互联】IOS开发之KYCircleMenu框架KYCircleMenu框架的功能实现一种弹出菜单按钮,用户点击主按钮,会依次弹出一圈按钮,围绕主按钮圆环状排列,按钮数自定,但在此封装的类中,按钮数至多为6个。
点击其中一个弹出按钮,将通过动画进入到第二个界面,在第二个界面中,点击返回按钮通过动画返回到菜单界面中。
再次点击主按钮,弹出的按钮将收进主按钮中。
KYCircleMenu框架的实现原理1、自定义初始化为KYCircleMenu,通过外部将一些属性值传递进来,通过这些值计算出三角形的斜边、button的原点[html]view plaincopy1.- (instancetype)initWithButtonCount:(NSInteger)buttonCount2. menuSize:(CGFloat)menuSize3. buttonSize:(CGFloat)buttonSize4. buttonImageNameFormat:(NSString *)buttonImageNameFormat5. centerButtonSize:(CGFloat)centerButtonSize6. centerButtonImageName:(NSString *)centerButtonImageName7. centerButtonBackgroundImageName:(NSString *)centerButtonBackgroundImageName8.{9. if (self = [self init]) {10.buttonCount_ = buttonCount;11.menuSize_ = menuSize;12.buttonSize_ = buttonSize;13.buttonImageNameFormat_ = buttonImageNameFormat;14.centerButtonSize_ = centerButtonSize;15.centerButtonImageName_ = centerButtonImageName;16.centerButtonBackgroundImageName_ = centerButtonBackgroundImageName;17.18. // Defualt value for triangle hypotenuse 三角形19.defaultTriangleHypotenuse_ = (menuSize - buttonSize) * .5f; //三角形的斜边20.minBounceOfTriangleHypotenuse_ = defaultTriangleHypotenuse_ - 12.f;21.maxBounceOfTriangleHypotenuse_ = defaultTriangleHypotenuse_ + 12.f;22.maxTriangleHypotenuse_ = kKYCircleMenuViewHeight * .5f; //三角形的最大斜边23.24. // Buttons' origin frame 原点25. CGFloat originX = (menuSize_ - centerButtonSize_) * .5f;26.buttonOriginFrame_ =27. (CGRect){{originX, originX}, {centerButtonSize_, centerButtonSize_}};28. }29. return self;30.}2、在加载视图(loadView)中,计算出self.view的frame; 在计算self.view 的高度时,还判断了当前控制器是否隐藏了导航栏,如果隐藏了,则此视图的高度就为整个屏幕的高度,否则,就要减去导航栏的高度[html]view plaincopy1.- (void)loadView2.{3. CGFloat viewHeight =4. (self.navigationController.isNavigationBarHidden5. ? kKYCircleMenuViewHeight : kKYCircleMenuViewHeight - kKYCircleMenuNavigationBarHeight);6. CGRect frame = CGRectMake(0.f, 0.f, kKYCircleMenuViewWidth, viewHeight);7. UIView * view = [[UIView alloc] initWithFrame:frame];8.self.view = view;9.}3、在viewDidLoad方法中,作了以下操作<1>设置menu_视图,这个用来装载button菜单按钮的<2>根据buttonCount_外部传进来的值来确定button菜单按钮的个数,来创建button,并将这些button全都叠放在menu_视图的中间<3>并创建了中间的主按钮centerButton,用来控制是否显示菜单按钮,将centerButton添加到了当前视图的正中间,与菜单按钮的原始frame重叠<4>监听了菜单按钮关闭的通知[html]view plaincopy1.- (void)viewDidLoad2.{3. [super viewDidLoad];4.5. // Constants6. CGFloat viewHeight = CGRectGetHeight(self.view.frame);7. CGFloat viewWidth = CGRectGetWidth(self.view.frame);8.9. //菜单视图的frama10. CGRect centerMenuFrame =11.CGRectMake((viewWidth - menuSize_) * .5f, (viewHeight - menuSize_) * .5f, menuSize_, menuSize_);12. //menu_指菜单视图13.menu_ = [[UIView alloc] initWithFrame:centerMenuFrame];14. [menu_ setAlpha:0.f];15. [self.view addSubview:menu_];16.17. // Add buttons to |ballMenu_|, set it's origin frame to center18. //buttonCount_ 周围菜单按钮的个数19. NSString * imageName = nil;20. for (int i = 1; i <= buttonCount_; ++i) {21. UIButton * button = [[UIButton alloc] initWithFrame:buttonOriginFrame_];22. [button setOpaque:NO]; //NO 设置控件透明, YES 设置控件不透明,默认为YES23. [button setTag:i];24.imageName = [NSString stringWithFormat:self.buttonImageNameFormat, button.tag];25. [button setImage:[UIImage imageNamed:imageName]26. forState:UIControlStateNormal];27. [button addTarget:self action:@selector(runButtonActions:) forControlEvents:UIControlEventTouchUpInside];28. [self.menu addSubview:button];29. }30.31. // Main Button32. CGRect mainButtonFrame =33.CGRectMake((CGRectGetWidth(self.view.frame) - centerButtonSize_) * .5f,34. (CGRectGetHeight(self.view.frame) - centerButtonSize_) * .5f,35. centerButtonSize_, centerButtonSize_);36.37.centerButton_ = [[UIButton alloc] initWithFrame:mainButtonFrame];38. [centerButton_ setBackgroundImage:[UIImage imageNamed:self.centerButtonBackgroundImageName]39. forState:UIControlStateNormal];40. [centerButton_ setImage:[UIImage imageNamed:self.centerButtonImageName]41. forState:UIControlStateNormal];42. [centerButton_ addTarget:self43. action:@selector(_toggle:)44. forControlEvents:UIControlEventTouchUpInside];45. [self.view addSubview:centerButton_];46.47. // Setup notification observer48. //监听关闭menu_视图的通知49. [self _setupNotificationObserver];50.}4、在viewWillAppear视图将要显示时,隐藏导航栏,并判断它的子视图是否按下按钮,如果是则将菜单通过recoverToNormalStatus方法将其恢复到原始的位置由于此处使用的是ios7,所以当我们隐藏导航栏时,状态栏也会跟着隐藏,如果是ios6,则状态栏不会隐藏,所以应该进行版本的判断,对其做出相应的处理,则不会出现此处不兼容的情况(此处我作了相应的修改,代码如下:)[html]view plaincopy1.- (id)init2.{3. if (self = [super init]) {4.isInProcessing_ = NO;5.isOpening_ = NO;6.isClosed_ = YES;7.shouldRecoverToNormalStatusWhenViewWillAppear_ = NO;8.#ifndef KY_CIRCLEMENU_WITH_NAVIGATIONBAR9.10. //隐藏导航栏11. if (ios7) {12. [self setNeedsStatusBarAppearanceUpdate];13. }14. else {15.16. [[UIApplication sharedApplication] setStatusBarHidden:YES];17. }18. [self.navigationController setNavigationBarHidden:YES];19.#endif20. }21. return self;22.}到此时,视图已经显示出来,其效果为5、当我们点击主按钮centerButton,则会触发此按钮的事件[html]view plaincopy1.//循环切换菜单(关闭、打开)2.- (void)_toggle:(id)sender3.{4. (isClosed_ ? [self open] : [self _close:nil]);5.}通过此方法,循环切换菜单(关闭、打开)因为是第一次触发此按钮,isClosed_的初始值为YES,则会调用open方法6、open方法:此方法是用来打开菜单视图<1>通过动画效果来打开菜单视图,通过传递不同的三角形斜边的值来实现缩放的动画效果<2>通过调用_updateButtonsLayoutWithTriangleHypotenuse,将三角形的斜边值传递给此方法来改变菜单按钮的frame,实现过程:_updateButtonsLayoutWithTriangleHypotenuse根据三角形斜边的值来更新按钮的布局,通过三角函数计算出各个按钮的x、y坐标,将point值以及按钮的tag值传递给_setButtonWithTag:origin:此方法,<3>_setButtonWithTag:origin:此方法的作用:根据tag值取出menu视图中的button,再根据CGPoint设置其frame[html]view plaincopy1.- (void)open2.{3. if (isOpening_) return;4.5.isInProcessing_ = YES;6. // Show buttons with animation7. [UIView animateWithDuration:.3f8. delay:0.f9. options:UIViewAnimationCurveEaseInOut10. animations:^{11. //将menu视图透明度设为112. [self.menu setAlpha:1.f];13. // Compute buttons' frame and set for them, based on |buttonCount|14. //计算按钮的frame15. [self _updateButtonsLayoutWithTriangleHypotenuse:maxBounceOfTriangleHypotenuse_];16. }17. completion:^(BOOL finished) {18. [UIView animateWithDuration:.1f19. delay:0.f20. options:UIViewAnimationCurveEaseInOut21. animations:^{22. [self _updateButtonsLayoutWithTriangleHypotenuse:defaultTriangleHypotenuse_];23. }24. completion:^(BOOL finished) {25.isOpening_ = YES;26.isClosed_ = NO;27.isInProcessing_ = NO;28. }];29. }];30.}[html]view plaincopy1.- (void)_updateButtonsLayoutWithTriangleHypotenuse:(CGFloat)triangleHypotenuse2.{3. //4. // Triangle Values for Buttons' Position5. //6. // /| a: triangleA = c * cos(x)7. // c / | b b: triangleB = c * sin(x)8. // /)x| c: triangleHypotenuse9. // ----- x: degree10. // a11. //12. //通过设置按钮中心点来来更新按钮的布局13. //通过三角函数计算出各个按钮的中心点14. CGFloat centerBallMenuHalfSize = menuSize_ * .5f;15.// CGFloat buttonRadius = centerButtonSize_ * .5f;16.17. //triangleHypotenuse:三角形的斜边18. if (! triangleHypotenuse) triangleHypotenuse = defaultTriangleHypotenuse_;// Distance to Ball Center 距离球中心19.20.21. //22. // o o o o o o o o o o o o o23. // \|/ \|/ \|/ \|/ \|/ \|/24. // 1 --|-- 2 --|-- 3 --|-- 4 --|-- 5 --|-- 6 --|--25. // /|\ /|\ /|\ /|\ /|\ /|\26. // o o o o o o o o27. //28. switch (buttonCount_) {29. case 1:30. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize -buttonRadius,31. centerBallMenuHalfSize - triangleHypotenuse - buttonRadius)];32. break;33.34. case 2: {35. CGFloat degree = M_PI / 4.0f; // = 45 * M_PI / 18036. CGFloat triangleB = triangleHypotenuse * sinf(degree);37. CGFloat negativeValue = centerBallMenuHalfSize - triangleB - buttonRadius;38. CGFloat positiveValue = centerBallMenuHalfSize + triangleB - buttonRadius;39. [self _setButtonWithTag:1 origin:CGPointMake(negativeValue, negativeValue)];40. [self _setButtonWithTag:2 origin:CGPointMake(positiveValue, negativeValue)];41.42. break;43. }44.45. case 3: {46. // = 360.0f / self.buttonCount * M_PI / 180.0f;47. // E.g: if |buttonCount_ = 6|, then |degree = 60.0f * M_PI / 180.0f|;48. // CGFloat degree = 2 * M_PI / self.buttonCount;49. //50. CGFloat degree = M_PI / 3.0f; // = 60 * M_PI / 18051. CGFloat triangleA = triangleHypotenuse * cosf(degree);52. CGFloat triangleB = triangleHypotenuse * sinf(degree);53. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize -triangleB - buttonRadius,54. centerBallMenuHalfSize - triangleA - buttonRadius)];55. [self _setButtonWithTag:2 origin:CGPointMake(centerBallMenuHalfSize +triangleB - buttonRadius,56. centerBallMenuHalfSize - triangleA - buttonRadius)];57. [self _setButtonWithTag:3 origin:CGPointMake(centerBallMenuHalfSize -buttonRadius,58. centerBallMenuHalfSize + triangleHypotenuse - buttonRadius)];59.60. break;61. }62.63. case 4: {64. CGFloat degree = M_PI / 4.0f; // = 45 * M_PI / 18065. CGFloat triangleB = triangleHypotenuse * sinf(degree);66. CGFloat negativeValue = centerBallMenuHalfSize - triangleB - buttonRadius;67. CGFloat positiveValue = centerBallMenuHalfSize + triangleB - buttonRadius;68. [self _setButtonWithTag:1 origin:CGPointMake(negativeValue, negativeValue)];69. [self _setButtonWithTag:2 origin:CGPointMake(positiveValue, negativeValue)];70. [self _setButtonWithTag:3 origin:CGPointMake(negativeValue, positiveValue)];71. [self _setButtonWithTag:4 origin:CGPointMake(positiveValue, positiveValue)];72. break;73. }74.75. case 5: {76. CGFloat degree = M_PI / 2.5f; // = 72 * M_PI / 18077. CGFloat triangleA = triangleHypotenuse * cosf(degree);78. CGFloat triangleB = triangleHypotenuse * sinf(degree);79. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize -triangleB - buttonRadius,80. centerBallMenuHalfSize - triangleA - buttonRadius)];81. [self _setButtonWithTag:2 origin:CGPointMake(centerBallMenuHalfSize -buttonRadius,82. centerBallMenuHalfSize - triangleHypotenuse - buttonRadius)];83. [self _setButtonWithTag:3 origin:CGPointMake(centerBallMenuHalfSize +triangleB - buttonRadius,84. centerBallMenuHalfSize - triangleA - buttonRadius)];85.86. CGFloat centerX1 = centerBallMenuHalfSize - triangleB;87. CGFloat centerY1 = centerBallMenuHalfSize - triangleA;88. CGFloat centerX2 = centerBallMenuHalfSize + triangleB;89. CGFloat centerX3 = centerBallMenuHalfSize;90. CGFloat centerY3 = centerBallMenuHalfSize - triangleHypotenuse;91. [self _setButtonCenterWithTag:1 origin:CGPointMake(centerX1, centerY1)];92. [self _setButtonCenterWithTag:2 origin:CGPointMake(centerX2, centerY1)];93. [self _setButtonCenterWithTag:3 origin:CGPointMake(centerX3, centerY3)];94.95.96.degree = M_PI / 5.0f; // = 36 * M_PI / 18097.triangleA = triangleHypotenuse * cosf(degree);98.triangleB = triangleHypotenuse * sinf(degree);99. [self _setButtonWithTag:4 origin:CGPointMake(centerBallMenuHalfSize -triangleB - buttonRadius,100. centerBallMenuHalfSize + t riangleA - buttonRadius)];101. [self _setButtonWithTag:5 origin:CGPointMake(centerBallMenuHalfSize + triangleB - buttonRadius,102. centerBallMenuHalfSize + tr iangleA - buttonRadius)];103. break;104. }105.106. case 6: {107. CGFloat degree = M_PI / 3.0f; // = 60 * M_PI / 180108. CGFloat triangleA = triangleHypotenuse * cosf(degree);109. CGFloat triangleB = triangleHypotenuse * sinf(degree);110. [self _setButtonWithTag:1 origin:CGPointMake(centerBallMenuHalfSize - triangleB - buttonRadius,111. centerBallMenuHalfSize - t riangleA - buttonRadius)];112. [self _setButtonWithTag:2 origin:CGPointMake(centerBallMenuHalfSize - buttonRadius,113. centerBallMenuHalfSize - t riangleHypotenuse - buttonRadius)];114. [self _setButtonWithTag:3 origin:CGPointMake(centerBallMenuHalfSize + triangleB - buttonRadius,115. centerBallMenuHalfSize - t riangleA - buttonRadius)];116. [self _setButtonWithTag:4 origin:CGPointMake(centerBallMenuHalfSize - triangleB - buttonRadius,117. centerBallMenuHalfSize + t riangleA - buttonRadius)];118. [self _setButtonWithTag:5 origin:CGPointMake(centerBallMenuHalfSize - buttonRadius,119. centerBallMenuHalfSize + t riangleHypotenuse - buttonRadius)];120. [self _setButtonWithTag:6 origin:CGPointMake(centerBallMenuHalfSize + triangleB - buttonRadius,121. centerBallMenuHalfSize + tr iangleA - buttonRadius)];122.123. }124.125. default:126. break;127. }128.}此时,所有的菜单按钮都显示出来了7、当我们再次点击主按钮时,此时的isClosed的值为NO,则会调用_close方法,将所有的按钮的frame都设置为菜单按钮的初始值buttonOriginFrame_,并为其设置动画,这样所有的按钮将会回到原先最初始的frame[html]view plaincopy1.- (void)_close:(NSNotification *)notification2.{3. if (isClosed_)4. return;5.6.isInProcessing_ = YES;7. // Hide buttons with animation8. [UIView animateWithDuration:.3f9. delay:0.f10. options:UIViewAnimationCurveEaseIn11. animations:^{12. for (UIButton * button in [self.menu subviews]) {13. [button setFrame:buttonOriginFrame_];14. }15. [self.menu setAlpha:0.f];16. }17. completion:^(BOOL finished) {18.isClosed_ = YES;19.isOpening_ = NO;20.isInProcessing_ = NO;21. }];22.}8、当我们点击菜单按钮时,则会触发此按钮的事件方法:runButtonActionsrunButtonActions:此方法可以通过使用此框架的用户自己调用此方法来设置其所要跳转的页面,此处演示是跳转到导航控制器,在runButtonActions中通过此方法pushiViewController 跳转到另一个控制器,并设置按钮的动画消失效果,实现过程就是将三角形的斜边设为最大的三角形斜边maxTriangleHypotenuse_,再通过_updateButtonsLayoutWithTriangleHypotenuse方法计算出按钮的frame[html]view plaincopy1.- (void)pushViewController:(id)viewController2.{3. [UIView animateWithDuration:.3f4. delay:0.f5. options:UIViewAnimationOptionCurveEaseInOut6. animations:^{7. // Slide away buttons in center view & hide them8. [self _updateButtonsLayoutWithTriangleHypotenuse:maxTriangleHypotenuse_];9. [self.menu setAlpha:1.f];10.11. /*/ Show Navigation Bar12. [self.navigationController setNavigationBarHidden:NO];13. CGRect navigationBarFrame = self.navigationController.navigationBar.frame;14. if (navigationBarFrame.origin.y <0) {15.navigationBarFrame.origin.y = 0;16. [self.navigationController.navigationBar setFrame:navigationBarFrame];17. }*/18. }19. completion:^(BOOL finished) {20. [self.navigationController pushViewController:viewController animated:YES];21. }];22.}9、从跳转的控制器返回到菜单页面时,再将按钮通过动画返回到原先的位置,将三角形斜边从最大值到默认三角形斜边,_updateButtonsLayoutWithTriangleHypotenuse方法根据给定的三角形斜边,计算出按钮的frame,也就是回到了如下的效果图KYCircleMenu框架的使用KYCircleMenu框架的使用其实很简单,首先需要创建一个KYCircleMenu的控制器,将此控制器显示在window上,再根据用户的需求,设置菜单按钮的个数,按钮的大小,以及点击菜单按钮后所要push到的页面等等,部分实现代码如下:[html]view plaincopy1.UINavigationController * navigationController = [UINavigationController alloc];2.3. // Setup circle menu with basic configuration4. CircleMenuViewController * circleMenuViewController;5.circleMenuViewController = [CircleMenuViewController alloc];6. (void)[circleMenuViewController initWithButtonCount:kKYCCircleMenuButtonsCount7. menuSize:kKYCircleMenuSize8. buttonSize:kKYCircleMenuButtonSize9. buttonImageNameFormat:kKYICircleMenuButtonImageNameFormat10. centerButtonSize:kKYCircleMenuCenterButtonSize11. centerButtonImageName:kKYICircleMenuCenterButton12. centerButtonBackgroundImageName:kKYICircleMenuCenterButtonBackground];13.14. // Set the cricle menu vc as the root vc15. (void)[navigationController initWithRootViewController:circleMenuViewController];16. [navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];17.18. // Set navigation controller as the root vc19. [self.window setRootViewController:navigationController];[html]view plaincopy1.- (void)runButtonActions:(id)sender2.{3. [super runButtonActions:sender];4.5. // Configure new view & push it with custom |pushViewController:| method6. UIViewController * viewController = [[UIViewController alloc] init];7. [viewController.view setBackgroundColor:[UIColor blackColor]];8. [viewController setTitle:[NSString stringWithFormat:@"View %d", [sender tag]]];9. // Use KYCircleMenu's |-pushViewController:| to push vc10. [self pushViewController:viewController];11.}。