Hello Li

lx的个人博客


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

3D - Touch(二)之Peek And Pop

发表于 2016-09-24   |   分类于 Swift   |   阅读次数

前言

在介绍了前面的桌面的3D-Touch,这篇文章来介绍应用中使用peek & pop。 比如QQ 微信中消息界面重压cell就会出现peek & pop。接下来实现这一效果。

实现

创建视图(sourceView)

首先用tableview来做例子。用storyboard创建表,在这里就不赘述了。

1
var titleArray = ["3D-Touch Objective-C","3D-Touch Swift","前言快报:Swift终将超越OC,进而取代OC","Github9月编程语言 JS 跃居第一位"]

创建一个数组来做tableview的数据源。

实现代理

在实现这一效果之前,需要使当前的控制器实现UIViewControllerPreviewingDelegate代理并且要判断当前设备是否支持Peek & pop:

1
2
3
if traitCollection.forceTouchCapability == .available{
registerForPreviewing(with: self, sourceView: tableView)
}

代理中有两个方法:

1
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?

第一个参数可以获取到要显示的是哪个目标view(sourceView)以及手势,其中有个属性(sourceRect)还可以控制那块区域展示出peek的效果

第二个参数location 顾名思义就是要控制能产生重压的区域。(与第一个参数的sourceRect不同,sourceRect只是哪片区域要展示peek效果,就是在屏幕中视图凸起的那一部分。如果不设置默认就是整个sourceView,而这个参数则是控制哪些区域能使用peek效果)。注意 “能” 和 “要”。
这个方法返回的是要显示的那个控制器,就是pop预览的那个控制器。

1
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)

这个方法就是用来做跳转的。

开始实现代理方法

我们需要新建一个控制器来做pop效果,返回出这个控制器。

1
2
3
4
5
6
7
8
9
10
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = tableView.indexPathForRow(at:location) , let cell = tableView.cellForRow(at: indexPath) else {
return nil
}
let detailVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "detail") as! DetailViewController
previewingContext.sourceRect = cell.frame
detailVC.text = (cell.textLabel?.text)!
return detailVC

}
1
2
3
4
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
// self.show(viewControllerToCommit, sender: self)
self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
}

show 和 push都能展示出相同的效果

在显示的控制器中设置代码

在detailviewcontroller中需要返回出pop向上拉的选项。(也可以不实现)另外要为了要展示出数据,我在该视图控制器中添加了一个textview来展示数据。

1
2
3
self.title = "详情"
self.automaticallyAdjustsScrollViewInsets = false
self.textView.text = text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
override var previewActionItems: [UIPreviewActionItem]{

let action1 = UIPreviewAction.init(title: "喜欢", style: .default) { (UIPreviewAction, UIViewController) in
}

let action2 = UIPreviewAction.init(title: "收藏", style: .default) { (UIPreviewAction, UIViewController) in

}

let cancle = UIPreviewAction.init(title: "取消", style: .default) { (UIPreviewAction, UIViewController) in

}

let delete = UIPreviewAction.init(title: "删除", style: .destructive) { (UIPreviewAction, UIViewController) in

}

let actionGroup = UIPreviewActionGroup.init(title: "删除", style: .destructive, actions: [cancle,delete])

return [action1, action2 ,actionGroup]
}

返回的数组中存的是UIPreviewAction。这个数组可以是个二维数组,所以可以展示出很多选项。例子中返回的就是一个二维数组。

最后

到此整个效果的代码都设置完了。接下来运行程序,看看我们的成果吧:

3D- Touch.gif

3D - Touch(一) 桌面

发表于 2016-09-23   |   分类于 Swift   |   阅读次数

桌面3D - Touch

快捷静态操作(Quick actions)

需要在 info.plist中配置

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
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeShare</string>
<key>UIApplicationShortcutItemTitle</key>
<string>弹一弹</string>
<key>UIApplicationShortcutItemType</key>
<string>com.yuwubao.search</string>
</dict>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeShare</string>
<key>UIApplicationShortcutItemTitle</key>
<string>摇一摇</string>
<key>UIApplicationShortcutItemType</key>
<string>com.yuwubao.search</string>
</dict>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeShare</string>
<key>UIApplicationShortcutItemTitle</key>
<string>扫一扫</string>
<key>UIApplicationShortcutItemType</key>
<string>com.yuwubao.search</string>
</dict>
</array>

关于几个必须要填写的项:

  1. UIApplicationShortcutItemTitle: 表示要显示的标题。展示在你的quick action菜单中的action标题。如果标题一行无法显示并且你没有指定子标题那么它将显示两行。可以使用本地化(localised)。
  2. UIApplicationShortcutItemType: 作为UIApplicationShortcutItem的一部分发送给你的应用。可以依据不同的shortcut类型用于执行你的actions。命名规则为: com.公司名.app名.图标作用名

关于选填的项:

  1. UIApplicationShortcutItemIconType: 定义内置图标类型的字符串,可选类型列表可以查询这里
  2. UIApplicationShortcutItemSubtitle: 用户展示你的actions的子标题的字符串。它将显示在你的quick actions标题的下方。可以本地化。
  3. UIApplicationShortcutItemIconFile:一个指定Assets Catalog或者Bundle中的字符串。如果指定了此键,则系统会忽略UIApplicationShortcutItemIconType
  4. UIApplicationShortcutItemUserInfo:一个字典,包含你想要解析的其他信息。

第二步

在入口类文件(appDelegate)中

1
2
3
4
5
6
7
8
9
10
11
12
13
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

//检测版本
if UIDevice.current.systemVersion >= "9.0" {
let shortcutItem = launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem
if let shortcutItem = shortcutItem{
self.quickActionWithShortcutItem(shortcutItem: shortcutItem)
}

}

return true
}

还要实现另一个方法

1
2
3
4
5
//MARK: - 3D-Touch
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
self.quickActionWithShortcutItem(shortcutItem: shortcutItem)
completionHandler(true)
}

由于代码的冗余 需要定义一个私有的方法 可以根据
localizedTitle 或者 type 来区别点击的是哪个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private  func quickActionWithShortcutItem(shortcutItem: UIApplicationShortcutItem){
let nav = self.window?.rootViewController as? UINavigationController
if shortcutItem.localizedTitle == "弹一弹"{

}else if shortcutItem.localizedTitle == "摇一摇"{

let detailVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "detail") as! DetailViewController
nav!.pushViewController(detailVC, animated: true)

}else{

nav!.pushViewController(ThirdViewController(), animated: true)
}
}

到这里完全设置好了桌面图标的3D - Touch。 由于最近系统升级到了iOS10 桌面icon的3D - Touch 新增了widget。接下来就来时适配iOS10。

Extention

(更多信息移步到这里)(喵神博客)

Extensions不是独立的应用程序。Extensions必须依赖于一个host app,叫作宿主APP,同时他们的生命周期相互独立,并且可以互相触发事件。一个宿主APP可以包含多个Extensions。本篇文章主要是 Today Extention。创建方法 File->New->Target

QQ20160923-0@2x.png

工程中会多出这些文件

QQ20160923-1@2x.png

在MainInterface.storyboard中我们可以定制UI。

QQ20160923-3@2x.png

当我们想纯代码构建UI时,在上图显示的Info.plist中NSExtension需要将NSExtensionMainStoryboard删掉,解除与storyboard的关联

例子中用的storyboard构建UI。 当我们需要与APP通信时。需要用到 URL Shchemes。

首先给label添加手势

1
2
widgetLabel.addGestureRecognizer(UITapGestureRecognizer.init(target: self
, action: #selector(TodayViewController.widgetLabelAction)))
1
2
3
@objc private  func widgetLabelAction() -> Void {
extensionContext?.open(NSURL(string: "simple://finished") as! URL, completionHandler: nil)
}

设置URL Schemes

QQ20160923-4@2x.png

运行程序

IMG_0609.PNG

我们也可以在widget中添加自己的APP显示信息了

Swift基础

发表于 2016-09-20   |   分类于 Swift   |   阅读次数

stride与循环结构

区间运算符
开区间:[a,b]
闭区间:[a,b)
举例:
1.开区间

1
2
3
for index in 1..<10{
index;
}

index的值一次为:0~9;可以用此方法遍历数组。比如:

1
2
3
4
5
6
var scoreArr = [22,33,44,55,66,77,88,99];
var count = scoreArr.count;
for index in 0 ..< count{
var s = scoreArr[index];
print(s);
}

2.闭区间

1
2
3
for index in 1...10{
index;
}

index的值以此为:0~10

在swift3.0中stride语法已经改为这样:stride(from: , to: , by: )函数和stride(from: , through: , by: )函数

stride 方法定义在 Strideable 协议中,swift3.0废弃了传统C的for循环之后,定义的全新方法。
stride(from: , to: , by: )相当于开区间;
stride(from: , through: , by: )相当于闭区间
个人理解:
表示从初始数值到目标数值,by:表示跨越的进度(可加可减)。
举例:

1
2
3
for index in stride(from: 10, through: 0, by: -1){
print(index);
}

屏幕快照 2016-09-07 下午10.03.33.png

1
2
3
for index in stride(from: 10, to: 0, by: -1){
print(index);
}

index的数值:
index –10
index –9
index –8
index –7
index –6
index –5
index –4
index –3
index –2
index –1

用stride方法遍历scoreArr数组

1
2
3
4
for i in stride(from: 0, to: scoreArr.count, by: 1){
var arr = scoreArr[i];
print(arr);
}

多种方法使tableView的Header下拉放大

发表于 2016-09-20   |   分类于 Objective-C   |   阅读次数

前言

看了峥吖同学的这篇文章【一行代码快速集成tableView头部缩放视图】之后 。想着自己用其他的方法来实现这一效果,于是乎想到

1
CGAffineTransformMakeScale

这一方法。

效果图

下拉放大.gif

开始实现

在自己写的过程中发现了一些问题, 直接把

1
self.tableView.tableHeaderView = self.imageView

之后并不能达到想要的效果。整张图片frame都随着tableview的拖动而改变。并不是像是固定在那里。tableview的顶部会出现大部分空白。然后我仔细看了一遍源码。发现做法是

1
[self.tableView insertSubview:imageView atIndex:0];

接着把一个透明view填充到tableview的header view中。

1
2
3
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];    
headerView.backgroundColor = [UIColor clearColor];
self.tableView.tableHeaderView = headerView;

找到这一技巧之后。自己写了一个稍微简单的demo。

1
2
3
4
5
6
7
8
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"header"]];
imageView.frame = CGRectMake(0, 0, self.view.frame.size.width, imageViewH);
[self.tableView insertSubview:imageView atIndex:0];
self.imageView = imageView;

UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, imageViewH)];
headerView.backgroundColor = [UIColor clearColor];
self.tableView.tableHeaderView = headerView;

在

1
- (void)scrollViewDidScroll:(UIScrollView *)scrollView

方法中这么写:

1
2
3
4
5
6
CGFloat offsetY = scrollView.contentOffset.y;
if (offsetY < 0) {
self.imageView.frame = CGRectMake(offsetY, offsetY, scrollView.bounds.size.width - offsetY * 2, imageViewH - offsetY);
} else {
self.imageView.frame = CGRectMake(0, 0, scrollView.bounds.size.width, imageViewH);
}

原理一模一样,拿到scrollview的偏移量计算下拉imageview的frame,使其imageview的宽高增大。上拉的时候恢复原来的frame。

另一种方法

还是在

1
- (void)scrollViewDidScroll:(UIScrollView *)scrollView

方法中拿到scrollview的偏移量计算缩放系数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CGFloat offsetY = scrollView.contentOffset.y + scrollView.contentInset.top;
CGFloat scale = 1.0;
if (offsetY < 0) {
//向下拉
scale = MIN(2.5, 1 - offsetY / imageViewH);
self.imageView.transform = CGAffineTransformMakeScale(scale, scale);
CGRect frame = self.imageView.frame;
frame.origin.y = offsetY;
self.imageView.frame = frame;
}else if(offsetY > 0)
{
//向上拉
CGRect frame = self.imageView.frame;
frame.origin.y = -offsetY/imageViewH;
self.imageView.frame = frame;
}

再向上拉的过程中要保证imageview不会进行缩放,只是改变下imageview的y轴的值。

最后

感谢峥吖同学提供的思路。demo地址:戳我

12
Hello Li

Hello Li

14 日志
6 分类
5 标签
GitHub
© 2018 Hello Li
由 Hexo 强力驱动
主题 - NexT.Pisces