本文是投稿文章,作者:標哥(微博:標哥的技術博客)
概述
HYBControllerTransitions是自定義圍場動畫API封裝類庫,使用簡便。使用者不需要了解太多轉場動畫知識,即可輕松接入項目使用。
這是一個給開發者們提供自定義push、pop、dismiss和present轉場動畫的開源組件。現在庫中支持泡泡放大縮小圍場、模態半屏轉場和移動切換轉場(KeyNote某轉場效果)。對於開發者們來說,這是一個很不錯的開源庫。開發者不需要了解轉場知識,只需要簡單一個API就可以實現對應的功能。
如果想要更深入地學習,請在源碼中查看對應的注釋說明!
開源目標
在設計此類庫時,希望以最簡潔的API來實現轉場功能。如果不懂任何轉場知識的人,也能輕松使用,那才算達到目標。
因此,如果您沒有學習過相關轉場方面的知識,請不要擔心,這個類庫不需要您掌握太多轉場的知識,只需要懂基本的OC語法即可輕松接入項目使用。
公共的屬性及API都封裝在HYBBaseTransition類型中,它遵守了需要實現轉場的所有協議並實現之。如果目前類庫中所提供的效果不滿足您的需求,您可以直接繼承於HYBBaseTransition於實現您希望得到的效果。
支持彈簧動畫效果
默認轉場動畫使用的不是彈簧動畫效果,如果覺得彈簧動畫效果更佳,僅需要設置為YES即可。
/** * Default is NO, if set to YES, it will be presented and dismissed with * spring animation. */ @property (nonatomic, assign) BOOL animatedWithSpring;
當然,使用到彈簧自然需要設置其參數。不過作者都提供有默認值,都是經過調試過得到的值。如果覺得默認值所得到的效果不夠好,請自行調整參數:
/** * The initial Spring velocity, Only when animatedWithSpring is YES, it will take effect. * Default is 1.0 / 0.5. If you don't know, just use the default value. */ @property (nonatomic, assign) CGFloat initialSpringVelocity; /** * The Spring damp, Only when animatedWithSpring is YES, it will take effect. * * Default is 0.5. If you don't know, just use the default value. */ @property (nonatomic, assign) CGFloat damp;
轉場類型動畫
目前所支持的動畫效果有以下:
Bubble Effect Transition:泡泡放大、縮小的動畫效果,僅支持模態呈現present/dismiss。
Modal Effect Transition:半屏呈現轉場,支持設置縮放系數、呈現高度等,僅支持模態呈現present/dismiss。
Move Push/Pop Transition:移動切換轉場效果,僅支持push/pop模式。
Buble Effect Transition
present時,以泡泡圓形放大;dismiss時,以泡泡圓形縮小至起點。當需要實現此轉場效果時,請使用HYBBubbleTransition類型。效果圖如下:
如何使用
使用起來非常簡單,只需要一個API且只在一處調用即可。比如,現在有HYBModalBubbleViewController,它有一個點擊事件,在點擊後會回調onPresent函數,然後配置如下即可實現轉場:
- (void)onPresent { HYBBubbleFromBottomController *vc = [[HYBBubbleFromBottomController alloc] init]; vc.modalPresentationStyle = UIModalPresentationCustom; // Remember to own it strongly // Because delegate is weak reference, and it will be released after out of the function body. self.bubbleTransition = [[HYBBubbleTransition alloc] initWithPresented:^(UIViewController *presented, UIViewController *presenting, UIViewController *source, HYBBaseTransition *transition) { // You need to cast type to the real subclass type. HYBBubbleTransition *bubble = (HYBBubbleTransition *)transition; // If you want to use Spring animation, set to YES. // Default is NO. // bubble.animatedWithSpring = YES; bubble.bubbleColor = presented.view.backgroundColor; // 由於一個控制器有導航,一個沒有,導致會有64的誤差,所以要記得處理這種情況 CGPoint center = [self.view viewWithTag:1010].center; center.y += 64; bubble.bubbleStartPoint = center; } dismissed:^(UIViewController *dismissed, HYBBaseTransition *transition) { // Do nothing and it is ok here. // If you really want to do something, here you can set the mode. // But inside the super class, it is set to be automally. // So you do this has no meaning. transition.transitionMode = kHYBTransitionDismiss; }]; vc.transitioningDelegate = self.bubbleTransition; [self presentViewController:vc animated:YES completion:NULL]; }
這裡會present HYBBubbleFromBottomController這個控制器類,但是HYBBubbleFromBottomController對象什麼也不需要做,就可以直接實現了轉場。
是不是真的很簡單呢?
如果想要了解更多功能功能,請在源代碼中查看類中所提供的所有公開屬性,幾乎都有默認值,若不需要修改,直接使用默認值就可以了。
注意事項:一定要將代理設置為對應的轉場類對象。而且一定要在當前控制器強引用該轉場類對象,因為設置為轉場代理,只是弱使用,如果沒有強引用,它就會被釋放掉:
// 代理不再是設置為self,而是設置為轉場對象 vc.transitioningDelegate = self.bubbleTransition;
Modal Effect Transition
當需要實現半屏呈現且帶縮放效果的轉場動畫時,可以使用此HYBModalTransition類。它僅支持present/dismiss模式。它提供了更多的屬性設置,稍候講解。效果如下:
如何使用
使用非常簡單。假設在HYBModalHalfController有一個點擊事件,點擊後會回調onPresent函數,只需要在此函數中實現即可:
- (void)onPresent { HYBModalHalfDetailController *vc = [[HYBModalHalfDetailController alloc] init]; self.transition = [[HYBModalTransition alloc] initWithPresented:^(UIViewController *presented, UIViewController *presenting, UIViewController *source, HYBBaseTransition *transition) { HYBModalTransition *modal = (HYBModalTransition *)transition; modal.scale = (CGPoint){0.95, 0.95}; // If you don't specify, it will use default value // modal.presentedHeight = 350.0; // If you don't want to, set to YES or do no set. modal.shouldDismissOnTap = YES; // Default is NO, if set to YES, it will use spring animation. modal.animatedWithSpring = YES; // Default is YES. including navigation bar when take snapshots. // When has navigation bar, if set to NO, it looks not so good. // modal.scapshotIncludingNavigationBar = NO; } dismissed:^(UIViewController *dismissed, HYBBaseTransition *transition) { // do nothing // 注釋掉也沒有關系,內部已經自動設置了。 transition.transitionMode = kHYBTransitionDismiss; }]; vc.transitioningDelegate = self.transition; [self presentViewController:vc animated:YES completion:NULL]; }
對於HYBModalHalfDetailController控制器類,什麼也不需要操作。這是不是有點太過於簡單了?對於dismissed這個block,其實這裡完全可以設置為nil,因為不需要做任何操作,默認就自動設置了mode。
支持帶導航截圖
如果當前控制器類有導航,最好還是連導航條也一起生成截圖,這樣效果會好很多。默認就是YES。如果不希望如此,請手動設置為N:
/** * Whether to include navigation bar when take snapshots. *Default is YES. If NO, it has only the presenting view. */ @property (nonatomic, assign) BOOL scapshotIncludingNavigationBar;
支持手勢點擊自動Dismiss
在彈出來之後,默認是添加了點擊手勢,可以自動dismiss。默認為YES,如果不希望如此,請手動設置為NO:
/** *When tap on the presenting view, should it automatically is dismissed. * * Default is YES. */ @property (nonatomic, assign) BOOL shouldDismissOnTap;
支持設置縮放、高度
都提供了默認值,但是如果想要調整到一個讓您滿意的效果,也許這些屬性就可以幫助您實現:
/** *Make the from view scale to the specified scale. * * Default is (0.9, 0.9) */ @property (nonatomic, assign) CGPoint scale; /** *The height for destination view to present. * * Default is half of destination view, it means desView.frame.size.height / 2 */ @property (nonatomic, assign) CGFloat presentedHeight;
Move Push/Pop Transition
類似於KeyNote的神奇移動效果push、pop動畫。效果圖如下:
使用起來也是很簡單的,不同於present/dismiss模式,由於push的時候還不能得到轉場過去的目標視圖,比如效果圖中的切換過去後看到的圖片控件。在創建控制器類的時候,控件是不存在的,因此只能使用其它的辦法來實現。
這裡所采用的方案是通過給UIViewController添加擴展屬性,如此就可以在創建UI的地方,將目標控件賦值。擴展所添加的屬性為:
/** * Set a target view to show. When push, it will transition to * the target view. and when poped, it will pop from the target view. */ @property (nonatomic, strong, nonnull) UIView *hyb_toTargetView;
如何使用
假設當前控制器類為HYBMoveViewController,它有一個collectionview,呈風格布局顯示一個圖片列表。當點擊cell的時候,就切換(push)到HYBMoveDetailController控制器中顯示更多內容。
實現如下:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { HYBMoveDetailController *vc = [[HYBMoveDetailController alloc] init]; HYBGridModel *model = self.datasource[indexPath.item]; vc.image = model.clipedImage; self.transition = [[HYBMoveTransition alloc] initWithPushed:^(UIViewController *fromVC, UIViewController *toVC, HYBBaseTransition *transition) { HYBMoveTransition *move = (HYBMoveTransition *)transition; HYBGridCell *cell = (HYBGridCell *)[collectionView cellForItemAtIndexPath:indexPath]; move.targetClickedView = cell.imageView; move.animatedWithSpring = YES; } poped:^(UIViewController *fromVC, UIViewController *toVC, HYBBaseTransition *transition) { // Do nothing, unless you really need to. }]; self.navigationController.delegate = self.transition; [self.navigationController pushViewController:vc animated:YES]; }
在點擊的時候,需要創建一個轉場對象,然後我們將導航類的代理設置為這個轉場對象,如下:
self.navigationController.delegate = self.transition;
這樣就可以實現內部自動處理了。當push的時候,會回調pushed閉包,在這裡返回了轉場對象,需要提供相關屬性設置,才能實現。一定要傳targetClickedView屬性,這是被點擊的控件,也是用於切換效果用的。
在HYBMoveDetailController控制器中,在viewDidLoad這裡創建UI的地方,創建了一個圖片控件,然後如些設置:
// You must specify a target view with this. self.hyb_toTargetView = imgView;
OK,到此就實現好功能了!
是否足夠簡單?
如何安裝
支持pod,可直接使用pod添加以下代碼到Podfile中:
pod 'HYBControllerTransitions', '~> 1.0.0'
如果您的工程不支持Pod,呆直接將HYBControllerTransitions目錄放到您的工程中即可!
源代碼
如果不想使用pod來安裝,或者想要看看demo,請到此處下載:HYBControllerTransitions。
致謝
非常感謝andreamazz,學習了很多他的開源作品!