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

2023-11-05 13:58
文章标签 代码 构建 2014 widget 用纯

本文主要是介绍如何用纯代码构建一个 Widget(2014),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

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

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

准备

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

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

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

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

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

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

运行

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

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

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

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

那么问题来了…

修改

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


@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呢? 重载如下方法即可

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

修改完以后您再看

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

进阶

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

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

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

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

首先修改viewDidLoad的代码

- (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();
    }];
    
    ...
    ...
    ...
    
}

然后修改按钮的动作

- (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 而纯代码的方式我相信会让很多人更得心应手

这篇关于如何用纯代码构建一个 Widget(2014)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/350297

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

ZOJ Monthly, August 2014小记

最近太忙太忙,只能抽时间写几道简单题。不过我倒是明白要想水平提高不看题解是最好的了。 A  我只能死找规律了,无法证明 int a[50002][2] ;vector< vector<int> > gmax , gmin ;int main(){int n , i , j , k , cmax , cmin ;while(cin>>n){/* g

2014 Multi-University Training Contest 8小记

1002 计算几何 最大的速度才可能拥有无限的面积。 最大的速度的点 求凸包, 凸包上的点( 注意不是端点 ) 才拥有无限的面积 注意 :  凸包上如果有重点则不满足。 另外最大的速度为0也不行的。 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct poin

2014 Multi-University Training Contest 7小记

1003   数学 , 先暴力再解方程。 在b进制下是个2 , 3 位数的 大概是10000进制以上 。这部分解方程 2-10000 直接暴力 typedef long long LL ;LL n ;int ok(int b){LL m = n ;int c ;while(m){c = m % b ;if(c == 3 || c == 4 || c == 5 ||

2014 Multi-University Training Contest 6小记

1003  贪心 对于111...10....000 这样的序列,  a 为1的个数,b为0的个数,易得当 x= a / (a + b) 时 f最小。 讲串分成若干段  1..10..0   ,  1..10..0 ,  要满足x非递减 。  对于 xi > xi+1  这样的合并 即可。 const int maxn = 100008 ;struct Node{int