读书频道 > 网站 > 网页设计 > iOS应用开发攻略
攻略1 添加基本的启动画面切换
12-08-20    叶孤城
收藏    我要投稿   

本文所属图书 > iOS应用开发攻略

本书收录了最新的iOS 软件开发的最佳做法,涵盖了应用开发及构建优雅解决方案的必备知识,包括:编写通用的启动画面和嵌入式Web 浏览器;构建复杂表视图;使app 或游戏活灵活现的填充、变换和动画;通过手势、...立即去当当网订购
问题
应用程序启动时,从默认图像到实际UI的切换如果很生硬,带给用户的第一印象会很糟糕。我们想让从应用程序的启动图像到初始UI的切换尽可能平滑流畅,但不清楚如何用最简洁的方式实现。
解决方案
iOS app启动的直观体验是这样的:
(1) 用户点击app图标;
(2) app的默认图像逐渐放大显示到屏幕上;
(3) app的初始UI加载到内存;
(4) UI显示到屏幕上,取代默认图像。
如果默认图像是品牌的横幅或其他特有的图片,那么由它到实际UI的切换可能会让用户觉得生硬。我们需要一种从启动画面到运行的程序之间的平滑切换。这可以通过许多方式来实现,我们从最简单的一种方式讲起,这应该是一种普遍适用的方式。我们先来处理一个纵向的iPhone程序,接下来看看支持各种方向的iPad版本。初始画面如图1所示。

图1 启动画面与初始UI
最简单的“启动画面切换”是默认图像淡出,而UI同时淡入。这种切换容易实现,成本不高,又能让用户体验截然不同。想想看,这是用户第一眼看到的东西,没有理由不做得平滑顺畅。
为了使默认图像淡出屏幕,首先需要显示一个视图,由它显示这幅图像,然后把这个视图淡出。这很容易,先创建一个可用于任何项目的简单的视图控制器,由它使用定制的启动屏幕图像,并定义一个执行淡出的-hide方法。
BasicSplashScreen/PRPSplashScreen.h
@interfacePRPSplashScreen : UIViewController {}
 
@property(nonatomic, retain) UIImage *splashImage;
@property(nonatomic, assign) BOOL showsStatusBarOnDismissal;
@property(nonatomic, assign) IBOutlet id<PRPSplashScreenDelegate> delegate;
 
- (void)hide;
 
@end
接口中有一个delegate属性,声明为id <PRPSplashScreenDelegate>类型。这个PRPSplashScreenDelegate协议定义在独立的头文件中,向相关程序传达启动画面的状态:启动画面何时开始显示、何时开始切换及何时结束切换。
读者肯定在很多地方做过委托所做的事情,但很可能以前没有定义过委托。我们来看看这个协议的定义,请注意@optional关键字,这意味着该委托不要求实现它声明的所有方法。一个对象如果想知道启动画面的状态,可以声明自己遵守PRPSplashScreenDelegate协议,实现一个或多个委托方法,并把自己赋值给启动画面的delegate属性。
BasicSplashScreen/PRPSplashScreenDelegate.h
@protocolPRPSplashScreenDelegate <NSObject>
 
@optional
- (void)splashScreenDidAppear:(PRPSplashScreen *)splashScreen;
- (void)splashScreenWillDisappear:(PRPSplashScreen *)splashScreen;
- (void)splashScreenDidDisappear:(PRPSplashScreen *)splashScreen;
 
@end
PRPSplashScreen在-loadView方法中构建其视图,这样就不必在每次用到它时都去拖XIB文件了,因而也更便于我们把它应用到项目中。view属性设置为一个以居中的图像充满屏幕的图像视图。
BasicSplashScreen/PRPSplashScreen.m
- (void)loadView {
    UIImageView *iv = [[UIImageView alloc] initWithImage:self.splashImage];
    iv.autoresizingMask = UIViewAutoresizingFlexibleWidth |
        UIViewAutoresizingFlexibleHeight;
    iv.contentMode = UIViewContentModeCenter;
    self.view = iv;
    [iv release];
}
现在来看看splashImage属性,它是可写的,所以必要时我们可以设置定制的切换图像。但是我们这里只使用Default.png作为启动图像,因为这个攻略的要点是创建平滑流畅的切换。所以,我们写了一个默认加载Default.png的懒初始化方法。如果是从默认的图像做切换,就无需改动这个属性。我们使用+[UIImage imageNamed:]来保证使用适当比例的图像(比如对于Retina显示屏使用Default@2x.png)。
BasicSplashScreen/PRPSplashScreen.m
- (UIImage *)splashImage {
    if (splashImage == nil) {
        self.splashImage = [UIImage imageNamed:@"Default.png"];
    }
    return splashImage;
}
设置启动画面很简单,只是从app的根视图控制器显示一个模态视图控制器而已。我们将在程序启动时,在添加了根视图之后、显示主窗口之前做这件事。时机很重要:根视图控制器在自身的视图没有准备好之前,不会正常显示模态视图控制器。本章的BasicSplashScreen项目中,我们在代码中也设定了一种溶解风格(淡入淡出)的切换。因为启动画面默认使用启动图像,所以不需要我们自己指定。
BasicSplashScreen/iPhone/AppDelegate_iPhone.m
- (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self.window addSubview:self.navController.view];
    self.splashScreen.showsStatusBarOnDismissal = YES;
    self.splashScreen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self.navController presentModalViewController:splashScreen animated:NO];
    [self.window makeKeyAndVisible];
    return YES;
}
如果打开MainWindow_iPhone.xib,我们会看到XIB文件中定义了一个PRPSplashScreen对象,如图2所示。在Interface Builder中,这个对象连接到app委托的splashScreen属性。前面的代码引用了这个属性,以显示启动画面。

启动画面在各自的MainWindowXIB文件中作初始化,并连接到应用程序委托的splashScreen属性。app委托也连接到启动画面的delegate属性。
图2 在Interface Builder中连接启动画面
窗口可见之后,启动画面视图控制器会收到标准的UIViewController消息,包括-viewDidAppear:。它意味着要开始画面切换,而且实现起来非常简单。我们首先通知委托,告诉它启动画面视图已经显示了,以便它在必要时为画面切换做准备。首先检查委托是否实现了适当的方法很重要,因为在委托协议中这些方法声明为可选的。向委托发送消息之后,我们发送-hide消息来执行启动画面切换。请注意此处我们使用了performSelector:withObject: afterDelay:,这样可以让UIKit运行循环(run loop)完成viewDidAppear机制。在自身的viewWillAppear:或viewDidAppear:方法中解除(dismiss)视图控制器会导致系统混乱,每个动作需要分离开来,并相互独立。
BasicSplashScreen/PRPSplashScreen.m
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    SEL didAppearSelector = @selector(splashScreenDidAppear:);
    if ([self.delegate respondsToSelector:didAppearSelector]) {
        [self.delegate splashScreenDidAppear:self];
    }
    [self performSelector:@selector(hide) withObject:nil afterDelay:0];
}
-hide方法首先检查是否要在淡出时显示状态条,然后使用标准的-dismissModalView- ControllerAnimated:方法来执行画面切换。添加这个处理是为了应对启动时不显示状态条而在UI中却显示状态条的情形。要实现这种效果,需在app的Info.plist文件中把UIStatusBar- Hidden设为YES,把启动画面的showsStatusBarOnDismissal属性设为YES。启动画面会负责重新激活状态条,所以我们不必自己在委托方法中来做(如图3所示)。


把UIStatusBarHidden键设为YES以便在启动时隐藏状态条。如果要在主UI中显示状态条,需要把启动画面的showStatusBarOnDismissal属性设为YES。
图3 启动时隐藏状态条
BasicSplashScreen/PRPSplashScreen.m
- (void)hide {
    if (self.showsStatusBarOnDismissal) {
        UIApplication *app = [UIApplication sharedApplication];
        [app setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
    }
    [self dismissModalViewControllerAnimated:YES];
}
启动画面也会通过转发标准的视图控制器方法-viewWillDisappear:和-viewDid- Disappear:,把画面切换的进度通知给委托。app委托使用相应的-splashScreenDid- Disappear:委托方法来删除不再需要的启动画面。
BasicSplashScreen/iPhone/AppDelegate_iPhone.m
- (void)splashScreenDidDisappear:(PRPSplashScreen *)splashScreen {
    self.splashScreen = nil;
}
以iPhone为目标环境运行BasicSplashScreen项目,看看从启动画面到UI的画面切换。委托的连接设置是在MainWindow_iPhone.xib和MainWindow_iPad.xib中做的,所以在代码中不必访问delegate属性。我们用来展示本书细节页面的PRPWebViewController类,会在攻略6中再详细讲解。
这个解决方案现在只能执行竖屏的画面切换,对于多数iPhone app来说就够了。而iPad app会经常以横屏和竖屏两种方式运行。因为UIViewController提供了自动旋转行为,而PRPSplashScreen继承了UIViewController,所以支持多种屏幕方向相当简单。我们先创建一个iPad专用的PRPSplashScreen的子类,添加对各种屏幕方向的支持。
BasicSplashScreen/iPad/PRPSplashScreen_iPad.m
- (BOOL)shouldAutorotateToInterfaceOrientation:
        (UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
子类中只写这几行代码即可,PRPSplashScreen的所有其他行为都原封不动。
最后一件事是提供一幅新的启动图像。当支持多种启动方向时,要提供默认图像的竖屏和横屏版本,UIKit会替我们选择正确的图像。然而,我们的代码无法知道使用的是哪幅,因此不能为启动画面视图选择正确的图像。为此,可以从UIDevice检测设备的方向或者从UIApplication检测状态条的方向,不过还有更简单的办法。既然我们的目的是让LOGO居中,我们可以制作一幅1024×1024像素的新的启动图像。这个大小满足两种方向的最大屏幕尺寸,而且无论设备如何旋转都能够在充满屏幕的同时保持居中。即使动态旋转发生在画面切换之前,图像仍可以保持居中。我们把这幅图像加到app之中,并通过由PRPSplashScreen定义的splashImage属性把它设置为启动画面的启动图像。
BasicSplashScreen/iPad/AppDelegate_iPad.m
- (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self.window addSubview:self.splitViewController.view];
 
    UIImage *splash = [UIImage imageNamed:@"splash_background_ipad.png"];
    self.splashScreen.splashImage = splash;
 
    self.splashScreen.showsStatusBarOnDismissal = YES;
    self.splashScreen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self.splitViewController presentModalViewController:splashScreen animated:NO];
 
    [self.window makeKeyAndVisible];
 
    return YES;
}
初始化代码的其余部分跟iPhone版本相同。请运行iPad版的BasicSplashScreen,观察横屏与竖屏状态下平滑流畅的画面切换,如图4所示。现在我们创建了一个从有特色的默认图像到app的初始UI之间的基本画面切换,这个效果容易复用,既能用于iPhone,又能用于iPad。





图4 iPad上的多种屏幕方向
点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站