21-纯代码构建Widget

如何用纯代码构建一个Widget(today extension)

前言

随着iOS8的发布 各种iPhone的新玩法出现了 其中最引人关注的就是today extension(也叫做widget) 这个在android上存在了多年的小玩意 也是iPhone一直被人诟病的东西 终于能用上了

网上有很多相关的文章教你如何编写一个简单的widget 但是却没有一篇适合我们这种纯代码的拥趸(也有很多人说应该放弃纯代码 改用Storyboard了) 那么接下来我就说说 如何用纯代码的方式来构建一个widget

准备

首先 你得有个正常的app项目(这是必须的 extension必须依附于某个app中 当然 不这样 你也无法单独安装某个widget)

打开项目工程 选择新建一个target 在Application Extension中选择today exntension 然后填入名字 确认即可

新建target

填入信息

这时你的项目里多个一个target 同时也多了下面

修改plist

接下来 删掉这个讨厌的MainInterface.storyboard 然后修改plist文件中的NSExtension字段

  • 删掉NSExtensionMainStoryboard字段
  • 添加NSExtensionPrincipalClass字段 并设为TodayViewController(你也可以指定其他的ViewController)

修改plist

修改完以后 Widget就可以开始编译运行了

运行

关于调试Widget 我推荐使用模拟器而不用真机 因为在研究过程中我发现真机调试的效果非常差 经常提示无法连接到手机(也有可能是5S的性能够不?) 导致无法正常的debug 或者无法reinstall 而模拟器则好点(至少能顺利的打印出log) 但是每次修改好代码以后 最好都先退出模拟器 再重新编译运行 如果你退出重新运行时提示下面这个错误 不用怕 多运行两次就ok了

模拟器报错

Command+R编译运行 会弹出提示框让你选择宿主app 就选择默认的today就好了
运行

如无意外 模拟器启动时会自动打开today 并显示你的widget
效果

是不是发现什么都没有? 如果用Storyboard构建的Widget 会默认有个Hello 可我们弄出来的Widget 却啥都没有 连高度都没有

那么问题来了…

修改

首先 我们设置一下widget的高度 并添加一个contentView和一个button(注意 这里我使用的是Masonry来完成autolayout 相关信息可见我的上一篇文章:Masonry介绍与使用实践(快速上手Autolayout)

12345678910111213141516171819202122232425262728293031323334353637
@interface TodayViewController () <NCWidgetProviding>

@property (strong, nonatomic) UIView *contentView;@property (nonatomic, strong) UIButton *btnTest;

@end

- (void)viewDidLoad {    [super viewDidLoad];

    //使用preferredContentSize设置大小 且只用设置高度就好了    self.preferredContentSize = CGSizeMake(0, 200);

    __weak __typeof(&*self)ws = self;

    self.contentView = [UIView new];    self.contentView.backgroundColor = [UIColor whiteColor];    [self.view addSubview:self.contentView];

    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {        make.edges.equalTo(ws.view);    }];

    self.btnTest = [UIButton buttonWithType:UIButtonTypeCustom];    [self.btnTest setTitle:[[NSDate date] description] forState:UIControlStateNormal];    self.btnTest.backgroundColor = [UIColor redColor];    [self.btnTest addTarget:self action:@selector(actionTest) forControlEvents:UIControlEventTouchUpInside];

    [self.contentView addSubview:self.btnTest];

    [self.btnTest mas_makeConstraints:^(MASConstraintMaker *make) {        make.center.equalTo(ws.contentView);        make.size.mas_equalTo(CGSizeMake(300, 40));    }];}

运行一下 看看效果
效果

控件是出来了 可是没有如我们的意 旁边还空了一块 原来widget默认会有一个inset 那么如何取消这个inset呢? 重载如下方法即可

1234
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{    return UIEdgeInsetsZero;}

修改完以后您再看

效果

一个Widget的模子就这样构建完成了

进阶

接下来 我们给button加个点击事件 用来改变widget的大小

1234
- (void) actionTest{    self.preferredContentSize = CGSizeMake(0, self.contentView.frame.size.height>250?200:300);}

效果

测试发现效果”还可以” 为什么仅仅是”还可以”呢 可以看到当size变化时 其他区域其实是有个动态变化的效果 但是我们的widget的变化是立即的 所以看上去不那么流畅(storyboard里就不存在这个问题了 因为使用了autolayout)

那么我们可不可以也使用autolayout 而不设置这个preferredContentSize呢? 答案是可以的

首先修改viewDidLoad的代码

1234567891011121314151617181920212223
- (void)viewDidLoad {    [super viewDidLoad];

    //去掉这一步    //self.preferredContentSize = CGSizeMake(0, 200);

    __weak __typeof(&*self)ws = self;

    self.contentView = [UIView new];    self.contentView.backgroundColor = [UIColor whiteColor];    [self.view addSubview:self.contentView];

    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {        make.edges.equalTo(ws.view);        //设置内部view的高度(一定要设置高优先级 不然会有冲突)        make.height.mas_equalTo(@200).priorityHigh();    }];

    ...    ...    ...

}

然后修改按钮的动作

12345678910
- (void) actionTest{    //去掉这一步    //self.preferredContentSize = CGSizeMake(0, self.contentView.frame.size.height>250?200:300);

    //更新autolayout    [self.contentView mas_updateConstraints:^(MASConstraintMaker *make) {        make.height.mas_equalTo(@(self.contentView.frame.size.height>250?200:300)).priorityHigh();    }];}

试着运行一下 你会发现世界变得很美丽了

效果

至此 发挥你的想象吧 you can do whatever you want!

小结

所有的准备工作都已经做完了 编写一个Widget也变得很简单 你可以像写任何一个ViewController一样来写Widget 而纯代码的方式我相信会让很多人更得心应手

时间: 2024-08-27 03:23:17

21-纯代码构建Widget的相关文章

iOS开发之构建Widget

http://www.cocoachina.com/ios/20150702/12337.html 伴随这iOS 8 系统多达4000项API更新而来同样还有Today Extension.而对iOS而言,有了Today Extension 开发者可以很好借助系统提供的接入点为系统定制的服务,提供自定义的附加功能.这意味着什么呢?从iOS 7版本尝试开路到现在iOS 8更新的到来终于向开发者开放Widget接入,这意味着系统应用和第三方应用都可以通知中心(Notification Center)

纯代码添加约束,autolayout 适配

IOS AutoLayout 代码约束—VFL 2014-12-22 22:19:43http://my.oschina.net/carson6931-Carson6931-点击数:2148 IOS 提供了两种添加约束的方法 第一种: +(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2

ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局 一.实现效果 二.使用纯代码自定义一个tableview的步骤 1.新建一个继承自UITableViewCell的类 2.重写initWithStyle:reuseIdentifier:方法 添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中

iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(一)

iOS开发UI篇-以微博界面为例使用纯代码自定义cell程序编码全过程(一) 一.storyboard的处理 直接让控制器继承uitableview controller,然后在storyboard中把继承自uiviewcontroller的控制器干掉,重新拖一个tableview controller,和主控制器进行连线. 项目结构和plist文件 二.程序逻辑业务的处理 第一步,把配图和plist中拿到项目中,加载plist数据(非png的图片放到spooding files中) 第二步,字

纯代码Tom

1 // 2 // LWTViewController.m 3 // 纯代码Tom 4 // 5 // Created by apple on 14-5-21. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import "LWTViewController.h" 10 #define KBtnSize 60 11 12 // 图标按钮的左右的排列 13 typedef enum { 14 KButtonThi

IOS之UI--小实例项目--添加商品和商品名(纯代码终结版)

*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: pointer; position: absolute

iOS:删除storyBoard,纯代码实现UITabBarController的视图切换功能

storyboard是一个很强大的编写代码的辅助工具,可以帮助布局多个视图之间的联系,既直观又能减少代码量:但是,作为一个程序员,在不使用storyboard的情况下,纯代码编写是必须的技能. 下面就用纯代码实现纯代码实现UITabBarController的视图切换功能,咱就实现三个视图之间的转换吧,代码不多,容易看的明白. 步骤: 1.删除storyboard故事板和UIViewController 2.创建三个控制器类,均继承自UIViewController,分别为FirstViewCo

IOS开发UI篇--UITableView的自定义布局==纯代码布局

UITableView中除了利用系统的UItableViewCell不能完成需求进行布局时,还可以进行自定义布局: 自定义布局分为两类:(1)利用代码进行创建 (2)利用xib进行实现: 下面对利用代码进行创建分析: 应用场景:像微博,等列表数据展示(由于微博的每个单元格的数据大小不一致,所以得计算每个单元格的大小) 分析:前提是获取列表数据,然后建立每个单元格的模型(建立单元格模型应继承UITableViewCell)复写 - (id)initWithStyle:(UITableViewCel

纯代码transform位移伸缩和旋转

1 // 2 // LWTViewController.m 3 // 纯代码位移和伸缩作业 4 // 5 // Created by apple on 14-5-20. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import "LWTViewController.h" 10 #pragma mark 定义常量 11 /** 图片距离顶部的高度 */ 12 #define KImageY 60 13 /**