Evernote样式的Share Extension

本文介绍如何在iOS应用中实现类似Evernote的Share Extension功能,包括自定义配置项图标、调整导航栏样式及自动调整视图控制器高度等技巧。

下文所述均是在继承 SLComposeServiceViewController 的基础上的不漂亮做法,对于无法满足更多要求时,请使用 UIViewController 或者 NSViewController 来实现

Evernote 无论是桌面还是移动客户端都以设计新颖,用户体验良好成为设计者们借鉴的标杆。iOS8 带来的Share Extension更是提高了 Evernote 的易用性,以前需要在桌面浏览器 Clip 保存的功能在 iPhone、iPad 上也能用了。

在众多开发者给自己应用定制 Share Extension 的时候,自然得看看 Evernote 是怎么把体验做得很好的。我在给公司应用定制时也首先想到了 Evernote。

最吸引开发者的应该是最底下带有 icon 的 TableViewCell。我们都知道配置下面的TableView需要在函数 - (NSArray *)configurationItems 中配置。

- (NSArray *)configurationItems {
    SLComposeSheetConfigurationItem *accountItem = [[SLComposeSheetConfigurationItem alloc] init];
    accountItem.title = @"account";
    SLComposeSheetConfigurationItem *groupItem = [[SLComposeSheetConfigurationItem alloc] init];
    groupItem.title = @"group";
    return @[accountItem, groupItem];
}

但是配置中并没有配置 icon 的参数。当然首先想到的是 Evernote 自定义了SLComposeSheetConfigurationItem 和SLComposeServiceViewController,但翻遍了文档和Google都没有找到相应的资料。找寻解决办法失败后想着以其花时间也可能找不到解决,还不如试试 Hacking 的方式。经过几天摸索,终于模仿得挺像了。

添加icon

既然没法配置 icon,那就在 viewDidLoad 或者 viewDidAppear 中手动添加 icon,然后将 SLComposeSheetConfigurationItem 的 title 置空。ViewController 跳转的时候控制它们隐藏显示。

PS: viewDidAppear也只会触发一次

self.view

icon 用 self.view 添加自然可以,但是 ConfigureItem 一多,键盘切换时就会发生错位了。 

这是为什么呢?

我们在 Extension 呈现后设置断点,打印出当前 ViewController 的层级。 原来在 SLComposeServiceViewController 中的 self.view并不是我们看到的 Extension 所显示的 view, 打印self.view.frame 得出的大小也不符。仔细查看 view 层级后,使用

UIView *containerView = [self.view subviews][0];  
[containerView addSubView:icon];

可以将 icon 挂到显示的 view 上。而Evernote是选择将显示的 view 往上提了一段距离来避免在小屏幕上碰到此问题。至此解决了 icon 显示的问题。

在你想用通常的方法,用 UIImageView 替换 NavigationItem.titleView时,发现不起作用。那是因为当前的 SLSheetNaviagtionController 与 UINavigationController 不一样,设置后也没效果。

那怎么办呢?

还是像之前我们在模拟 TableViewCell 时一样,自己添加 icon 吧。

self.logoImage = [[UIImageView alloc] initWithFrame:CGRectMake(150, 10, 56, 22)];  
self.logoImage.image = [UIImage imageNamed:@"navi_lobi_logo"];  
[containerView addSubview:self.logoImage];

自动改变ViewController的高度

使用Evernote时观察到,在选择 notebook 页面,当 notebook 很多时,会自动增加 ViewController 的高度,使之适应整个屏幕。 这是怎么实现的?

只需在 pushConfigurationViewController 之前设置 vc 的 preferredContentSize 就行。

groupItem.tapHandler = ^(void) {  
        GroupTableViewController *groupVC = [[GroupTableViewController alloc] init];
        groupVC.preferredContentSize = CGSizeMake(self.navigationController.navigationBar.frame.size.width, [groupVC needsContentHeight]);
        [_self pushConfigurationViewController:groupVC];
    };

Evernote的实现方式

在几天研究后,观察到一个细节。在上面的 ViewController 的层级图里,作为呈现的 view 其实是被包到一个 TableView 里了。既然是 TableView, 那肯定可以上下拖动了。 但是 Evernote 的 Extension 是无法拖动的。所以我怀疑 Evernote 也是采用我这种 Hacking 方式,因为你一拖动,手动添加的 icon 又会错位了,所以只能把 TableView 的 scroll 禁止了。

- (void)disableScrollInSubviews:(UIView*)av {
    for (UIView *v in [av subviews]) {
        if ([v isKindOfClass:[UIScrollView class]]) {
            UIScrollView *sView = (UIScrollView*)v;
            sView.scrollEnabled = NO;
            return;
        }
        else {
            [self disableScrollInSubviews:v];
        }
    }
}

Preview

SLComposeServiceViewController 里有个很重要的方法 - (UIView *)loadPreviewView;。 preview 的行为比较诡异,没有细致研究,待补充。。。

虽然实现方式没怎么高大上,算是暂时能用。如果你有更好的方式,或者本文里有什么错误,欢迎留言指出。

源码来自:https://pan.quark.cn/s/7a757c0c80ca 《在Neovim中运用Lua的详尽教程》在当代文本编辑器领域,Neovim凭借其卓越的性能、可扩展性以及高度可定制的特点,赢得了程序开发者的广泛青睐。 其中,Lua语言的融入更是为Neovim注入了强大的活力。 本指南将深入剖析如何在Neovim中高效地运用Lua进行配置和插件开发,助你充分发挥这一先进功能的潜力。 一、Lua为何成为Neovim的优选方案经典的Vim脚本语言(Vimscript)虽然功能完备,但其语法结构与现代化编程语言相比显得较为复杂。 与此形成对比的是,Lua是一种精简、轻量且性能卓越的脚本语言,具备易于掌握、易于集成的特点。 因此,Neovim选择Lua作为其核心扩展语言,使得配置和插件开发过程变得更加直观和便捷。 二、安装与设置在Neovim中启用Lua支持通常十分简便,因为Lua是Neovim的固有组件。 然而,为了获得最佳体验,我们建议升级至Neovim的最新版本。 可以通过`vim-plug`或`dein.vim`等包管理工具来安装和管理Lua插件。 三、Lua基础在着手编写Neovim的Lua配置之前,需要对Lua语言的基础语法有所掌握。 Lua支持变量、函数、控制流、表(类似于数组和键值对映射)等核心概念。 它的语法设计简洁明了,便于理解和应用。 例如,定义一个变量并赋值:```lualocal myVariable = "Hello, Neovim!"```四、Lua在Neovim中的实际应用1. 配置文件:Neovim的初始化文件`.vimrc`能够完全采用Lua语言编写,只需在文件首部声明`set runtimepath^=~/.config/nvim ini...
基于STM32 F4的永磁同步电机无位置传感器控制策略研究内容概要:本文围绕基于STM32 F4的永磁同步电机(PMSM)无位置传感器控制策略展开研究,重点探讨在不使用机械式位置传感器的情况下,如何通过算法实现对电机转子位置和速度的精确估算与控制。文中结合STM32 F4高性能微控制器平台,采用如滑模观测器(SMO)、扩展卡尔曼滤波(EKF)或高频注入法等先进观测技术,实现对电机反电动势或磁链的实时估算,进而完成磁场定向控制(FOC)。研究涵盖了控制算法设计、系统建模、仿真验证(可能使用Simulink)以及在嵌入式平台上的代码实现与实验测试,旨在提高电机驱动系统的可靠性、降低成本并增强环境适应性。; 适合人群:具备一定电机控制理论基础和嵌入式开发经验的电气工程、自动化及相关专业的研究生、科研人员及从事电机驱动开发的工程师;熟悉C语言和MATLAB/Simulink工具者更佳。; 使用场景及目标:①为永磁同步电机驱动系统在高端制造、新能源汽车、家用电器等领域提供无位置传感器解决方案的设计参考;②指导开发者在STM32平台上实现高性能FOC控制算法,掌握位置观测器的设计与调试方法;③推动电机控制技术向低成本、高可靠方向发展。; 其他说明:该研究强调理论与实践结合,不仅包含算法仿真,还涉及实际硬件平台的部署与测试,建议读者在学习过程中配合使用STM32开发板和PMSM电机进行实操验证,以深入理解控制策略的动态响应与鲁棒性问题。
先看效果: https://pan.quark.cn/s/21391ce66e01 企业级办公自动化系统,一般被称为OA(Office Automation)系统,是企业数字化进程中的关键构成部分,旨在增强组织内部的工作效能与协同水平。 本资源提供的企业级办公自动化系统包含了详尽的C#源代码,涉及多个技术领域,对于软件开发者而言是一份极具价值的参考资料。 接下来将具体介绍OA系统的核心特性、关键技术以及在实践操作中可能涉及的技术要点。 1. **系统构造** - **三层构造**:大型OA系统普遍采用典型的三层构造,包含表现层、业务逻辑层和数据访问层。 这种构造能够有效分离用户交互界面、业务处理过程和数据存储功能,从而提升系统的可维护性与可扩展性。 2. **C#编程语言** - **C#核心**:作为开发语言,C#具备丰富的类库和语法功能,支持面向对象编程,适用于开发复杂的企业级应用。 - **.NET Framework**:C#在.NET Framework环境中运行,该框架提供了大量的类库与服务,例如ASP.NET用于Web开发,Windows Forms用于桌面应用。 3. **控件应用** - **WinForms**或**WPF**:在客户端,可能会使用WinForms或WPF来设计用户界面,这两者提供了丰富的控件和可视化设计工具。 - **ASP.NET Web Forms/MVC**:对于Web应用,可能会使用ASP.NET的Web Forms或MVC模式来构建交互式页面。 4. **数据库操作** - **SQL Server**:大型OA系统通常采用关系型数据库管理系统,如SQL Server,用于存储和处理大量数据。 - **ORM框架**:如Ent...
### Evernote 应用介绍 Evernote 是一款功能强大的数字笔记管理工具,支持多平台操作并提供丰富的特性来满足用户的多样化需求。通过该应用,用户不仅可以创建和归档笔记,还能嵌入多种媒体形式的内容,如照片、音频以及收藏的网页链接[^2]。 #### 基础概念 - **笔记本 (Notebook)**:类似于实体书中的章节,用于分类存储笔记。 - **笔记 (Note)**:具体的信息单元,可以包含文字、图片、附件等多种内容。 - **标签 (Tag)**:为每条笔记添加关键词,便于快速检索相关内容。 - **搜索功能**:支持全文搜索,即使是在图片内的文本也能被识别和索引[^4]。 --- ### 使用指南 #### 1. 创建与管理笔记 用户可以通过界面轻松创建新笔记,在其中输入所需的文字信息,并附加其他类型的文件或多媒体资源。此外,还提供了便捷的方式将外部数据导入至 Evernote 中,比如电子邮件转发或者直接扫描纸质文档。 #### 2. 数据同步与访问 借助云服务技术,所有保存于 Evernote 上的数据都会自动实现跨设备间的实时更新共享。这意味着无论何时何地只要连接互联网就能即时获取最新版本的工作资料[^3]。 #### 3. 高效组织方法论 为了更好地发挥此软件带来的便利性,建议采用如下策略优化个人工作效率: - 利用层次分明的目录体系安排不同主题下的子项; - 给重要事项打上专属标志以便突出显示; - 定期回顾已存档案以重新评估价值所在。 #### 4. 开发者集成选项 对于希望进一步定制化体验的技术爱好者来说,官方也开放了一系列 API 接口供第三方开发者调用扩展基本功能集之外的新玩法——例如基于 Python 脚本解析 .ENEX 文件格式从而批量迁移历史记录;亦或是依靠 Android-Job 类库调度定时执行某些特定逻辑片段等等[^1][^5]。 ```python from evernote.api.client import EvernoteClient # 初始化客户端实例 client = EvernoteClient(token="your_developer_token", sandbox=False) # 获取 NoteStore 对象 note_store = client.get_note_store() # 查询某个 Notebook 下的所有 Notes ID 列表 filter_ = note_store.NoteFilter() result_spec = note_store.NotesMetadataResultSpec(includeTitle=True) notes_metadata_list = note_store.findNotesMetadata(filter_, 0, 10, result_spec).notes for meta_data in notes_metadata_list: print(f"Note Title: {meta_data.title}") ``` 上述代码展示了如何利用 `evernote-sdk-python` 来列举指定笔记本里的前十个标题名称作为演示例子。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值