区块链技术
联系我们

iOS 自定义页面的切换动画与交互动画,ios自定义页面切换

发布时间:2019-01-31信息来源:admin

iOS 自定义页面的切换动画与交互动画,ios自定义页面切换

在iOS7之前,开发者为了寻求自定义Navigation Controller的Push/Pop动画,只能受限于子类化一个UINavigationController,或是用自定义的动画去覆盖它。但是随着iOS7的到来,Apple针对开发者推出了新的工具,以更灵活地方式管理UIViewController切换。


效果预览:


自定义导航栏的Push/Pop动画

为了在基于UINavigationController下做自定义的动画切换,先建立一个简单的工程,这个工程的rootViewController是一个UINavigationController,UINavigationController的rootViewController是一个简单的UIViewController(称之为主页面),通过这个UIViewController上的一个Button能进入到下一个UIViewController中(称之为详情页面),我们先在主页面的ViewController上实现两个协议:UINavigationControllerDelegate和UIViewControllerAnimatedTransitioning,然后在ViewDidLoad里面把navigationController的delegate设为self,这样在导航栏Push和Pop的时候我们就知道了,然后用一个属性记下是Push还是Pop,就像这样:

func navigationController(navigationController: UINavigationController!, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController!, toViewController toVC: UIViewController!) -> UIViewControllerAnimatedTransitioning! {
    navigationOperation = operation
    return self
}
这是iOS7的新方法,这个方法需要你提供一个UIViewControllerAnimatedTransitioning,那UIViewControllerAnimatedTransitioning到底是什么呢?

UIViewControllerAnimatedTransitioning是苹果新增加的一个协议,其目的是在需要使用自定义动画的同时,又不影响视图的其他属性,让你把焦点集中在动画实现的本身上,然后通过在这个协议的回调里编写自定义的动画代码,即“切换中应该会发生什么”,负责切换的具体内容,任何实现了这一协议的对象被称之为动画控制器。你可以借助协议能被任何对象实现的这一特性,从而把各种动画效果封装到不同的类中,只要方便使用和管理,你可以发挥一切手段。我在这里让主页面实现动画控制器也是可以的,因为它是导航栏的rootViewController,会一直存在,我只要在里面编写自定义的Push和Pop动画代码就可以了:

//UIViewControllerTransitioningDelegate
func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval {
    return 0.4
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning!) {
    let containerView = transitionContext.containerView()
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
    
    var destView: UIView!
    var destTransform: CGAffineTransform!
    if navigationOperation == UINavigationControllerOperation.Push {
        containerView.insertSubview(toViewController.view, aboveSubview: fromViewController.view)
        destView = toViewController.view
        destView.transform = CGAffineTransformMakeScale(0.1, 0.1)
        destTransform = CGAffineTransformMakeScale(1, 1)
    } else if navigationOperation == UINavigationControllerOperation.Pop {
        containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)
        destView = fromViewController.view
        // 如果IDE是Xcode6 Beta4+iOS8SDK,那么在此处设置为0,动画将不会被执行(不确定是哪里的Bug)
        destTransform = CGAffineTransformMakeScale(0.1, 0.1)
    }
    UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
            destView.transform = destTransform
        }, completion: ({completed in
            transitionContext.completeTransition(true)
        }))
}

上面第一个方法返回动画持续的时间,而下面这个方法才是具体需要实现动画的地方。UIViewControllerAnimatedTransitioning的协议都包含一个对象:transitionContext,通过这个对象能获取到切换时的上下文信息,比如从哪个VC切换到哪个VC等。我们从transitionContext获取containerView,这是一个特殊的容器,切换时的动画将在这个容器中进行;UITransitionContextFromViewControllerKey和UITransitionContextToViewControllerKey就是从哪个VC切换到哪个VC,容易理解;除此之外,还有直接获取view的UITransitionContextFromViewKey和UITransitionContextToViewKey等。

我按Push和Pop把动画简单的区分了一下,Push时scale由小变大,Pop时scale由大变小,不同的操作,toViewController的视图层次也不一样。最后,在动画完成的时候调用completeTransition,告诉transitionContext你的动画已经结束,这是非常重要的方法,必须调用。在动画结束时没有对containerView的子视图进行清理(比如把fromViewController的view移除掉)是因为transitionContext会自动清理,所以我们无须在额外处理。

注意一点,这样一来会发现原来导航栏的交互式返回效果没有了,如果你想用原来的交互式返回效果的话,在返回动画控制器的delegate方法里返回nil,如:

if operation == UINavigationControllerOperation.Push {
    navigationOperation = operation
    return self
}
return nil
然后在viewDidLoad里,Objective-C直接self.navigationController.interactivePopGestureRecognizer.delegat = self就行了,Swift除了要navigationController.interactivePopGestureRecognizer.delegate = self之外,还要在self上声明实现了UIGestureRecognizerDelegate这个协议,虽然实际上你并没有实现。

一个简单的自定义导航栏Push/Pop动画就完成了。


自定义Modal的Present/Dismiss动画自定义Modal的Present与Dismiss动画与之前类似,都需要提供一个动画管理器,我们用详情页面来展示一个Modal页面,详情页面就作为动画管理器:
func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval {
    return 0.6
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning!) {
    let containerView = transitionContext.containerView()
    
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
    
    var destView: UIView!
    var destTransfrom = CGAffineTransformIdentity
    let screenHeight = UIScreen.mainScreen().bounds.size.height
    
    if modalPresentingType == ModalPresentingType.Present {
        destView = toViewController.view
        destView.transform = CGAffineTransformMakeTranslation(0, screenHeight)
        containerView.addSubview(toViewController.view)
    } else if modalPresentingType == ModalPresentingType.Dismiss {
        destView = fromViewController.view
        destTransfrom = CGAffineTransformMakeTranslation(0, screenHeight)
        containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)
    }
    
    UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0,
    options: UIViewAnimationOptions.CurveLinear, animations: {
        destView.transform = destTransfrom
    }, completion: {completed in
        transitionContext.completeTransition(true)
    })
}
动画部分用了一个iOS7的弹簧动画,usingSpringWithDamping的值设置得越小,弹的就越明显,动画的其他地方与之前类似,不一样的是之前主页面除了做动画管理器之外,还实现了UINavigationControllerDelegate协议,因为我们是自定义导航栏的动画,而在这里需要自定义Modal动画就要实现另一个协议:UIViewControllerTransitioningDelegate,这个协议与之前的UINavigationControllerDelegate协议具有相似性,都是返回一个动画管理器,iOS7的方法总共有四个,有两个交互式的先不管,我们只需要实现另两个即可:
func animationControllerForPresentedController(presented: UIViewController!, presentingController presenting: UIViewController!, sourceController source: UIViewController!) -> UIViewControllerAnimatedTransitioning! {
    modalPresentingType = ModalPresentingType.Present
    return self
}

func animationControllerForDismissedController(dismissed: UIViewController!) -> UIViewControllerAnimatedTransitioning! {
    modalPresentingType = ModalPresentingType.Dismiss
    return self
}
我同样的用一个属性记下是Present还是Dismiss,然后返回self。因为我是用的Storyboard,所以需要在prepareForSegue方法里设置一下transitionDelegate:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    let modal = segue.destinationViewController as UIViewController
    modal.transitioningDelegate = self
}
对需要执行自定义动画的VC设置transitionDelegate属性即可。如此一来,一个针对模态VC的自定义动画也完成了。
自定义导航栏的交互式动画与动画控制器类似,我们把实现了UIViewControllerInteractiveTransitioning协议的对象称之为交互控制器,最常用的就是把交互控制器应用到导航栏的Back手势返回上,而如果要实现一个自定义的交互式动画,我们有两种方式来完成:实现一个交互控制器,或者使用iOS提供的UIPercentDrivenInteractiveTransition类作交互控制器。
使用UIPercentDrivenInteractiveTransition我们这里就用UIPercentDrivenInteractiveTransition来完成导航栏的交互式动画。先看下UIPercentDrivenInteractiveTransition的定义:

实际上这个类就是实现了UIViewControllerInteractiveTransitioning协议的交互控制器,我们使用它就能够轻松地为动画控制器添加一个交互动画。调用updateInteractiveTransition:更新进度;调用cancelInteractiveTransition取消交互,返回到切换前的状态;调用finishInteractiveTransition通知上下文交互已完成,同completeTransition一样。我们把交互动画应用到详情页面Back回主页面的地方,由于之前的动画管理器的角色是主页面担任的,Navigation Controller的delegate同一时间只能有一个,那在这里交互控制器的角色也由主页面来担任。首先添加一个手势识别器:

let popRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: Selector("handlePopRecognizer:"))
popRecognizer.edges = UIRectEdge.Left
self.navigationController.view.addGestureRecognizer(popRecognizer)
UIScreenEdgePanGestureRecognizer继承于UIPanGestureRecognizer,能检测从屏幕边缘滑动的手势,设置edges为left检测左边即可。然后实现handlePopRecognizer:

func handlePopRecognizer(popRecognizer: UIScreenEdgePanGestureRecognizer) {
    var progress = popRecognizer.translationInView(navigationController.view).x / navigationController.view.bounds.size.width
    progress = min(1.0, max(0.0, progress))
    
    println("\(progress)")
    if popRecognizer.state == UIGestureRecognizerState.Began {
        println("Began")
        self.interactivePopTransition = UIPercentDrivenInteractiveTransition()
        self.navigationController.popViewControllerAnimated(true)
    } else if popRecognizer.state == UIGestureRecognizerState.Changed {
        self.interactivePopTransition?.updateInteractiveTransition(progress)
        println("Changed")
    } else if popRecognizer.state == UIGestureRecognizerState.Ended || popRecognizer.state == UIGestureRecognizerState.Cancelled {
        if progress > 0.5 {
            self.interactivePopTransition?.finishInteractiveTransition()
        } else {
            self.interactivePopTransition?.cancelInteractiveTransition()
        }
        println("Ended || Cancelled")
        self.interactivePopTransition = nil
    }
}
我用了一个实例变量引用UIPercentDrivenInteractiveTransition,这个类只在需要用时才创建,否则在正常Push/Pop的时候,即使只是点击操作并没有识别手势的情况下,也会进入交互(你也可以在要求你返回交互控制器时,进行一些判断,通过返回nil来屏蔽,但这显然就太麻烦了)。当手势识别的时候我们调用pop,用户手势发生变化时,调用update去更新,不管是end还是cancel,都判断下是进入下一个页面还是返回之前的页面,完成这一切后把交互控制器清理掉。

现在我们已经有了交互控制器对象,只需要把它给告知给Navigation Controller就行了,我们实现UINavigationControllerDelegate的另一个方法:

func navigationController(navigationController: UINavigationController!, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning!) -> UIViewControllerInteractiveTransitioning! {
    return self.interactivePopTransition
}
我们从详情页面通过自定义的交互动画返回到上一个页面的工作就完成了。

使用UIPercentDrivenInteractiveTransition的Demo


自定义交互控制器我在之前提过,UIPercentDrivenInteractiveTransition实际上就是实现了UIViewControllerInteractiveTransitioning协议,只要是实现了这个协议的对象就可以称之为交互控制器,我们如果想更加精确的管理动画以及深入理解处理上的细节,就需要自己实现UIViewControllerInteractiveTransitioning协议。UIViewControllerInteractiveTransitioning协议总共有三个方法,其中startInteractiveTransition:是必须实现的方法,我们在里面初始化动画的状态:
func startInteractiveTransition(transitionContext: UIViewControllerContextTransitioning!) {
    self.transitionContext = transitionContext
    
    let containerView = transitionContext.containerView()
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
    
    containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)
    
    self.transitingView = fromViewController.view
}
这里不涉及动画,只是把需要切换的view添加到上下文环境中即可。动画部分我们还是和之前使用UIPercentDrivenInteractiveTransition的接口保持一致,添加几个方法:
func updateWithPercent(percent: CGFloat) {
    let scale = CGFloat(fabsf(Float(percent - CGFloat(1.0))))
    transitingView?.transform = CGAffineTransformMakeScale(scale, scale)
    transitionContext?.updateInteractiveTransition(percent)
}

func finishBy(cancelled: Bool) {
    if cancelled {
        UIView.animateWithDuration(0.4, animations: {
            self.transitingView!.transform = CGAffineTransformIdentity
        }, completion: {completed in
            self.transitionContext!.cancelInteractiveTransition()
            self.transitionContext!.completeTransition(false)
        })
    } else {
        UIView.animateWithDuration(0.4, animations: {
            print(self.transitingView)
            self.transitingView!.transform = CGAffineTransformMakeScale(0, 0)
            print(self.transitingView)
        }, completion: {completed in
            self.transitionContext!.finishInteractiveTransition()
            self.transitionContext!.completeTransition(true)
        })
    }
}
updateWithPercent:方法用来更新view的transform属性,finishBy:方法主要用来判断是进入下一个页面还是返回到之前的页面,并告知transitionContext目前的状态,以及对当前正在scale的view做最后的动画。这里的transitionContext和transitingView可以在前面的处理手势识别代码中取得,我将里面的代码更新了一下,变成下面这样:
func handlePopRecognizer(popRecognizer: UIScreenEdgePanGestureRecognizer) {
    var progress = popRecognizer.translationInView(navigationController.view).x / navigationController.view.bounds.size.width
    progress = min(1.0, max(0.0, progress))
    
    println("\(progress)")
    if popRecognizer.state == UIGestureRecognizerState.Began {
        println("Began")
        isTransiting = true
          //self.interactivePopTransition = UIPercentDrivenInteractiveTransition()
        self.navigationController.popViewControllerAnimated(true)
    } else if popRecognizer.state == UIGestureRecognizerState.Changed {
          //self.interactivePopTransition?.updateInteractiveTransition(progress)
        updateWithPercent(progress)
        println("Changed")
    } else if popRecognizer.state == UIGestureRecognizerState.Ended || popRecognizer.state == UIGestureRecognizerState.Cancelled {
          //if progress > 0.5 {
          //    self.interactivePopTransition?.finishInteractiveTransition()
          //} else {
          //    self.interactivePopTransition?.cancelInteractiveTransition()
          //}
        finishBy(progress < 0.5)
        println("Ended || Cancelled")
        isTransiting = false
          //self.interactivePopTransition = nil
    }
}
另外还用一个额外布尔值变量isTransiting来标识当前是否在手势识别中,这是为了在返回交互控制器的时候,不会在不当的时候返回self:
func navigationController(navigationController: UINavigationController!, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning!) -> UIViewControllerInteractiveTransitioning! {
    if !self.isTransiting {
        return nil
    }
    return self
}
这样一来就完成了自定义交互控制器。可以发现,基本流程与使用UIPercentDrivenInteractiveTransition是一致的,UIPercentDrivenInteractiveTransition主要是帮我们封装了transitionContext的初始化以及对它的调用等,只是动画部分需要我们在额外处理一下了。
使用自定义交互控制器的Demo(上传到我的资源页面时总是失败,所以只能上传到GitHub上了)

最后附上一张图,这个图比较容易区分那几个名称相近的协议:




浏览手机网页看到的交互动画一般是什格式怎制作的

游戏需要依赖其他比如flash或c之类,而交互演示可以利用html5的功能足够,具体的可以举个例子,我没有ios也没接触过 不过常规网站上的交互动画利用html本身的一些功能就能实现,简单的游戏也能实现,但效果差强人意
 
ppt 怎为自定义动画中添加素材

一.视图的变化
1、PowerPoint 2003的普通视图分为“大纲”和“幻灯片”两种模式,新增的“幻灯片”模式能让我们看到幻灯片的全貌,使得在操作某一张幻灯片时能对整体结构有明确的把握。
2、插入新幻灯片更方便、快捷:在“幻灯片”视图模式下,只需点击回车键,即可在正编辑的幻灯片下添加一张新幻灯片。
3、幻灯片放映模式下,左下角的第二个图标,可以将光标指针变换为圆珠笔、毡尖笔、荧光笔三种形式,这些笔型可在播放的幻灯片上进行圈点,充当教鞭用,并可改变笔尖颜色,保存笔迹。
二.操作对象的变化
1.所有对象编辑时都多了个旋转点,可随意旋转。
2.剪贴画:是PowerPoint软件提供的小图片库,PowerPoint 2003中提供了更多的图片素材,我们可以利用“剪贴画”面板(右侧),通过输入搜索文字、搜索范围、结果类型更快地在剪贴画中查找到自己所属的图片。
3.新建相册:PowerPoint 2003提供了制作相册的功能,此功能可将大量的图片方便、快捷地插入到幻灯片中,适用于图片教学。
操作方法:
①点击菜单栏中的“文件”→“新建”
②在右侧弹出的“新建演示文稿”面板中,选择“相册”
③在弹出的“相册”对话框中,找到图片所在位置,选择要输入的多张图片,点击“插入”
④在“相册”对话框中,可删除多余的图片,还可调整图片的顺序、方向、亮度、对比度;在“相册版式”中可调整图片版式、相框形状,还可以为相册添加设计模板等。
⑤我们可以通过点击菜单栏中的“格式”→“相册”,对“相册格式”进行调整和修改。
4.插入图示:这几种图示使得一些过程、关系的描述更加直观,不需再用自选图形进行一点一点的组合!
操作方法:点击菜单栏中的“插入”→“图示”,在弹出的对话框中,选择一种合适的关系图即可。
a、组织结构图——用于显示层次关系;
b、循环图——用于显示持续循环的过程;
c、射线图——用于显示核心元素的关系;
d、棱锥图——用于显示基于基础的关系;
e、维恩图——用于显示元素间的重叠区域;
f、目标图——用于显示实现目标的步骤。
利用图示工具栏可以对图示进行编辑管理,有"插入图形、版式、选择、图示样式、适应文字"等操作。
其中除了组织结构图,其它图示之间可以进行转换。
三. 针对幻灯片的不同操作
在幻灯片中应用设计模板时,使用PowerPoint 2000时,无论是从“插入”菜单操作,还是从工具按钮操作,或使用快捷键“Ctrl+M”,都需要从弹出的版式中选择适当的版式。在2003中可直接从幻灯片设计面板中的应用设计模块里的“幻灯片版式”选择,对于不合适的版式,也不必删除重来,直接从相应的版式中将其替换即可。
操作方法:点击菜单栏中的“格式”,选择“幻灯片版式”或“幻灯片设计”
1.幻灯片版式:放在普通视图窗口的右边(可拖动为浮动式面板),分为文字版式、内容版式、文字和内容版式、其它版式四大类,使幻灯片的制作更加方便。
2.幻灯片设计:放在普通视图窗口的右边,分为设计模板、配色方案、动画方案。
(1)设计模板:过去每个演示文稿只能使用一个设计模板,不能将模板直接应用于单独的幻灯片,在PowerPoint 2003里已经没有这种限制了,我们可以将模式分别应用于母板、所有幻灯片、选定幻灯片、新演示文稿,这样一个演示文稿中可以应用任意多个模板。
操作方法:
①应用于所有幻灯片:单击模板右边的下拉箭头, 选择应用于所有幻灯片。
②应用于选定幻灯片:先选中一张或多张幻灯片,再单......余下全文>>
 

http://www.bkjia.com/Androidjc/863155.htmlwww.bkjia.comtruehttp://www.bkjia.com/Androidjc/863155.htmlTechArticleiOS 自定义页面的切换动画与交互动画,ios自定义页面切换 在iOS7之前,开发者为了寻求自定义Navigation Controller的Push/Pop动画,只能受限于子...

本文源自: 凯发k8娱乐官网


上一篇:【Android】开发优化之——调优工具:dump hprof file 查看内存情况,找到内存泄露,androidhp 下一篇:没有了