UITouch
之所以先說UITouch是因為從Peek到Pop這個過程中,相信其內(nèi)部用到了這個東西,我們來看一下iOS9在這個UITouch中加了哪些東西:
- UIForceTouchCapability
- UIForceTouchCapabilityUnknown //3D Touch檢測失敗
- UIForceTouchCapabilityUnavailable //3D Touch不可用
- UIForceTouchCapabilityAvailable //3D Touch可用
這3個枚舉值就是我們來判斷設(shè)備是否開啟3D Touch功能,可以在UIViewController生命周期的viewWillAppear中我們是這么判斷的:
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
{
xxxxxxxx
}
當然在生命周期內(nèi),如果用戶有意修改了設(shè)備的3D Touch功能,我們還有一個地方來重新檢測:
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
剛剛說了Peek和Pop和這個有關(guān),對的,就是這個類中的force屬性以及他的最大值maximumPossibleForce,我們在UIView上做一個簡單的實驗
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
UITouch *touch = [touches anyObject];
NSLog(@"%f",touch.force);
self.backgroundColor = [UIColor colorWithRed:(touch.force / touch.maximumPossibleForce )green:0 blue:1 alpha:1];
}
按的越重,這個view的red就越大
為了得到maximumPossibleForce值,我故意在這個函數(shù)中加上了
if (touch.force == touch.maximumPossibleForce)
{
NSLog(@"%f",touch.force);
}
輸出發(fā)現(xiàn)當3D touch開的時候這個值為20/3,所以得到結(jié)論force是從0~20/3
從Peek到Pop也正是根據(jù)這個值大于某個指定的值時觸發(fā)
Peek & Pop
剛剛說了Peek和Pop的觸發(fā)和UITouch的force有關(guān),在切入正題之前我們還要將觸發(fā)這2個事件的另一個東西:
previewActionItems
我們創(chuàng)建一個PeekViewController,在這個利用到了UIPreviewAction 和 UIPreviewActionGroup 2個iOS9新加的類型和他們的初始化方法我們重寫
- (NSArray <id <UIPreviewActionItem>> *)previewActionItems
從而來定義previewActionItems,這里沒什么難度直接上代碼
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems
{
// 生成UIPreviewAction
UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"Action 1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Action 1 selected");
}];
UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"Action 2" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Action 2 selected");
}];
UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"Action 3" style:UIPreviewActionStyleSelected handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Action 3 selected");
}];
UIPreviewAction *tap1 = [UIPreviewAction actionWithTitle:@"tap 1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"tap 1 selected");
}];
UIPreviewAction *tap2 = [UIPreviewAction actionWithTitle:@"tap 2" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"tap 2 selected");
}];
UIPreviewAction *tap3 = [UIPreviewAction actionWithTitle:@"tap 3" style:UIPreviewActionStyleSelected handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"tap 3 selected");
}];
// 塞到UIPreviewActionGroup中
NSArray *actions = @[action1, action2, action3];
NSArray *taps = @[tap1, tap2, tap3];
UIPreviewActionGroup *group1 = [UIPreviewActionGroup actionGroupWithTitle:@"Action Group" style:UIPreviewActionStyleDefault actions:actions];
UIPreviewActionGroup *group2 = [UIPreviewActionGroup actionGroupWithTitle:@"Action Group" style:UIPreviewActionStyleDefault actions:taps];
NSArray *group = @[group1,group2];
return group;
}
我們發(fā)現(xiàn)他是一個二維結(jié)構(gòu),所以能展示的東西還是非常多的。
好了準備工作到此結(jié)束,我們切入正題
在ViewController中,創(chuàng)建一個label作為觸發(fā)的view
_label = [[UILabel alloc] initWithFrame:CGRectMake(10, 300, self.view.frame.size.width - 20, 100)];
_label.userInteractionEnabled = YES;
_label.textAlignment = NSTextAlignmentCenter;
_label.backgroundColor = [UIColor yellowColor];
_label.font = [UIFont boldSystemFontOfSize:20];
_label.text = @"Peek && Pop";
[self.view addSubview:_label];
然后檢測是否可以使用3DTouch,如果可以就注冊:
- (void)check3DTouch
{
// 如果開啟了3D touch
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
{
[self registerForPreviewingWithDelegate:(id)self sourceView:_label];
}
}
最后我們來寫Peek和Pop的代理方法
- peek:
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
//防止重復(fù)加入
if ([self.presentedViewController isKindOfClass:[PeekViewController class]])
{
return nil;
}
else
{
PeekViewController *peekViewController = [[PeekViewController alloc] init];
return peekViewController;
}
}
這個代理在按的過程中會進來多次,但是我們并不需要多個peek對象,所以如果觸發(fā)的self.presentedViewController和我們想要的peekViewController已經(jīng)是同一個了,那就return nil,我們按label在出現(xiàn)peekViewController的時候向上移動我們能看到剛剛創(chuàng)建的previewActionItems的2個group
點開一個就能看到我們沒個group的items
點擊就會觸發(fā)我們剛剛在block中定義的事件
- Pop:
在Peek的基礎(chǔ)上不要向上移動,而是按得更重一些,個人感覺已經(jīng)到了maximumPossibleForce這個時候觸發(fā)代理:
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
{
PopViewController *popViewController = [[PopViewController alloc] init];
[self showViewController:popViewController sender:self];
}
這時候我們看到了PopViewController
當然我們在PopViewController還需要給他加個dismiss的方法,讓他可以回去
好了,官方說的所有3D Touch的功能都介紹好了,這是我的Demo