回到我们的iOS图书开放欢迎动画教程系列!
在本教程的第一个自定义程序中,您学习了如何创建应用视图展示部分中的和后续系列,以在您的中创建深度真实页面感。
在这部分中,将学习自定义导航并应用到一个以创建合集的方式,然后将您的学习内容打开。
入门
02.gif在 Xcode 中打开项目。现在,当您的行为一来打开教程的页面时,您就可以从本页面滑入。UINavigationController的默认转换。在但时,自定义的自定义过渡将如下所示:
03.gif自定义转换用户喜欢在关闭和打开状态之间的自然方式为设置动画。
是时候开始了!
创建您的自定义导航控制器
要在远程或您弹出上单击自定义转换,必须创建自定义导航控件并实现UINavigationControllerDelegate
。
iOS\Source\Cocoa Touch 类将新文件命名为 CustomNavigationController 。确保它是UINavigationController的子类和语言为斯威夫特。单击,然后单击创建。
打开CustomNavigationController.swift将其内容替换为以下内容:
导入UIKit
类CustomNavigationController : UINavigationController , UINavigationControllerDelegate {
覆盖func viewDidLoad () {
super .viewDidLoad()
//1
委托=自己
}
//2
func navigationController ( navigationController : UINavigationController , animationControllerForOperation operation : UINavigationControllerOperation , fromViewController fromVC : UIViewController , toViewController toVC : UIViewController ) -> UIViewControllerAnimatedTransitioning ? {
如果操作==。推{
返回零
}
如果操作==。流行{
返回零
}
返回零
}
}
这是您的代码中的任何事项:
- 在
viewDidLoad
您自己将向导设置为自己的委托。 -
navigationController(_:animationControllerForOperation:fromViewController:toViewController:)
您可以在当前视图的控制方法或标准转换时执行此命令,并且您的返回代码可以是从返回的方法之一UINavigationControllerDelegate
。快将替换为您自己的自定义转换对象。nil
现在你已经设置了自定义导航控制器,是替换板中的默认导航控制器时候的故事了。
打开 Main.storyboard并单击左侧故事板视图系列结构中的导航控制器。接下来,单击Identity Inspector在Custom Class下,将UINavigationController更改为CustomNavigationController,如下所示:
04.png您制造并运行以确保一切正常;自从返回nil
委托方法后,什么都不会改变,该方法默认为导航系统的标准转换。
创建自定义过渡
是时候进入有趣的部分了——制造你的自定义过渡对象!:]
使用自定义方法过渡对象,您创建的必须类的UIViewControllerAnimatedTransitioning协议,特别是符合以下条件:
- 过渡动画的持续时间:必须同步返回。
- animateTransition:必须。提供您正在转换的此程序。多种繁重的工作将在中完成。
- 动画结束:任选。过渡完成时通知您。您可以在此方法中执行所需的采集。
你设置的过渡
iOS\Source\Cocoa Touch Class模板将新文件命名为BookOpeningTransition 。确保它是NSObject的子类和语言斯威夫特。单击,然后单击创建。
打开BookOpeningTransition.swift将其内容替换为以下内容:
导入UIKit
//1
类BookOpeningTransition : NSObject , UIViewControllerAnimatedTransitioning {
// MARK: 存储的属性
var transforms = [ UICollectionViewCell : CATransform3D ]() //2
var toViewBackgroundColor: UIColor ? //3
var isPush = true //4
//5
// MARK: UIViewControllerAnimatedTransitioning
func transitionDuration ( transitionContext : UIViewControllerContextTransitioning ) -> NSTimeInterval {
返回1
}
func animateTransition ( transitionContext : UIViewControllerContextTransitioning ) {
}
}
查看每个评论部分:
-
BookOpeningTransition
实现UIViewControllerAnimatedTransitioning
协议所需的方法。 - 字典
transforms
存储键值对,其中键是一个单元UICollectionViewCell
,值是类型CATransform3D
。该字典在打开时跟踪每个格的页面转换。 - 这定义了您过渡到的颜色,这变淡看起来更干净。
- 布尔值
isPush
确定是消费者还是发起, - 在这里,您需要的方法是错误的添加
UIViewControllerAnimatedTransitioning
;您很快就会实现这些方法。
现在你已经设置了变量,是时候实现协议的方法了。
将把的内容替换为transitionDuration(_:)
以下内容:
如果是推{
返回1
} 无论如何{
返回1
}
transitionDuration(_:)
返回转换动画的持续时间。在这种情况下,它在广泛或现时您希望使用 1 秒。这种方式可以让您轻松更改下或启动的时间。
您需要实现第二个必须的传送协议——animateTransition
魔法将发生的地方!:] 您将分两部分实现:
-
animateTransition
辅助方法来安装。 -
animateTransition
实现辅助方法来设置pop。
创作创作转换
形象自己在现实生活中打开一本书:
05.png虽然很复杂,但您只需要考虑动画的状态,让我们UIView
的方法animateWithDuration
如下处理状态之间的动画:
- 第一阶段是书合上的时候。
- 第 2 阶段是打开书本的时候;这本上是您在本教程第 1 部分中创建的转换。
animateTransition(_:)
首先,在协议方法之前,您将有一些辅助方法来处理这种实现状态。
在BookOpening中,将下面的代码添加到类中:Transition.swift
// MARK: 辅助方法
func makespectiveTransform () -> CATransform3D {
var Transform = CATransform3DIdentity
Transform.m34 = 1.0 / - 2000
返回变换
}
代码返回一个变换,并在 z 轴上添加透视图。稍后将在使用期间帮助您动画转换您的视图。
状态 1 – 已关闭的书
,在后面添加以下代码makePerspectiveTransform
:
func closePageCell(变换格:BookPageCell) {
// 1
var = self .makePerspectiveTransform ()
// 2
如果cell.layer.anchorPoint.x == 0 {
// 3
变换= CATransform3DRotate (变换, CGFloat ( 0 ), 0 , 1 , 0 )
// 4
变换= CATransform3DTranslate (transform, - 0.7 * cell.layer.bounds.width / 2 , 0 , 0)
// 5
变换= CATransform3DScale (变换, 0.7 , 0.7 , 1 )
}
// 6
别说{
// 7
变换= CATransform3DRotate (变换, CGFloat ( - M_PI ), 0 , 1 , 0 )
// 8
变换= CATransform3DTranslate (变换, 0.7 * cell.layer.bounds.width / 2 , 0 , 0 )
// 9
变换= CATransform3DScale (变换, 0.7 , 1 )
}
//10
cell.layer.transform =变换
}
回想一下,BookViewController是页面的集合视图。您的页面以实现与书脊方法的集合视图,并在轴上旋转它以关闭翻页效果。(或页面)转换为适合的并适合的书籍封面。
这是的转换快速说明:
06.png下面是实现这一点的代码的解释:
- 使用您之前创建的辅助方法初始化一个新的转换。
- 检查单元是否为正确。
- 如果是这样,基于它的立场设置为以0开放管理。
- 将图片移到封面的中心。
- 将x和y上的缩放比例0.7。回想一下,您在上一个教程中将封面人物缩放到0.7,以防您想知道这个神奇的数字来自哪里。
- 如果格不是标签页,它必须是左侧页面。
- 将左侧页面的位置设置为180。因此,您希望将其到书页的位置是平坦的。
- 将页面移动到背后的中心。
- 将页面缩放回0.7。
- 最后,设置单元格的变换。
现在在上面添加的方法下面添加方法:
func setStartPositionForPush ( fromVC : BooksViewController , toVC : BookViewController ) {
// 1
toViewBackgroundColor = fromVC.collectionView ? 。背景颜色
toVC.collectionView ? .backgroundColor = nil
//2
fromVC.selectedCell() ? .alpha = 0
//3
对于 toVC.collectionView !.visibleCells() 的单元格为![书页细胞变换] {
//4页
细胞变换[.transform] = cell.layer
//5
关闭页面单元格(unitg)
cell.updateShadowLayer()
//6
如果让 indexPath = toVC.collectionView ? .indexPathForCell(细胞) {
如果 indexPath.row == 0 {
cell.shadowLayer.opacity = 0
}
}
}
}
setStartPositionForPush(_:toVC:)
设置过渡的第 1 个阶段。它需要两个视图来制作动画:
-
fromVC
,BooksViewController类型,让您滚动浏览您的书籍列表。 -
toVC
,属于BookView类型,可以让您翻阅选择书籍控制器的页面。
这是这段代码中发生的事情:
-
存储BooksViewController的视图的背景颜色,并将BookViewController的集合视图背景设置为集合
nil
。 - 隐藏的精选图像封面。
toVC
现在将处理封面的显示。 - 循环浏览书页。
- 将每个页面的当前转换保存在其打开状态。
- 书籍从状态开始,将会将页面关闭转换为关闭并更新您的图层。
- 最后,加载图像的承载。
状态2——打开的书
现在您已经完成了状态 1 的转换,您可以继续进行状态 2,从合上的书到打开的书。
在下面添加以下方法setStartPositionForPush(_:toVC:)
):
func setEndPositionForPush ( fromVC : BooksViewController , toVC : BookViewController ) {
//1
对于 fromVC.collectionView !.visibleCells() 中的单元格为![ BookCoverCell ] {
单元格.alpha = 0
}
//2
对于 toVC.collectionView !.visibleCells() 中的单元格为![书页] {
cell.layer.transform = [细胞]!
cell.updateShadowLayer(动画:真)
}
}
深入研究的代码:
- 隐藏书籍封面,因为您正在展示所有精选书籍的页面。
- 在 BookViewController中保存浏览书籍的页面并加载先前的打开转换。
从BooksViewController追踪到BookController之后,需要进行一些收拾工作。
在上面添加的方法之后添加下面的方法:
func cleanupPush ( , toVCViewController , toVC ) {
将添加回的视图控制器: BookViewController 到背景
VC 。.backgroundColor = toViewBackgroundColor
}
在保存所有内容之后,您将看到 BookViewController集合的背景颜色设置为您的背景颜色隐藏在后面。
实施开书过渡
现在你已经有你的方法了,你已经准备好感应激活了animateTransition(_:)
!
//1
让容器= transitionContext.containerView()
//2
如果是推{
//3
让 fromVC = transitionContext.viewControllerForKey( UITransitionContextFromViewControllerKey ) 为!BooksViewController
让 toVC = transitionContext.viewControllerForKey( UITransitionContextToViewControllerKey ) 为!BookViewController
//4
container.addSubview(toVC.view)
// 执行过渡
//5
self .setStartPositionForPush(fromVC, toVC: toVC)
UIView .animateWithDuration( self .transitionDuration (transitionContext), delay: 0.0 , usingSpringWithDamping: 0.7 , initialSpringVelocity: 0.7 , options: nil , animations: {
//6
self .setEndPositionForPush(fromVC, toVC: toVC)
},完成:{完成于
//7
self .cleanupPush(fromVC, toVC: toVC)
//8
transitionContext.completeTransition(完成)
})
} 无论如何{
//流行音乐
}
这是发生的事情animateTransition(_:)
:
- 获取储物柜视图,查看其切换视图之间的超级棒。
- 如果您正在执行用户。
- 如果是这样,获取
fromVC
(BooksViewController) 和toVC
(BookViewController)。 - 将( BookViewController
toVC
)添加到包含视图。 - 为和从视图关闭设置的状态。
- 状态,您从状态(Opened State ) 动画到结束位置 ( Opened State )
- 执行任何收拾。
- 通知系统过渡完成。
将遥控转换应用到导航
现在您已经设置了浏览器,是时候将其应用您的自定义导航系统了。
打开 BooksViewController.swift并在类声明之后添加以下属性:
var过渡:BookOpeningTransition
属性跟踪您的转换是现在让您知道的转换。
在结束大括号后添加以下扩展名:
扩展BooksViewController {
func animationForPresentController ( vc : UIViewController ) -> UIViewControllerAnimatedTransitioning? {
// 1
var过渡= BookOpeningTransition ()
// 2
过渡.isPush = true
// 3
self .transition =过渡
// 4
返回过渡
}
}
这将用于创建代码与设置的相关方法部分,在这种情况下,您希望将其扩展为一个分组。
仔细看一下代码:
- 创建一个新的过渡。
- 您正在展示自己的风格,或者因此设置
isPush
为true
- 保存暂时过渡。
- 返回过渡。
现在打开CustomNavigationController.swift将推送语句替换为以下内容:if
如果操作==。推{
如果让 vc = fromVC 作为BooksViewController {
返回 vc.animationControllerForPresentController(toVC)
}
}
这将检查您的调用控制器的控制器是否显示控制器,显示控制器的转换图书视图的:BookOpening。
并为您制作您的应用程序;打开您的选择运行,会从这本书看到的一个动画程序:
07.gif呃。。怎么没有动画?
08.png它直接从一本合上的书跳到一本打开的书,因为你还没有加载页面的单元格!
太阳从BooksViewController转换到BookViewController,它们都是UICollectionViewControllers。UICollectionView单元格不会在主线程上,因此导航时您的代码会在看到零个单元开始加载 - 并且没有任何动画!
您需要给集合视图的时间来加载所有单元格。
打开BooksViewController.swift并替换为以下内容:openBook(_:)
func openBook(书:书?) {
让 vc =故事板?.instantiateViewControllerWithIdentifier( "BookViewController" ) 为!BookViewController
vc.book = selectedCell() ? .book
//1
vc.view.snapshotViewAfterScreenUpdates( true )
//2
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self .navigationController ? .pushViewController(vc, 动画: true )
返回
})
}
下面是解决您问题的方法:
- 您告诉 BookViewController在合并更改后创建快照。
- 确保在主网上有BookViewController以使用单元时间加载。
再次构建并运行您的应用程序;您应该会看到这本书在每周正确的动画:
09.gif出现了很多!
您现在已经完成了转换,可以继续进行启动。
实现 Pop Helper 方法
舞台是画面与现在正在当前状态2现在正在开书。
10.png打开 BookOpeningTransition.swift并添加以下代码:
// MARK: 弹出窗口
函数 setStartPop ( from BookViewController : BookViewController ) { // sitionView从VC的视图
中删除背景
到VC.collectionViewController ? 。背景颜色
从VC.collectionView ?.backgroundColor = nil
}
setStartPositionForPop(_:toVC)
只需注意存储 BookViewController 的集合视图的颜色,并移除BookViewController的集合视图的。请注意,您无需设置单元转换,因为这本书当前显示任何背景状态。
setEndPositionForPop(_:toVC)
在上面刚刚添加的代码之后立即添加以下代码:
func setEndPositionForPop ( fromVC : BookViewController , toVC : BooksViewController ) {
//1
让coverCell = toVC.selectedCell()
//2
对于toVC.collectionView !.visibleCells() 中的单元格为![ BookCoverCell ] {
如果细胞!=覆盖细胞{
单位格.alpha = 1
}
}
//3
对于来自VC.collectionView !.visibleCells() 中的单元格为![书页] {
关闭页面单元格(unitg)
}
}
设置方法从打开到关闭此弹出转换的结束状态:
- 获取精选的书籍封面。
- 在关闭书本的状态下,遍历所有BooksViewController中的书皮并将它们全部淡化。
- 在BookViewController中循环当前书的所有页面,将单元格转换为关闭状态。
现在添加以下方法:
func cleanupPop ( , toVCView : toVCViewController ) {
将添加回BookController的ViewControllerfrom
背景VC。.backgroundColor = self .toViewBackgroundColor
// 取消隐藏原书封面
toVC.selectedCell() ? .alpha = 1
}
展开转换完成后,此会执行一些清理。过程显示将BooksViewController的方法视图背景设置原始状态和原始书籍封面。
现在在注释的代码块animateTransition(_:)
内的协议方法中添加以下代码:else``//POP
//1
让 fromVC = transitionContext.viewControllerForKey( UITransitionContextFromViewControllerKey ) 为!BookViewController
让 toVC = transitionContext.viewControllerForKey( UITransitionContextToViewControllerKey ) 为!BooksViewController
//2
container.insertSubview(toVC.view, belowSubview: fromVC.view)
//3
setStartPositionForPop(fromVC, toVC: toVC)
UIView .animateWithDuration(self .transitionDuration (transitionContext),动画:{
//4
self .setEndPositionForPop(fromVC, toVC: toVC)
},完成:{完成于
//5
self .cleanupPop(fromVC, toVC: toVC)
//6
transitionContext.completeTransition(完成)
})
下面是pop过渡动画的工作原理:
- 获取过渡是中涉及的视图控制器。
fromVC
现在是BookViewController(打开的书本状态),toVC
是BooksViewController(关闭的书本状态)。 - 在包含视图中的BookViewController栏目中添加BooksViewController 。
-
setStartPositionForPop(_:toVC)
将其设置为之前存储的背景颜色nil
。 - 从打开的书本状态动画到合上的书本状态。
- 动画完成后,通过将背景颜色设置回其原始颜色,并通过封面来展示画作。
- 通知过渡完成。
将 Pop 过渡应用到导航系统
现在您需要设置转换设置选项。
打开 BooksViewController.swift并在后面添加以下方法animationControllerForPresentController(_:)
:
func animationControllerForDismissController ( vc : UIViewController ) -> UIViewControllerAnimatedTransitioning? {
var过渡= BookOpeningTransition ()过渡
.isPush = false
self.transition =过渡
返回过渡
}
这再次创建了一个新的BookingTransition,但唯一的区别是转换现在设置为启动。
现在打开CustomNavigationController.swift将弹出语句替换为以下内容:if
如果操作==。流行{
如果让 vc = toVC 为?BooksViewController {
返回 vc.animationControllerForDismissController(vc)
}
}
这将返回过渡并执行动画以关闭本书。
制作并运行您的应用程序;选择一本书以查看它的打开和关闭,如下所示:
11.gif创建导航网
但你的过渡动画看起来很不错—— !
首先,打开BookOpeningTransition.swift并添加以下属性:
// MARK : 使用Transfer
varactive:UIPercentDrivenInteractive?
打开CustomNavigationController.swift并添加以下代码:
func navigationController ( navigationController : UINavigationController , interactionControllerForAnimationController animationController : UIViewControllerAnimatedTransitioning ) -> UIViewControllerInteractiveTransitioning? {
如果让动画工程师=动画工程师为?BookOpeningTransition {
返回动画教程。
}
返回零
}
在上面的中,您从BookOpeningTransition
。这导航系统可以使用监视动画的模式,以便用户可以使用工具制作工具或合上一个。
现在打开BooksViewController.swifttransition
并在变量下添加以下属性:
//1
变量驱动程序:UIPercentInteractiveTransition
?UIGestureRecognizer ? {
设置{
如果让识别器=识别器{
集合视图?.addGestureRecognizer(识别器)
}
}
}
这就是您添加这些变量的原因:
-
interactionController
是类UIPercentDrivenInteractiveTransition
的控件,它可以在控件之间使用动画转换进出类型,使用工具还可以实现,它是一个应用在一个应用程序之间UIViewControllerTransitioning的自定义对象。您已经创建了协议BookOpeningTransition — 正是支持的!iteractionController
可以文档控制其工作和请求显示此控制器之间的关联。了解有关课程的更多信息,阅读Apple 的相关原理的相关信息。 -
recognizer
是一个UIGestureRecognizer。您将使用一个识别器来捏合这本书。
现在在 BooksViewController扩展的transition.isPush = true
行下添加以下代码段:animationControllerForPresentController(_:)
交互控制器
= transition.interactionController
让您的导航工具知道如何使用您的定制工具。
将相同的代码添加到animationControllerForDismissController(_:)
,下transition.isPush = false
:
交互控制器
= transition.interactionController
将以下代码添加到viewDidLoad()
:
识别器= UIPinchGestureRecognizer(目标:自我,动作: “handlePinch:”)
这会初始化一个UIPinchGestureRecognizer,它允许用户操作方法执行捏合handlePinch(_:)
。
像这样执行下面的动作viewDidLoad()
:
// MARK: 识别动作
func handlePinch:UIPinchestureRecognizer) {
切换识别器.state {
案例.开始:
//1替代驱动
器InteractiveTransition ()
//如果器
.view = View { //3
如果器.view = View {
//
4 var book = self -selectedCell ( ) .book
//5 self .openBook(书)
}
//6
} 无论如何{
//7
导航控制器?.popViewControllerAnimated(真)
}
案例.更改:
//8
如果过渡!.isPush {
//9
var progress = min ( max ( abs ((recognizer.scale - 1 )) / 5 , 0 ), 1 )
//10
替代品?.updateInteractiveTrans(提醒)
//11
} 无论如何{
//12
var progress = min ( max ( abs (( 1 - Recognizer .scale)), 0 ), 1 )
//13
替代品?.updateInteractiveTrans(提醒)
}
案例结束:
//14
替代品?.finishInteractive Transition()
//15个
资源=无
默认:
休息
}
}
UIPGestureRecognizer ,您将跟踪不同的状态。状态开始您紧缩何时开始。状态更改了检测捏合的变化,并结束让您知道捏合何时结束。
您的代码实现的概要handlePinch(_:)
如下:
开始状态
- 实例化一个UIPercentDrivenInteractiveTransition对象。
- 如果另一种夹点距离大于或之间的相似
1
。 - 如果是这样,请确保您所看到的视图是集合视图。
- 抓住被捏的书。
- 执行BookViewController的发布以显示书的页面。
- 如果规模
1
…… - …执行BookViewController的pop以再次显示书籍封面。
改变状态——捏合时
- 查看当前是否转换正在执行推送。
-
如果正在您的用户到BookController ,必须获取您
progress
的捏合样式。查看和之间。将捏捏缩小缩小其一个的五分之一;这使得打开一本使过渡。否则书会立即跳到打开状态。progress``0``1
- 根据您计算之前的更新已经完成的转换。
- 如果没有触发触发,那么它现在必须触发。
- 合上书本时,必须从1变成。
- 最后,更新最后。
结束状态 - 停止捏合
- 通知系统转换的用户已注册。
- 将工具用于
nil
。
因此,您必须将状态提交给控制器,以便它可以自行启动。
打开BookViewController.swiftbook
,并在变量下添加以下属性:
变量识别器:UIGestureRecognizer? {
设置{
如果让识别器=识别器{
集合视图?.addGestureRecognizer(识别器)
}
}
}
每当您在BookViewController中的设置立即识别器中,该显示将添加到集合中,以便您可以在用户合上本本时跟踪合合时的内容。
,您需要在Book和BookViewController之间以及ViewController之间。
打开BookOpenTransition.swift设置。随后添加到cleanUpPush(_:toVC)
您的设置背景点:
// 转移识别器
toVC.recognizer = fromVC.recognizer
BooksViewController将携带到BookViewController传递到BookViewController ,然后将捏合类型。
当您从BookViewController弹出到BooksViewController的时候,您必须将捏合传回。
移动到cleanUpPop(_:toVC)
设置背景颜色之后:
// 转移识别器
toVC.recognizer = fromVC.recognizer
构建并运行您的应用程序;任何一本书并使用捏合选择打开并关闭这本书:
12.gif捏合也是打开和关闭的自然机制;这是一个捡漏的机会。
打开 Main.storyboard,选择Custom Navigation View Controller,打开 Attributes Inspector 并取消取消显示 Navigation Controller部分下的Bar Visibility ,如下:
13.png再次构建并运行您的应用程序:
14.gif结论
您可以使用教程中的所有代码部分下载最终项目。
在教程中如何自定义应用程序,您还提供了更多的学习视图,以便用户使用更自然、更方便地使用本教程创建自定义应用程序,并使用本教程来创建和合上应用程序您的应用程序同时解决了相同的基本问题,并应用了更多的个性化程序,它从其他应用程序中应用程序帮助。
使用默认的“缓入/缓出”动画更?好吧,您可以考虑开发一些时间。但是最好的应用程序有额外的定制润色,使它们的发光效果。每个人都记得他们下载的使用很有趣的应用程序;你知道,那些给你带来一点UI刺激,但又不实用性的东西。
这里也推荐一些面试相关的内容,祝各位网友都能拿到满意offer!
GCD面试要点
block面试要点
Runtime面试要点
RunLoop面试要点
内存管理面试要点
MVC、MVVM面试要点
网络性能优化面试要点
网络编程面试要点
KVC&KVO面试要点
数据存储面试要点
混编技术面试要点
设计模式面试要点
UI面试要点
网友评论