美文网首页iOS技术资料iOSiOS
通过LaunchScreen自定义启动动画

通过LaunchScreen自定义启动动画

作者: Andy矢倉 | 来源:发表于2015-10-28 02:09 被阅读30998次

    大晚上刷微博,刷到一篇转发自里脊串的博客Tips:获取APP的Launch Image

    大致内容是:通过获取打包到App里的启动图,初始化一个UIImageView与屏幕同等大小再加载到UIWindow上来做启动延时,从而达到自定义启动动画的目的。代码里的各种Key没太看懂,放到工程里也没法显示效果。文中的意思是不要增加启动图的方式来适配,那我想了想iOS启动画面的方式目前我所知就两种:启动图和布局文件。我现在基本上没有用图片作为启动图,都是直接用布局文件搞定。

    PS:今年开发的App基本上都是支持iOS7以上了,所以没太用启动图了,Xcode 6LaunchScreen.xib,到Xcode 7变成了LaunchScreen.storyboard,无可厚非,两者本质都是一样的。

    教程看的云里雾里的,不过不打紧,思路还是一样的,我想如果StoryboardSize Class玩得多同学还是喜欢布局文件作为启动图的方式吧,所以我的方式是获取LaunchScreen.storyboard里的ViewController,在把View提取出来加到UIWindow显示做动画即可。

    这种方式的好处就是,获取大小就是屏幕的大小,而且只要你把不同屏幕的布局搞定了,系统会帮你生成好加在的启动页,这样就免去了判断和从新设置大小的麻烦,这样才是真适配嘛~

    废话不多说,上代码吧~
    (对了,记得给LaunchScreen.storyboard里的ViewController设置好Storyboard ID

    UIViewController *viewController = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateViewControllerWithIdentifier:@"LaunchScreen"];
    
    UIView *launchView = viewController.view;
    UIWindow *mainWindow = [UIApplication sharedApplication].keyWindow;
    launchView.frame = [UIApplication sharedApplication].keyWindow.frame;
    [mainWindow addSubview:launchView];
    
    [UIView animateWithDuration:0.6f delay:0.5f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        launchView.alpha = 0.0f;
        launchView.layer.transform = CATransform3DScale(CATransform3DIdentity, 1.5f, 1.5f, 1.0f);
    } completion:^(BOOL finished) {
        [launchView removeFromSuperview];
    }];
    

    此代码片段,如果应用启动初始化如果是代码可以在AppDelegate加,Storyboard加载方式需要加在ViewController里。


    2015.11.27
    最近项目UI框架切换到UITabBarController,发现这个动画没法使用,是由于如果在Storyboard中使用UITabBarController,如果做启动登录需求,肯定是按需加载,就需要自建继承自UITabBarController的关联,如果在- (void)viewDidLoad里加载就会导致如下警告:

    Warning: Attempt to present <HXLoginViewController: 0x7fa5a063cca0> on <HXMainViewController: 0x7fa5a05ae0b0> whose view is not in the window hierarchy!**
    

    系统没法知道该怎么显示,所以只能放到- (void)viewDidAppear:(BOOL)animated里来做,UITabBarController框架加载这个动画没效果也是这个原因,但是没Debug警告,不过要注意,如果只是单纯使用这个动画没啥问题,但是如果在UITabBarController上用模态视图的方式做按需加载以及转场动画需要处理- (void)viewDidAppear:(BOOL)animated重复调用的问题。


    2016.03.28
    最近看到很多人留言没效果,其实稍微调试一下就知道,不是没效果,是时机出了问题,之前的效果应该在9.1之前能看到,新的系统版本应该改了时机,这里的技巧无非就是在以下三个时机处理:

    - (void)viewDidLoad;
    - (void)viewWillAppear:(BOOL)animated;
    - (void)viewDidAppear:(BOOL)animated;
    

    经过了测试在viewDidLoadviewWillAppear:加这个效果都是出现视图层级的问题,这是由于控制器生成的视图直接盖在了启动页上,层级在其之上当然无法显示。

    按照之前的方式在viewDidLoad或者viewWillAppear实际的效果是这样:

    所以现在想要看到效果,就只能在最后一个时机viewDidAppear:里加入示例代码了。

    Demo:https://github.com/shicang1990/LaunchScreenAnimation-Storyboard

    相关文章

      网友评论

      • 我本善良:博主,您好。app支持横屏和竖屏,用LaunchScreen.storyboard做为启动界面,但是效果比如是距屏幕底部40pt有个logo,居中;产品要求app启动的时候始终是竖屏效果,不管手机是横屏还是竖屏?LaunchScreen.storyboard怎么适配横屏和竖屏
      • 秋天的田野:我这样做动画是有,但怎么也设置不了状态栏的颜色,想改成白色改不了,开始是白色,加载了这个launch后就变黑色了,不知道怎么回事?希望各位大神分享下经验,谢谢
      • 桔呢:怎么设置满屏,不要有状态条
        Andy矢倉:选中viewcontroller隐藏statusbar
      • d17ecb6c9605:我按照25楼这个纯代码布局,写在delegate里 ,但是每次进去都有空白的launchScreen.SD的展示出来,然后再展示我定义的这个启动图 ,体验很不好,- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];

        // UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        // aVC *aVC = [board instantiateViewControllerWithIdentifier:@"aVC"];
        // self.window.rootViewController = aVC;

        UITabBarController *tabbarVC = [[UITabBarController alloc]init];
        self.window.rootViewController = tabbarVC;
        tabbarVC.view.backgroundColor = [UIColor blueColor];
        UIViewController *viewController = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateViewControllerWithIdentifier:@"LaunchScreen"];

        UIView *launchView = viewController.view;
        launchView.frame = self.window.frame;
        UIImageView * launchImgView = [[UIImageView alloc]initWithFrame:CGRectMake(launchView.center.x - 50 , launchView.center.y - 50, 100, 100)];
        launchImgView.image = [UIImage imageNamed:@"C-AvatarIcon"];
        [launchView addSubview:launchImgView];
        //修改为加载到rootVC上
        [self.window.rootViewController.view addSubview:launchView];
        [UIView animateWithDuration:1.0f delay:0.5f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        launchView.alpha = 0.0f;
        launchView.layer.transform = CATransform3DScale(CATransform3DIdentity, 2.0f, 2.0f, 1.0f);
        } completion:^(BOOL finished) {

        [launchView removeFromSuperview];

        }];
        [self.window makeKeyAndVisible];
        return YES;
        }
      • 兔兔小八哥:过程其实是在加载完启动页面以后,在window上加载了一个view然后删除掉,其实我觉得这样写有点浪费,还不如直接把图片写死在程序里或者是通过subview获取image,这是我的理解,不知道对不对,求楼主指教哦 :relaxed:
      • Swifer:楼主,你好。我在做启动页动画的时候,启动页的图片会往上移一下。大概会是什么原因?
        fighting骚年:启动页的约束设置的不对
      • 三剑客之砍你一刀没商量:我也有闪屏.... 看到这么多人有闪屏... 楼主也不告知一下为什么
      • 飞翔的小骑兵:纯代码加载方式:appDelegate

        [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];

        // UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        // aVC *aVC = [board instantiateViewControllerWithIdentifier:@"aVC"];
        // self.window.rootViewController = aVC;

        TabbarController *tabbarVC = [[TabbarController alloc]init];
        self.window.rootViewController = tabbarVC;

        UIViewController *viewController = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateViewControllerWithIdentifier:@"LaunchScreen"];

        UIView *launchView = viewController.view;
        launchView.frame = self.window.frame;
        //修改为加载到rootVC上
        [self.window.rootViewController.view addSubview:launchView];

        [UIView animateWithDuration:1.0f delay:0.5f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        launchView.alpha = 0.0f;
        launchView.layer.transform = CATransform3DScale(CATransform3DIdentity, 2.0f, 2.0f, 1.0f);
        } completion:^(BOOL finished) {

        [launchView removeFromSuperview];

        }];
        [self.window makeKeyAndVisible];
        return YES;
      • novisibleselect:我想问问为什么使用storyboard启动就不可以在didfinishlaunching里写这个代码?
      • 哭泣男孩儿:不错哦。
      • Easy_VO:收藏观望中-。-
      • 神码:有个地方
        AppDelegate *delegate = [UIApplication sharedApplication].delegate;
        UIWindow *mainWindow = delegate.window;
        可以改成
        UIWindow *mainWindow = [UIApplication sharedApplication].keyWindow;
        而且不用导入AppDelegate.h
        Andy矢倉:@神码 谢谢,已修正
      • 老初:楼主是如何解决闪屏的? :fearful:
        Hello_Tiger:@Andy矢倉 就是demo里的啊
        Andy矢倉:先分析好自己的App的UI结构和层级,闪屏才能对症下药 @老初 @李小虎
        Hello_Tiger:@老初 这个闪屏的解决了没啊
      • younger_times:如果我想让图片是从后台拿,那这个应该怎么弄呢?
      • 五月飞:楼主,我在ViewController 调storeBorad 获取view的方法storyboardWithName 在ViewController 里我同看查看层级关系,发现UIImageView 是空白的,我也设置过 ViewController的StoreBorad ID了,图片没有显示出来,然后我把你demo里面的LaunchScreen.storyboard替换到我项目中去,图片就显示出来了,麻烦楼主能不能把在LaunchScreen.storyboard里面的操作也截图一下,更新下文章 :blush:
      • holyjoy:楼主,如果想动态改变启动页里的image,或者在启动也上加了button,怎样关联。有木有办法。。。
      • vision_colion:楼主。我也基本照搬你的代码,代码加载的,放在appledelegate,没有任何效果啊 :flushed:
      • developer_cp3:我设置了launchView 背景色 但是不管用啊,ma_wenbo@126.com
        给个demo 嘛 楼主,无论放在 viewdidload 还是 appdelegate 都试过了 都不行的呢
        往launchscreen.storeBorad 上面 拖东西 可以显示 没问题 但是,获取到view 然后改变颜色 啊或者在view 上面加东西啊 就不行得
      • 18221518435:效果是有效果,但是中间有一个短暂的闪屏的效果。不知如何解决好。
        Hello_Tiger:还是有闪屏啊~
        18221518435:@18221518435 我发现不要加载到Window上,直接加载到ViewColler里面,不会有闪屏的效果。
      • Ilovecoding822:试了试11.27更新部分中的方法,这次有效果了,嘿嘿。
        vision_colion:@hippo_baby 新更新的在哪看:fearful:
      • Ilovecoding822:代码加vc里了,storyboard id也加了,是main storyboard启动,lanuchscreen加了底色,但最终没效果呀,还是默认系统自带的效果(展示完底色lanuchscreen就立即消失)。。。为啥,求教!
      • 91阿生:demo放个! 一看就知道了 :+1:
      • Bison:加AppDelegate里面没任何效果的样子,,,,,
        代码如下
        ```
        UIViewController *viewController = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateViewControllerWithIdentifier:@"LaunchScreen"];

        UIView *launchView = viewController.view;
        AppDelegate *delegate = [UIApplication sharedApplication].delegate;
        UIWindow *mainWindow = delegate.window;

        _splashView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 568)];
        [_splashView setImage:[UIImage imageNamed:@"Default"]];
        launchView.backgroundColor = [UIColor redColor];
        [launchView addSubview:_splashView];

        [mainWindow addSubview:launchView];

        [UIView animateWithDuration:0.6f delay:0.5f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
        launchView.alpha = 0.0f;
        launchView.layer.transform = CATransform3DScale(CATransform3DIdentity, 1.5f, 1.5f, 1.0f);
        } completion:^(BOOL finished) {
        [launchView removeFromSuperview];
        _tabViewController = [[LBTabBar alloc]init];
        self.window.rootViewController = _tabViewController;

        }];
        ```
        程序然:楼上是没有初始化window
        Bison::sweat::disappointed_relieved::cold_sweat::cry::sleepy:肯定是代码所以才写到appde那里的撒…
        Andy矢倉:@Bison 代码片段,如果应用启动初始化如果是代码可以在AppDelegate加,Storyboard加载方式需要加在ViewController里
      • Laughingg:不错
        Andy矢倉:@潇小溅 :grin: :grin: :grin:
      • MrLeoZou:基本照搬你的代码,用storyboard启动,写在viewController的viewdidiload方法中的代码,发现没有任何效果
        Andy矢倉:@MelodyZhy 放viewDidLoad里也没有?
        MelodyZhy:@Andy矢倉 LaunchScreen.storyboard里ViewController的View有值,也改了view的颜色,但并没有变化。。。。
        Andy矢倉:@Leo_ZZP 断点看下你有没有拿到LaunchScreen.storyboard里ViewController的View,如果照做了没效果就是没拿到,或者是白底启动页,白底的就加个图或者改个底色
      • 夜央未尽:有时候launch 停留的时间比较长,就导致launch 还没有消失,动画效果已经做完了。这样反而看不到launch的动画效果。
        Andy矢倉:@夜央未尽 放ViewController就不会有这种问题
      • 十一岁的加重:更新的挺快哦,实用
        Andy矢倉:@十一岁的加重 :blush: :blush: :blush:
      • liheizi:启动图如果只是中间一个图片的话,方便适应,用storyboard ,但是整个屏幕就是一张图片,用image方便点吧~~美工给每个尺寸的界面都适配了一张图
        Andy矢倉:@Eugene 如果使用LaunchScreen.storyboard这种方式还放一整张图在里面,那还不如直接用图片,LaunchScreen.storyboard加载方式是基于AutoLayout和SizeClass的,主要目的是适配屏幕,如果启动图太复杂,是要比图片浪费时间,具体还是看需求
      • Kimball:我想问这个代码写在哪里?
        Andy矢倉:@Kimball 代码片段加在ViewController里,应用启动初始化如果是代码可以在AppDelegate加,Storyboard加载方式需要加在ViewController里
      • 是我始终拒绝成长吗:好像没有什么效果呀
        Andy矢倉:@是我始终拒绝成长吗 请看2015.11.27更新,可能是类似问题。
        Andy矢倉:@是我始终拒绝成长吗 你确定下LaunchScreen内有内容,代码片段加在ViewController里,应用启动初始化如果是代码可以在AppDelegate加,Storyboard加载方式需要加在ViewController里

      本文标题:通过LaunchScreen自定义启动动画

      本文链接:https://www.haomeiwen.com/subject/trwxhttx.html