2016-08-16 18:12:21 HK_5788 阅读数 800

1、参考资料

        A、ios安全保护--白皮书

        B、知乎

2、启动过程简述

      打开Ios设备后,其应用程序处理器会立即执行只读内存(称为Boot Rom)中的代码,这些不可更改的代码,是在制造芯片的时设计好的,为隐式受信任代码。Boot Rom 代码包含Apple根CA公钥,这个公钥用于验证底层引导加载程序(LLB)是否经过Apple签名,以决定是否允许其加载。这是信任链中的第一步,信任链中的每个步骤都确保下一步周获得Apple的签名。当LLB完成任务后,它会验证并运行下一阶段的引导加载程序iBoot。iBoot 又会验证并运行Ios内核。

       iBoot映射device tree, 加载kernel,校验签名。

       接着kernel初始化,操作系统启动成功。

       最后启动springBoard, 所有应用程序都是由它启动的,同时也是系统消息分发的中心。

       启动过程结束。

2018-02-19 21:37:30 findhappy117 阅读数 830

概述

根据UIBezierPath和CAShapeLayer自定义倒计时进度条,适用于app启动的时候设置一个倒计时关闭启动页面。可以设置进度条颜色,填充颜色,进度条宽度以及点击事件等。

详细

我们都知道 APP启动时加载的是LaunchImage 这张静态图。现在好多应用启动时都是动态的,并且右上角可选择跳过。

动态启动页 下午7.34.54.gif

这里介绍一下自己在做这种动画时的一种方案。

启动图依然是加载的,只不过是一闪而过,这时候我想到的是拿到当前的LaunchImage图片,然后进行处理,造成一种改变了LaunchImage动画的假象。

思路如下:

根据UIBezierPath和CAShapeLayer自定义倒计时进度条,适用于app启动的时候设置一个倒计时关闭启动页面。可以设置进度条颜色,填充颜色,进度条宽度以及点击事件等。

一、设置跳过按钮

ZLDrawCircleProgressBtn.h:

/**
 *  set complete callback
 *
 *  @param lineWidth line width
 *  @param block     block
 *  @param duration  time
 */
- (void)startAnimationDuration:(CGFloat)duration withBlock:(DrawCircleProgressBlock )block;

ZLDrawCircleProgressBtn.m :

先初始化相关跳过按钮及进度圈:

// 底部进度条圈
@property (nonatomic, strong) CAShapeLayer *trackLayer;
// 表层进度条圈
@property (nonatomic, strong) CAShapeLayer *progressLayer;
@property (nonatomic, strong) UIBezierPath *bezierPath;
@property (nonatomic, copy)   DrawCircleProgressBlock myBlock;
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self == [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
        
        [self.layer addSublayer:self.trackLayer];
        
    }
    return self;
}
- (UIBezierPath *)bezierPath {
    if (!_bezierPath) {
        
        CGFloat width = CGRectGetWidth(self.frame)/2.0f;
        CGFloat height = CGRectGetHeight(self.frame)/2.0f;
        CGPoint centerPoint = CGPointMake(width, height);
        float radius = CGRectGetWidth(self.frame)/2;
        
        _bezierPath = [UIBezierPath bezierPathWithArcCenter:centerPoint
                                                     radius:radius
                                                 startAngle:degreesToRadians(-90)
                                                   endAngle:degreesToRadians(270)
                                                  clockwise:YES];
    }
    return _bezierPath;
}

底部进度条圈:

- (CAShapeLayer *)trackLayer {
    if (!_trackLayer) {
        _trackLayer = [CAShapeLayer layer];
        _trackLayer.frame = self.bounds;
        // 圈内填充色
        _trackLayer.fillColor = self.fillColor.CGColor ? self.fillColor.CGColor : [UIColor clearColor].CGColor ;
        _trackLayer.lineWidth = self.lineWidth ? self.lineWidth : 2.f;
        // 底部圈色
        _trackLayer.strokeColor = self.trackColor.CGColor ? self.trackColor.CGColor : [UIColor colorWithRed:197/255.0 green:159/255.0 blue:82/255.0 alpha:0.3].CGColor ;
        _trackLayer.strokeStart = 0.f;
        _trackLayer.strokeEnd = 1.f;
        
        _trackLayer.path = self.bezierPath.CGPath;
    }
    return _trackLayer;
}

表层进度条圈:

- (CAShapeLayer *)progressLayer {
    
    if (!_progressLayer) {
        _progressLayer = [CAShapeLayer layer];
        _progressLayer.frame = self.bounds;
        _progressLayer.fillColor = [UIColor clearColor].CGColor;
        _progressLayer.lineWidth = self.lineWidth ? self.lineWidth : 2.f;
        _progressLayer.lineCap = kCALineCapRound;
        // 进度条圈进度色
        _progressLayer.strokeColor = self.progressColor.CGColor ? self.progressColor.CGColor  : [UIColor  colorWithRed:197/255.0 green:159/255.0 blue:82/255.0 alpha:1].CGColor;
        _progressLayer.strokeStart = 0.f;
        
        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        pathAnimation.duration = self.animationDuration;
        pathAnimation.fromValue = @(0.0);
        pathAnimation.toValue = @(1.0);
        pathAnimation.removedOnCompletion = YES;
        pathAnimation.delegate = self;
        [_progressLayer addAnimation:pathAnimation forKey:nil];
        
        _progressLayer.path = _bezierPath.CGPath;
    }
    return _progressLayer;
}

设置代理回调:

#pragma mark -- CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    if (flag) {
        self.myBlock();
    }
}
#pragma mark ---
- (void)startAnimationDuration:(CGFloat)duration withBlock:(DrawCircleProgressBlock )block {
    self.myBlock = block;
    self.animationDuration = duration;
    [self.layer addSublayer:self.progressLayer];
}

二、启动页

ZLStartPageView.h :

露出 显示引导页面方法:

/**
 *  显示引导页面方法
 */
- (void)show;

ZLStartPageView.m :

  1. 初始化启动页

// 启动页图
@property (nonatomic,strong) UIImageView *imageView;
// 跳过按钮
@property (nonatomic, strong) ZLDrawCircleProgressBtn *drawCircleBtn;
- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        
        // 1.启动页图片
        _imageView = [[UIImageView alloc]initWithFrame:frame];
        _imageView.contentMode = UIViewContentModeScaleAspectFill;
        _imageView.image = [UIImage imageNamed:@"LaunchImage_667h"];
        [self addSubview:_imageView];
        
        // 2.跳过按钮
        ZLDrawCircleProgressBtn *drawCircleBtn = [[ZLDrawCircleProgressBtn alloc]initWithFrame:CGRectMake(kscreenWidth - 55, 30, 40, 40)];
        drawCircleBtn.lineWidth = 2;
        [drawCircleBtn setTitle:@"跳过" forState:UIControlStateNormal];
        [drawCircleBtn setTitleColor:[UIColor  colorWithRed:197/255.0 green:159/255.0 blue:82/255.0 alpha:1] forState:UIControlStateNormal];
        drawCircleBtn.titleLabel.font = [UIFont systemFontOfSize:14];
        
        [drawCircleBtn addTarget:self action:@selector(removeProgress) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:drawCircleBtn];
        self.drawCircleBtn = drawCircleBtn;
        
    }
    return self;
}

2. 显示启动页且完成时候回调移除

- (void)show {
    //  progress 完成时候的回调
    __weak __typeof(self) weakSelf = self;
    [weakSelf.drawCircleBtn startAnimationDuration:showtime withBlock:^{
        [weakSelf removeProgress];
    }];
    
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    [window addSubview:self];
}

3. 移除启动页面

- (void)removeProgress {
    
    self.imageView.transform = CGAffineTransformMakeScale(1, 1);
    self.imageView.alpha = 1;
    
    [UIView animateWithDuration:0.3 animations:^{
        self.drawCircleBtn.hidden = NO;
        self.imageView.alpha = 0.05;
        self.imageView.transform = CGAffineTransformMakeScale(5, 5);
    } completion:^(BOOL finished) {
        
        self.drawCircleBtn.hidden = YES;
        [self.imageView removeFromSuperview];
    }];
}


三、动态启动页的显示代码放在AppDeleate中

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[HomeViewController alloc] init]];
    [self.window makeKeyAndVisible];
    
    [self setupStartPageView];
    
    return YES;
}

设置启动页:

- (void)setupStartPageView {
    
    ZLStartPageView *startPageView = [[ZLStartPageView alloc] initWithFrame:self.window.bounds];
    [startPageView show];
}

这个时候就可以可以测试喽~

四、压缩文件截图

A76F7747-90AB-44F6-BBCC-7B2315EC6291.png

界面性问题可以根据自己项目需求调整即可, 具体可参考代码, 项目能够直接运行!

注:本文著作权归作者,由demo大师(http://www.demodashi.com)宣传,拒绝转载,转载需要作者授权


2015-09-29 00:46:28 freeWayWalker 阅读数 12521

这篇文章站在GUI设计师的角度概述了APP从项目启动到切片输出的过程,相当于工作流程的介绍。这里写的不是一种规范,只是一种工作方法,加上技术的更新是非常快的,大家在具体工作中,一定要灵活运用。

这里我们只说IOS系统下的设计,至于Android,因为尺寸太多,涉及的东西比较乱。1

Part 1 项目立项

文件结构

项目名称v1.0 -> 01_源文件psd
02_效果图jpg
03_标注图png
04_标注源文件
05_切片资源png
原型.rar

工具:

界面设计:PS, AI

标注:PxCook(Windows), Sketch(Mac)

切图:Cutterman(PS插件), Assistor PS(PS插件)

Part 2 Photoshop

设计尺寸

  1. 640*960 4时代的尺寸

  2. 640*1136 5/5S/5C

  3. 750*1334 6 目前我做设计稿的设计尺寸,IPhone6的尺寸,向下可以适配4,5,向上可以适配6 plus。我记得IP6推出后,我问总监应该用什么尺寸设计,他说用IP6的吧,好适配,切出来就是@2x了,改一改上下都能照顾到。
    ps setting - iPhone 6
    推荐做设计稿的时候使用IPhone6的尺寸进行设计。

参考线

文档建立之初就设置好参考线是个很好的工作习惯。上下的参考线很容易设置,因为是根据iPhone自身系统设置的,左右的参考线我习惯设置为24px,也就是显示内容距离边框的距离。这不是绝对的,我和总监研究过,究竟是设置为左右30px还是24px比较好,通过对国内国外各种APP的对比,觉得24px更适合一些,不宽不窄,这个完全是设计师个人的设计习惯,所以不要当成什么规范,确切的说,整个屏幕你都可以随便做,但是我们这里说的是正常页面。

pt和px

公式一:

1pt= (DPI / 72) px

当photoshop中新建画布的分辨率为72ppi( 即 72dpi时 ), 1pt=1px; 当新建画布分辨率为72*2=144ppi时,1pt=2px。

附与尺寸有关的定义:

px:pixel,像素,电子屏幕上组成一幅图画或照片的最基本单元

pt: point,点,印刷行业常用单位,等于1/72英寸

ppi: pixel per inch,每英寸像素数,该值越高,则屏幕越细腻

dpi: dot per inch,每英寸多少点,该值越高,则图片越细腻

dp: dip,Density-independent pixel, 是安卓开发用的长度单位,1dp表示在屏幕像素点密度为160ppi时1px长度

sp: scale-independent pixel,安卓开发用的字体大小单位。2

Part 3 页面标注

标注颜色

颜色用16进制和RGB表示都可能用得到,建议标注颜色时,两种色值表达都标上(16进制&RGB)。

标注内容

文字需要提供:字体大小(px),字体颜色;

顶部标题栏的背景色值,透明度;

标题栏下方以及Tab bar上方其实有一条分割线,需要提供色值;

内容显示区域的背景色;

底部Tab bar的背景色值。

页面需要标注的地方

所有元素统一距离屏幕最左24px。

1、标题栏:背景色,标题栏文字大小,文字颜色;

2、Banner:所有撑满横屏的大图,不需要横向尺寸,把高度标出了就可以了;

3、菜单图标:

图标的大小和图标的可点击区域不一定一致。

也就是说,图标可以做的很小,但是为了保证点击的准确性和流畅性,工程师可以把可点击区域设置的很大,这样标注和切图的时候就要注意,标注的是可点击区域的大小,切图切的也是可点击区域的大小,也就是用透明区域去补上,否则图片会模糊。

4、模块间隔:这个位置其实不是太重要,我习惯标注上这里,麻烦能少则少。

5、图片+文字:这个应该比较常见,只标注一个单位(图+文)就可以了。

图片需要标注宽高。

图片距离上下左右的距离,文字大小颜色,这里的文字其实算两个控件,标题文字以及说明文字,需要单独标出。

6、Tab Bar:这个位置其实比较特殊,你可以单独标注图标大小+文字大小;还可以图标+文字算作一个控件,整个切出来;我们工程师的习惯是用整个的,也就是图标+文字算作一个ICON。

所有的页面标注总结起来就是:标文字,标图片,标间距,标区域;

切图的时候记得输出个偶数尺寸的切片。

Part 4 切片资源的输出

全局性的切图常见问题

① 你的所有设计尺寸,包括图形效果,应该尽量使用偶数。

技术开发使用的尺寸是设计稿像素尺寸的一半,也就是说,如果你用24px的字体,技术那边就是设置为12px。

② 切图尺寸应该提供几套?

*.png IPhone2G,3G,3GS使用(好像没人用这手机了吧)

*@2x.png IPhone4,5,6优先加载此尺寸图片(不是必须使用这个尺寸,是优先加载调用这个尺寸)

*@3x.png IPhone6 plus使用的尺寸

可以简单的理解为倍数关系(其实是为了满足不同分辨率,我觉得不用过于深究),如果你使用IPhone 6尺寸做设计稿,那么切片输出就是@2x,缩小2倍就是@1x,扩大1.5倍就是@3x了。

理论上,为了达到最好的视觉效果,你应该输出三套尺寸,推荐输出三种尺寸的切片资源。

另外现在几乎看不到3GS了,所以需不需要提供一倍图,还是要和工程师讨论一下~

@1x @2x @3x是开发工具Xcode软件需要的UI资源,命好名称后,IOS设备会自动的选取合适尺寸。

③共用资源的图片,输出一张就可以

类似重复的按钮之类的,只要提供一张共用的资源就可以了;上面的文字是技术写上去的。

理论上按照最佳视觉效果,你应该提供多尺寸的图片;但通常我只提供最大尺寸的一张图片即可,这一点要和你的搭档沟通好,却问他需要什么方式。

④切片的输出格式

位图格式:PNG 24,PNG 8,JPG

在JPG和PNG两种格式图片大小相差不是很大的情况下,推荐使用PNG;如果图片大小相差很大,使用JPG。

欢迎页面,ICON一定要使用PNG格式,在不影响视觉效果的前提下,可以考虑使用PNG 8;

矢量图格式:PDF,SVG

IOS原生支持的两种矢量图片格式,但是支持的一般,并不能保证100%把所有图片效果渲染出来;为了保险起见,我通常不使用这两种格式,推荐还是使用位图,如果以后技术提升,100%支持SVG和PDF这种矢量格式图,那个时候也许不用提供这么多套尺寸了~

⑤图标的点击区域

最小点击区域问题:

IOS人机指导手册里推荐的最小可点击元素的尺寸是44*44 point(点),在设备上1 point等于1像素,所以转换成像素就是44*44像素,换算成物理尺寸大概是7mm左右吧(人机工效学研究中得出的结论:用食指操作,触击范围在7mm左右合适;用拇指操作,范围在9mm左右合适)。

⑥图片图标的不同状态

按钮可能有正常(normal),按下(pressed),选中(selected),禁用(disabled)等多种状态。

切片的命名规则

切片种类+功能+图片描述(可有可无)+状态.png

名称应使用英文命名(中文不识别,推荐小写字母),不要以数字或者符号当作开头,使用下划线进行连接。

切图常用命名习惯

举个例子:一个首页的处于正常状态的确定按钮

btn_sure_nor.png

btn_sure_nor@2x.png

切片种类是按钮(btn);功能是确定(sure);状态是normal(正常)

Tab bar(底部栏)

图标+文字的模式,图标最好单独切,文字后面程序加上去。另外记住,同一模块的图标切片大小保持一致。

Part 5 工作常用数据

你需要使用的字体

如果是用Mac设计的小伙伴,直接就用苹果黑体字就好了;不过用Windows的就没那么幸运了,PC上还没和IPhone默认字体效果完全一样的字体,通常都是拿其他字体代替。

苹果丽黑 Hiragino Sans GB W3(普通)/W6(粗体) 比较接近IPhone字体的一款字体,这是我之前一直使用的设计字体。

黑体-简 STHeitiSC-Light Mac里面拷出来的苹果黑体,比较贴近IPhone手机字体,目前在用。

关于字体大小的问题

顶部操作栏文字大小 34-38px

标题文字大小 28-34px

正文文字大小 26-30px

辅助性文字大小 20-24px

Tab bar文字大小 20px

文字大小只是一个范围,这要根据设计的视觉效果来决定,不要死记硬背,但是切记,字体大小要用偶数。

你需要知道的IPhone设计尺寸(这里是一个整屏的尺寸包括了状态栏)

320*480 IPhone3GS (我没见过3GS实体机,只在网上见过图片,但你需要知道这个尺寸)

640*960 IPhone 4/4s (4时代的设计尺寸)

640*1136 IPhone 5/5s/5c (5时代的设计尺寸,虽然现在出来6/6 plus,但还有人再用这个尺寸设计)

750*1334 IPhone 6 (目前最新的设计尺寸,基本上现在做IOS的APP设计,用这个的应该最多)

1242*2208 IPhone6 plus (这是标准分辨率,也就是设计需要的尺寸;另外还存在物理分辨率是1080*1920,这并不需要深入理解。plus还涉及到横屏,横屏是是没有状态栏的,设计横屏时可以参考IPad的设计模式)

你需要提交的启动页面

依据开发工具Xcode提供的LaunchImage(启动页面)的各项尺寸:

320*480 IPhone3GS (我没见过3GS实体机,只在网上见过图片,但你需要知道这个尺寸)

640*960 IPhone 4/4s (4时代的设计尺寸)

640*1136 IPhone 5/5s/5c (5时代的设计尺寸,虽然现在出来6/6 plus,但还有人再用这个尺寸设计)

750*1334 IPhone 6 (目前最新的设计尺寸,基本上现在做IOS的APP设计,用这个的应该最多)

1242*2208 IPhone6 plus (这是标准分辨率,也就是设计需要的尺寸;另外还存在物理分辨率是1080*1920,这并不需要深入理解。plus还涉及到横屏,横屏是是没有状态栏的,设计横屏时可以参考IPad的设计模式)

完整列表如下:

iPhone尺寸规格

设备iPhone 宽Width 高Height 对角线Diagonal 逻辑分辨率(points) Scale Factor 设备分辨率(pixel resolution) PPI
1st gen(includs 1/1G/2G) 2.4 inches (61 mm) 4.5 inches (115 mm) 3.5-inch 320*480 @1x 320*480 163
3G(s) 2.44 inches (62.1 mm) 4.55 inches (115.5 mm) 3.5-inch 320*480 @1x 320*480 163
4(s) 2.31 inches (58.6 mm) 4.54 inches (115.2 mm) 3.5-inch 320x480 @2x 640x960 326
5c 2.33 inches (59.2 mm) 4.90 inches (124.4 mm) 4-inch 320x568 @2x 640x1136 326
5(s) 2.31 inches (58.6 mm) 4.87 inches (123.8 mm) 4-inch 320x568 @2x 640x1136 326
6(s) 2.64 inches (67.0 mm, 67.1 mm for 6s) 5.44 inches (138.1 mm, 138.3 mm for 6s) 4.7-inch standard mode 375x667(zoomed mode 320x568) @2x standard mode 750x1334(zoomed mode 640x1136) 326
6(s) Plus 3.06 inches (77.8 mm), 3.07 inches (77.9 mm) for 6s plus 6.22 inches (158.1 mm), 6.23 inches (158.2 mm) for 6s plus 5.5-inch standard mode 414x736(zoomed mode 375×667) @3x standard mode 1242x2208(zoomed mode 1125×2001) downsampled / 1.15(× 0.96) -> 1080x1920 401

iPad尺寸规格

设备iPad 宽Width 高Height 对角线Diagonal 逻辑分辨率(point) Scale Factor 设备分辨率(pixel) PPI
mini 1 5.3 inches (134.7 mm) 7.87 inches (200 mm) 7.9-inch 768*1024 @1x 768*1024 163
mini 2(3) 5.3 inches (134.7 mm) 7.87 inches (200 mm) 7.9-inch 768*1024 @2x 1536x2048 326
mini 4 5.3 inches (134.8 mm) 8 inches (203.2 mm) 7.9-inch 768*1024 @2x 1536x2048 264
Air(Air 2) 6.6 inches (169.5 mm) 9.4 inches (240 mm) 9.7-inch 768*1024 @2x 1536x2048 264
Pro 8.68 inches (220.6 mm) 12 inches (305.7 mm) 12.9-inch 1024x1366 @2x 2048x2732 264

注意,启动页面一定要是PNG格式的。

图标的提交尺寸

IOS系统可以自动把图片裁剪为圆角,所以提交图标的时候,你只需要提交正方形的PNG图片即可。

因为需要的图标非常多,不可能全部加进去,只能选择最好的尺寸,我们的工程师要求我提供以下图标尺寸:

1024*1024 Retina APP Icon for APP Store(高清屏的APP Store)

512*512 APP Icon for APP Store(普通屏幕的APP Store)

120*120 6的主屏幕尺寸

114*114 5/4s/4的主屏幕图标尺寸

57*57 3GS的主屏幕图标尺寸

58*58 Retina Settings图标尺寸

29*29 Settings图标尺寸

提交的图标尺寸不是固定的,所以,去找和你搭档的工程师,让他给你出一份需要提交的图标尺寸文档。


  1. “纯干货!一款APP从设计稿到切图过程全方位揭秘” http://www.uisdc.com/from-design-to-slice
  2. “扒一扒那些px、pt、ppi、dpi、dp、sp之间的关系” http://design.jobbole.com/92179/
2019-06-26 18:48:39 qihoo_tech 阅读数 1163

奇技指南

本文来自360奇舞团iOS团队QiShare投稿,原文:

https://www.jianshu.com/p/f4e78a44ddf8


前情回顾

一个完整的app都需要多种尺寸的图标和启动图。一般情况,设计师根据开发者提供的一套规则,设计出图标和启动图供开发人员使用。但最近作者利用业余时间做了个app,不希望耽误设计师较多时间,就只要了最大尺寸的图标和启动图各一个。本想着找一下现成的工具,批量生成需要的的图片,但最后没有找到,只好使用Photoshop切出了不同尺寸的图片。这期间,设计师还换过一次图标和启动图,作者就重复了切图工作,这花费了大量的时间。于是事后,作者开发了一个mac app——图标&启动图生成器(简称生成器)以提高工作效率。

作者用两篇文章分别介绍生成器的使用和实现细节。本文是第二篇。


上篇文章《iOS 图标&启动图生成器(一)》,本篇文章介绍生成器的实现细节。

生成器的工程非常简单,可以概括为一个界面一个资源文件和一个ViewController。结构如下图。

640?wx_fmt=other


01

界面

生成器app只有一个界面,因为界面复杂度较小,作者选用了Storyboard+Constraints的方式进行开发。下图显示了界面中的控件和约束情况。

640?wx_fmt=other


其中各控件对应的类如下所示。

控件
图片框NSImageView
平台选择器NSComboBox
路径按钮NSButton
路径文本框NSTextField
导出按钮NSButton



02

资源文件

app所支持的平台规则数据从资源文件QiConfiguration.plist中获取。QiConfiguration.plist相当于一个字典,每个平台对应着字典的一对keyvalue;
value是一个数组,存储着该平台所需要的一组尺寸规格数据(item);
item是尺寸规格数据的最小单元,内部标记了该尺寸规格的图片的用途、名称和尺寸。

QiConfiguration.plist的具体结构如下图所示。

640?wx_fmt=other


03

ViewController

工程使用默认的ViewController管理界面、资源数据和逻辑。
首先,界面控件元素在ViewController中对应下图中的5个实例。

640?wx_fmt=other

其中,imageViewplatformBoxpathField不需要响应方法。并且,platfromBox_pathField的默认/记忆数据由NSUserDefaults管理。


static NSString * const selectedPlatformKey = @"selectedPlatform";static NSString * const exportedPathKey = @"exportedPath";NSString * const selectedPlatformKey = @"selectedPlatform";
static NSString * const exportedPathKey = @"exportedPath";
- (void)viewDidLoad {        [super viewDidLoad];        NSString *selectedPlatform = [[NSUserDefaults standardUserDefaults] objectForKey:selectedPlatformKey];    [_platformBox selectItemWithObjectValue:selectedPlatform];        NSString *lastExportedPath = [[NSUserDefaults standardUserDefaults] objectForKey:exportedPathKey];    _pathField.stringValue = lastExportedPath ?: NSHomeDirectory();}

[super viewDidLoad];

NSString *selectedPlatform = [[NSUserDefaults standardUserDefaults] objectForKey:selectedPlatformKey];
[_platformBox selectItemWithObjectValue:selectedPlatform];

NSString *lastExportedPath = [[NSUserDefaults standardUserDefaults] objectForKey:exportedPathKey];
_pathField.stringValue = lastExportedPath ?: NSHomeDirectory();
}

这里忽略这三个控件,重点介绍pathButtonexportButton的响应方法中的代码逻辑。


1. -pathButtonClicked:

pathButton的响应方法负责打开文件目录,并回传选择的路径给pathField,以显示出来。

代码如下:

- (IBAction)pathButtonClicked:(NSButton *)sender {        NSOpenPanel *openPanel = [NSOpenPanel openPanel];    openPanel.canChooseDirectories = YES;    openPanel.canChooseFiles = NO;    openPanel.title = @"选择导出目录";    [openPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse result) {        if (result == NSModalResponseOK) {            self.pathField.stringValue = openPanel.URL.path;        }    }];}NSButton *)sender {

NSOpenPanel *openPanel = [NSOpenPanel openPanel];
openPanel.canChooseDirectories = YES;
openPanel.canChooseFiles = NO;
openPanel.title = @"选择导出目录";
[openPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse result) {
if (result == NSModalResponseOK) {
self.pathField.stringValue = openPanel.URL.path;
}
}];
}


2. - exportButtonClicked

exportButton的响应方法负责根据imageView中的源图片、platform中选择的平台规则和pathField中显示的导出路径生成图片并打开图片所在的文件夹。

代码如下:

- (IBAction)exportButtonClicked:(NSButton *)sender {        NSImage *image = _imageView.image;    NSString *platform = _platformBox.selectedCell.title;    NSString *exportPath = _pathField.stringValue;        if (!image || !platform || !exportPath) {        NSAlert *alert = [[NSAlert alloc] init];        alert.messageText = @"请先选择源图片、平台和导出路径";        alert.alertStyle = NSAlertStyleWarning;        [alert addButtonWithTitle:@"确认"];        [alert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) {}];    }    else {        [[NSUserDefaults standardUserDefaults] setObject:platform forKey:selectedPlatformKey];        [[NSUserDefaults standardUserDefaults] synchronize];        [[NSUserDefaults standardUserDefaults] setObject:exportPath forKey:exportedPathKey];        [[NSUserDefaults standardUserDefaults] synchronize];                [self generateImagesForPlatform:platform fromOriginalImage:image];    }}NSButton *)sender {

NSImage *image = _imageView.image;
NSString *platform = _platformBox.selectedCell.title;
NSString *exportPath = _pathField.stringValue;

if (!image || !platform || !exportPath) {
NSAlert *alert = [[NSAlert alloc] init];
alert.messageText = @"请先选择源图片、平台和导出路径";
alert.alertStyle = NSAlertStyleWarning;
[alert addButtonWithTitle:@"确认"];
[alert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) {}];
}
else {
[[NSUserDefaults standardUserDefaults] setObject:platform forKey:selectedPlatformKey];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] setObject:exportPath forKey:exportedPathKey];
[[NSUserDefaults standardUserDefaults] synchronize];

[self generateImagesForPlatform:platform fromOriginalImage:image];
}
}
- (void)generateImagesForPlatform:(NSString *)platform fromOriginalImage:(NSImage *)originalImage {        NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"QiConfiguration" ofType:@"plist"];    NSDictionary *configuration = [NSDictionary dictionaryWithContentsOfFile:plistPath];    NSArray<NSDictionary *> *items = configuration[platform];        NSString *directoryPath = [[_pathField.stringValue stringByAppendingPathComponent:platform] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];    [[NSFileManager defaultManager] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];        if ([platform containsString:@"AppIcons"]) {        [self generateAppIconsWithConfigurations:items fromOriginalImage:originalImage toDirectoryPath:directoryPath];    }    else if ([platform containsString:@"LaunchImages"]) {        [self generateLaunchImagesWithConfigurations:items fromOriginalImage:originalImage toDirectoryPath:directoryPath];    }}- (void)generateAppIconsWithConfigurations:(NSArray<NSDictionary *> *)configurations fromOriginalImage:(NSImage *)originalImage toDirectoryPath:(NSString *)directoryPath {        for (NSDictionary *configuration in configurations) {        NSImage *appIcon = [self generateAppIconWithImage:originalImage forSize:NSSizeFromString(configuration[@"size"])];        NSString *filePath = [NSString stringWithFormat:@"%@/%@.png", directoryPath, configuration[@"name"]];        [self exportImage:appIcon toPath:filePath];    }    [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:directoryPath isDirectory:YES]];}- (void)generateLaunchImagesWithConfigurations:(NSArray<NSDictionary *> *)configurations fromOriginalImage:(NSImage *)originalImage toDirectoryPath:(NSString *)directoryPath {        for (NSDictionary *configuration in configurations) {        NSImage *launchImage = [self generateLaunchImageWithImage:originalImage forSize: NSSizeFromString(configuration[@"size"])];                NSString *filePath = [NSString stringWithFormat:@"%@/%@.png", directoryPath, configuration[@"name"]];        [self exportImage:launchImage toPath:filePath];    }    [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:directoryPath isDirectory:YES]];}- (NSImage *)generateAppIconWithImage:(NSImage *)fromImage forSize:(CGSize)toSize  {        NSRect toFrame = NSMakeRect(.0, .0, toSize.width, toSize.height);    toFrame = [[NSScreen mainScreen] convertRectFromBacking:toFrame];        NSImageRep *imageRep = [fromImage bestRepresentationForRect:toFrame context:nil hints:nil];    NSImage *toImage = [[NSImage alloc] initWithSize:toFrame.size];        [toImage lockFocus];    [imageRep drawInRect:toFrame];    [toImage unlockFocus];        return toImage;}- (NSImage *)generateLaunchImageWithImage:(NSImage *)fromImage forSize:(CGSize)toSize {        // 计算目标小图去贴合源大图所需要放大的比例    CGFloat wFactor = fromImage.size.width / toSize.width;    CGFloat hFactor = fromImage.size.height / toSize.height;    CGFloat toFactor = fminf(wFactor, hFactor);        // 根据所需放大的比例,计算与目标小图同比例的源大图的剪切Rect    CGFloat scaledWidth = toSize.width * toFactor;    CGFloat scaledHeight = toSize.height * toFactor;    CGFloat scaledOriginX = (fromImage.size.width - scaledWidth) / 2;    CGFloat scaledOriginY = (fromImage.size.height - scaledHeight) / 2;    NSRect fromRect = NSMakeRect(scaledOriginX, scaledOriginY, scaledWidth, scaledHeight);        // 生成即将绘制的目标图和目标Rect    NSRect toRect = NSMakeRect(.0, .0, toSize.width, toSize.height);    toRect = [[NSScreen mainScreen] convertRectFromBacking:toRect];    NSImage *toImage = [[NSImage alloc] initWithSize:toRect.size];        // 绘制    [toImage lockFocus];    [fromImage drawInRect:toRect fromRect:fromRect operation:NSCompositeCopy fraction:1.0];    [toImage unlockFocus];        return toImage;}- (void)exportImage:(NSImage *)image toPath:(NSString *)path {        NSData *imageData = image.TIFFRepresentation;    NSData *exportData = [[NSBitmapImageRep imageRepWithData:imageData] representationUsingType:NSPNGFileType properties:@{}];        [exportData writeToFile:path atomically:YES];}NSString *)platform fromOriginalImage:(NSImage *)originalImage {

NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"QiConfiguration" ofType:@"plist"];
NSDictionary *configuration = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSArray<NSDictionary *> *items = configuration[platform];

NSString *directoryPath = [[_pathField.stringValue stringByAppendingPathComponent:platform] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];

if ([platform containsString:@"AppIcons"]) {
[self generateAppIconsWithConfigurations:items fromOriginalImage:originalImage toDirectoryPath:directoryPath];
}
else if ([platform containsString:@"LaunchImages"]) {
[self generateLaunchImagesWithConfigurations:items fromOriginalImage:originalImage toDirectoryPath:directoryPath];
}
}

- (void)generateAppIconsWithConfigurations:(NSArray<NSDictionary *> *)configurations fromOriginalImage:(NSImage *)originalImage toDirectoryPath:(NSString *)directoryPath {

for (NSDictionary *configuration in configurations) {
NSImage *appIcon = [self generateAppIconWithImage:originalImage forSize:NSSizeFromString(configuration[@"size"])];
NSString *filePath = [NSString stringWithFormat:@"%@/%@.png", directoryPath, configuration[@"name"]];
[self exportImage:appIcon toPath:filePath];
}
[[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:directoryPath isDirectory:YES]];
}

- (void)generateLaunchImagesWithConfigurations:(NSArray<NSDictionary *> *)configurations fromOriginalImage:(NSImage *)originalImage toDirectoryPath:(NSString *)directoryPath {

for (NSDictionary *configuration in configurations) {
NSImage *launchImage = [self generateLaunchImageWithImage:originalImage forSize: NSSizeFromString(configuration[@"size"])];

NSString *filePath = [NSString stringWithFormat:@"%@/%@.png", directoryPath, configuration[@"name"]];
[self exportImage:launchImage toPath:filePath];
}
[[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:directoryPath isDirectory:YES]];
}

- (NSImage *)generateAppIconWithImage:(NSImage *)fromImage forSize:(CGSize)toSize {

NSRect toFrame = NSMakeRect(.0, .0, toSize.width, toSize.height);
toFrame = [[NSScreen mainScreen] convertRectFromBacking:toFrame];

NSImageRep *imageRep = [fromImage bestRepresentationForRect:toFrame context:nil hints:nil];
NSImage *toImage = [[NSImage alloc] initWithSize:toFrame.size];

[toImage lockFocus];
[imageRep drawInRect:toFrame];
[toImage unlockFocus];

return toImage;
}

- (NSImage *)generateLaunchImageWithImage:(NSImage *)fromImage forSize:(CGSize)toSize {

// 计算目标小图去贴合源大图所需要放大的比例
CGFloat wFactor = fromImage.size.width / toSize.width;
CGFloat hFactor = fromImage.size.height / toSize.height;
CGFloat toFactor = fminf(wFactor, hFactor);

// 根据所需放大的比例,计算与目标小图同比例的源大图的剪切Rect
CGFloat scaledWidth = toSize.width * toFactor;
CGFloat scaledHeight = toSize.height * toFactor;
CGFloat scaledOriginX = (fromImage.size.width - scaledWidth) / 2;
CGFloat scaledOriginY = (fromImage.size.height - scaledHeight) / 2;
NSRect fromRect = NSMakeRect(scaledOriginX, scaledOriginY, scaledWidth, scaledHeight);

// 生成即将绘制的目标图和目标Rect
NSRect toRect = NSMakeRect(.0, .0, toSize.width, toSize.height);
toRect = [[NSScreen mainScreen] convertRectFromBacking:toRect];
NSImage *toImage = [[NSImage alloc] initWithSize:toRect.size];

// 绘制
[toImage lockFocus];
[fromImage drawInRect:toRect fromRect:fromRect operation:NSCompositeCopy fraction:1.0];
[toImage unlockFocus];

return toImage;
}

- (void)exportImage:(NSImage *)image toPath:(NSString *)path {

NSData *imageData = image.TIFFRepresentation;
NSData *exportData = [[NSBitmapImageRep imageRepWithData:imageData] representationUsingType:NSPNGFileType properties:@{}];

[exportData writeToFile:path atomically:YES];
}

上述是工程的所有代码,代码较多。建议有需要的同学移步至工程源码阅读(点击阅读原文查看)。

地址:

https://github.com/QiShare/QiAppIconGenerator


相关阅读

不会PS如何快速得到自己想要的图片——iOS图标&启动图生成器


界世的你当不

只做你的肩膀

640?wx_fmt=jpeg640?wx_fmt=jpeg

 360官方技术公众号 

技术干货|一手资讯|精彩活动

空·


2016-01-09 17:11:16 junbaozi 阅读数 547

启动页专题

 

总述:

两种方式,一种是使用系统自带的,按规则定义启动图片名称即可,显示为1秒,要想延长时间,用[nsthread sleepForTimeInterval:5.0 ,另一种就是自定义uiivew,加到window中去。

1    系统自带方式

1.1    添加图片

1,准备图片资源,放入工程中,即可,默认时间为1s

      iOS设备现在有三种不同的分辨率:iPhone 320x480iPhone 4 640x960iPad 768x1024。以前程序的启动画面(图片)只要准备一个 Default.png 就可以了,但是现在变得复杂多了。下面就是 CocoaChina 会员做得总结

  如果一个程序,既支持iPhone又支持iPad,那么它需要包含下面几个图片:

Default-Portrait.png iPad专用竖向启动画面 768x1024或者768x1004

Default-Landscape.png iPad专用横向启动画面 1024x768或者1024x748

Default-PortraitUpsideDown.png iPad专用竖向启动画面(Home按钮在屏幕上面),可省略 768x1024或者768x1004

Default-LandscapeLeft.png iPad专用横向启动画面,可省略 1024x768或者1024x748

Default-LandscapeRight.png iPad专用横向启动画面,可省略 1024x768或者1024x748

Default.png iPhone默认启动图片,如果没有提供上面几个iPad专用启动图片,则在iPad上运行时也使用Default.png(不推荐) 320x480或者320x460

Default@2x.png iPhone4启动图片640x960或者640x920

 

  为了在iPad上使用上述的启动画面,你还需要在info.plist中加入key: UISupportedInterfaceOrientations。同时,加入值UIInterfaceOrientationPortrait, UIInterfacOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight

1.2    延迟时间

2,如果想想设启动画面的显示时间,

XXXAppDelegate.m- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法中插入以下一行代码:

 

  // Insert delay of 5 seconds befor the splash screen disappers.

 

  [NSThread sleepForTimeInterval:5.0];  // 其实这一行代码也可以不加,因为默认情况下欢迎界面的时间只有一秒,加这一句是为了延长

 

 欢迎界面的展示时间到5秒,时间大家可以自己定义。

 

1.3    启动时显示状态栏

•  <AppName>-info.plist文件中加入选项 "Status bar is initiallyhidden",值为 YES



AppDelegate.m文件中的 - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法内加入代码:   [[UIApplication sharedApplication] setStatusBarHidden:NO];

 

【注意】

如果你的程序同时使用了导航栏作为根视图控制器 UINavigationController,则应该将语句 [[UIApplication sharedApplication] setStatusBarHidden:NO]放在 [self.window makeKeyAndVisible];之前,否则会出现状态栏与导航栏重叠的情况。可能是因为调用 makeKeyAndVisible时会去判断当前程序是否显示状态栏,以此来布导航栏的位置。

 

2    自定义方法

3,在XXXAppDelegate.m- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions中通过使用uiviewuiimageview等控件自定义启动画面

3    App 图标添加

 

The app icon set named "AppIcon" did not have anyapplicable content.

Solution: 

1.DeleteApp Icon segment in Images.xcassets.

2.Createa new App Icon segment in Images.xcassets. (It will add all iOS device iconsize needness)

3.Modifythe icon size to mach the icon size.

4.Dropinto the icon set.

5.Rebuild.

 

http://www.cnblogs.com/xuzhong/p/3775975.html

 

4    引导页开发

4.1    UIScrollview+UIImageView方案

我们在第一次打开App的时候,通常不是直接进入App主界面,而是会有一个能左右滑动、介绍App功能的界面。我是用NSUserDefaults +UIScrollview实现。

新建一个类,继承UIView,假设名为Guide。在initWithFrame方法里:

  CGFloat screenHeight = [UIScreenmainScreen].bounds.size.height;

  UIScrollView* scrollView =[[UIScrollView alloc] initWithFrame:frame];

  scrollView.backgroundColor =[UIColor whiteColor];

 scrollView.showsHorizontalScrollIndicator = NO;

 scrollView.showsVerticalScrollIndicator = NO;

  scrollView.contentSize =CGSizeMake(320*4, screenHeight);

  scrollView.pagingEnabled = YES;

  for (int i=0; i<4; i++) {

    UIImageView* imageView =[[UIImageView alloc initWithFrame:CGRectMake(i*320, 0, 320, screenHeight)];

  imageView.contentMode =UIViewContentModeScaleAspectFill;

 

  NSString *filePath = [[NSBundlemainBundle] pathForResource:

              [NSStringstringWithFormat:@"FileName"

                       ofType:@"FileType"];

  imageView.image = [UIImageimageWithContentsOfFile:filePath];

  [scrollView addSubview:imageView];

  if (i == 3) {

    UIButton* start = [UIButtonbuttonWithType:UIButtonTypeCustom];

    start.frame = CGRectMake(0,0, 100,44);

    start.layer.cornerRadius = 5;

    start.layer.borderWidth = 0.5;

    [start setCenter:CGPointMake(1120, iPhone5?450:400)];

    [start setTitleColor:[UIColorgrayColor] forState:UIControlStateNormal];

    [start addTarget:selfaction:@selector(closeView) forControlEvents:UIControlEventTouchUpInside];

    [start setTitle:@"Start" forState:UIControlStateNormal];

    [scrollView addSubview:start];

  }

这样,就有了一个有4张图片的引导页。

怎么去判断是不是第一次登陆呢,需要用到NSUserDefaults类。

didFinishLaunchingWithOptions:函数中可以这样判断:

NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];

if([userDefaults objectForKey:@"FirstLoad"] == nil) {

    [userDefaults setBool:NO forKey:@"FirstLoad"];

    //显示引导页

}

 

4.2    UIScrollview+UIPageControl

 

ios用户引导页

http://blog.csdn.net/wanglj7525/article/details/43408809

 

http://www.open-open.com/lib/view/open1411201907593.html

http://blog.csdn.net/yesjava/article/details/7894663

 

@interface WelcomeViewController ()<UIScrollViewDelegate>

 

@end

 

@implementation WelcomeViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScrollView];

    [self setupPageControl];

}

//创建程序第一次加载要显示的视图

 

- (void)setupScrollView

 

{

    CGRect r = [[UIScreen mainScreen] applicationFrame];

    UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:[UIScreen mainScreen].bounds];

    scrollView.delegate =self;

    [self.view addSubview:scrollView];

    //关闭水平方向上的滚动条

    scrollView.showsHorizontalScrollIndicator =NO;

    //是否可以整屏滑动

    scrollView.pagingEnabled =YES;

    scrollView.tag =200;

    scrollView.contentSize =CGSizeMake(r.size.width *3, [UIScreen mainScreen].bounds.size.height);

    for (int i = 0; i < 3; i++) {

        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(r.size.width * i,0,r.size.width, [UIScreen mainScreen].bounds.size.height)];

        imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"t%d_full", i +1]ofType:@"jpg"]];

        [scrollView addSubview:imageView];

    }

   

    UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];

    button.backgroundColor=[UIColor darkGrayColor];

    [button setTitle:@"开始体验" forState:UIControlStateNormal];

    button.frame=CGRectMake(r.size.width*2+r.size.width/2-50, [UIScreen mainScreen].bounds.size.height -80, 100, 30);

    [button addTarget:self action:@selector(showDocList) forControlEvents:UIControlEventTouchUpInside];

    [button setImage:[UIImage imageNamed:@"start.png"] forState:UIControlStateNormal];

    button.imageEdgeInsets=UIEdgeInsetsMake(0, 80, 0, 0);

    button.titleEdgeInsets=UIEdgeInsetsMake(0, -40, 0, 20);

    [scrollView addSubview:button];

    

}

//跳转到主页面

-(void)showDocList{

    ScrollerViewController *mainList=[self.storyboard instantiateViewControllerWithIdentifier:@"mainNavigation"];

    [self presentViewController:mainList animated:NO completion:nil];

}

 

- (void)setupPageControl

{

    UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height -40, [UIScreen mainScreen].bounds.size.width, 20)];

    pageControl.tag =100;

    //设置表示的页数

    pageControl.numberOfPages =3;

    //设置选中的页数

    pageControl.currentPage =0;

    //设置未选中点的颜色

    pageControl.pageIndicatorTintColor = [UIColor whiteColor];

    //设置选中点的颜色

    pageControl.currentPageIndicatorTintColor = [UIColor orangeColor];

    //添加响应事件

    [pageControl addTarget:self action:@selector(handlePageControl:)forControlEvents:UIControlEventValueChanged];

    [self.view addSubview:pageControl];

    

}

 

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

 

{

    UIPageControl *pagControl = (UIPageControl *)[self.view viewWithTag:100];

    pagControl.currentPage = scrollView.contentOffset.x / [UIScreen mainScreen].bounds.size.width;

    

}

 

- (void)handlePageControl:(UIPageControl *)pageControl

 

{

    //切换pageControl .对应切换scrollView不同的界面

    UIScrollView *scrollView = (UIScrollView *)[self.view viewWithTag:200];

    //

    [scrollView setContentOffset:CGPointMake(320 * pageControl.currentPage,0)animated:YES];

    

}

 

4.3    第三方库MYBlurIntroductionView方案

4.3.1 设计思路

            新建一个LaunchVC,然后在RootVC中以模态窗口的方式弹出此VC。引导页采用本地缓存方式,支持从服务端动态加载然后更新显示。

4.3.2 LaunchVC弹出逻辑

LaunchVC弹出逻辑(注意只加载一次):

if (![MDUtilityhasLoadLaunchView]) {

        _launchVC = [[MDLaunchViewControlleralloc] init];

        [self.navigationControllerpresentViewController:_launchVCanimated:NOcompletion:nil];

    }

 

4.3.3 LaunchVC初始化逻辑

LaunchVC初始化逻辑:

- (void)viewDidLoad {

    [super viewDidLoad];

   

    [self initSubViews];

   

    // Doany additional setup after loading the view.

}

 

-(void) initSubViews

{

    if (!_introductView) {

        [self initIntroductView];

    }

}

 

-(void)initIntroductView

{

    NSArray *launchImgFileArr = [MDUtilitygetLaunchImgFilePathArr];

   

    if ([launchImgFileArr count] <= 0) {

        return;

    }

   

    //动态加载引导页图片

    NSMutableArray *panelMArr = [[NSMutableArrayalloc] init];

   

    for (NSString *imgFilein launchImgFileArr) {

        //Create Stock Panel With Image

//        MYIntroductionPanel*launchView = [[MYIntroductionPanel alloc] initWithFrame:CGRectMake(0, 0,self.view.frame.size.width, self.view.frame.size.height) title:nildescription:nil image:[UIImage imageWithContentsOfFile:imgFile]];

 

        MDLaunchView *launchView = [[MDLaunchViewalloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width,self.view.frame.size.height)WithbackImg:[UIImageimageWithContentsOfFile:imgFile]];

       

        [panelMArr addObject:launchView];

    }

   

    //Createthe introduction view and set its delegate

    MYBlurIntroductionView *introductionView = [[MYBlurIntroductionViewalloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width,self.view.frame.size.height)];

    introductionView.delegate =self;

    //    introductionView.BackgroundImageView =[UIImage imageNamed:@"Toronto, ON.jpg"];

    //introductionView.LanguageDirection= MYLanguageDirectionRightToLeft;

    _introductView = introductionView;

   

    //Buildthe introduction with desired panels

    [introductionView buildIntroductionWithPanels:panelMArr];

   

    //Addthe introduction to your view

    [self.viewaddSubview:introductionView];

}

 

4.3.4 本地缓存引导图片逻辑

+(BOOL)hasLoadLaunchView

{

    BOOL loaded = [[[NSUserDefaultsstandardUserDefaults] valueForKey:kHasLoadLaunchView] boolValue];

   

    return loaded;

}

 

//刷新本地缓存的引导页图片数据

+ (void)loadLaunchImgData

{

    // 获取Documents目录路径

    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);

    NSString *docDir= [paths objectAtIndex:0];

   

    NSString*launchDir = [docDirstringByAppendingString:@"/LaunchImg"];

   

    NSFileManager*fm=[NSFileManagerdefaultManager];

//    NSString *imagePath = [[NSBundlemainBundle] pathForResource:@"22" ofType:@"jpg"];

   

    if(![fmfileExistsAtPath:launchDir]){

        NSError*error = nil;

        //下面是对该文件进行制定路径的保存

        [fm createDirectoryAtPath:launchDirwithIntermediateDirectories:YESattributes:nilerror:nil];

       

        NSString*sourcePath = [[NSBundlemainBundle] pathForResource:@"1"ofType:@"jpg"];

        NSString*toPath = [launchDirstringByAppendingString:@"/1.jpg"];

        [fm copyItemAtPath:sourcePathtoPath:toPatherror:&error];

        if(error) {

            return;

        }

//        [[self class] copyFile:sourcePathTo:toPath];

       

        sourcePath = [[NSBundlemainBundle] pathForResource:@"2"ofType:@"jpg"];

        toPath = [launchDir stringByAppendingString:@"/2.jpg"];

        [fm copyItemAtPath:sourcePathtoPath:toPatherror:&error];

        if(error) {

            return;

        }

       

        sourcePath = [[NSBundlemainBundle] pathForResource:@"3"ofType:@"jpg"];

        toPath = [launchDir stringByAppendingString:@"/3.jpg"];

        [fm copyItemAtPath:sourcePathtoPath:toPatherror:&error];

        if(error) {

            return;

        }

       

        sourcePath = [[NSBundlemainBundle] pathForResource:@"4"ofType:@"jpg"];

        toPath = [launchDir stringByAppendingString:@"/4.jpg"];

        [fm copyItemAtPath:sourcePathtoPath:toPatherror:&error];

        if(error) {

            return;

        }

       

        [[NSUserDefaults standardUserDefaults] setValue:[NSNumbernumberWithBool:NO]forKey:kHasLoadLaunchView];

    }

    else

    {

        [[NSUserDefaults standardUserDefaults] setValue:[NSNumbernumberWithBool:YES]forKey:kHasLoadLaunchView];

       

        ///TODO:后续在此进行网络请求,删除本地文件,然后更新本地文件,然后重置kHasLoadLaunchView值为NO

    }

}

 

+(NSArray *)getLaunchImgFilePathArr

{

    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);

    NSString*docDir = [paths objectAtIndex:0];

   

    NSString*launchDir = [docDirstringByAppendingString:@"/LaunchImg"];

   

    NSFileManager*fm=[NSFileManagerdefaultManager];

   

    //取得一个目录下得所有文件名

    NSArray*files = [fm subpathsAtPath:launchDir];

   

    if([files count] > 0) {

        NSMutableArray*filePathArr = [[NSMutableArrayalloc] init];

       

        for (NSString *fpinfiles) {

            [filePathArr addObject:[launchDirstringByAppendingString:[NSStringstringWithFormat:@"/%@",fp]]];

        }

       

        returnfilePathArr;

    }

    else

        return nil;

}

  

5    半透明遮罩

5.1    法一

我最后采取的方法,是present一个窗口化的ViewController。但是这个窗口默认的背景色是磨砂不透明的,因此还需要把它的背景色设为透明。这样看起来就像是全屏遮罩一样,但是由于系统不认为新的View是全屏的,所以上一个View也不会被unload

 

YLSLockScreenViewController*lockScreenController = [[YLSLockScreenViewController alloc] init];

lockScreenController.modalPresentationStyle= UIModalPresentationFormSheet;//窗口

      

[self.mainViewControllerpresentViewController:lockScreenController animated:YES completion:^(void){

   lockScreenController.view.superview.backgroundColor = [UIColorclearColor];//背景色透明

}];

 

代码比较简单,需要注意的是,设置背景色透明的那行代码,需要写在completion block里,而且设置的不是controller.view.backgroundColor,而是controller.view.superview.backgroundColor

 

iOS7实现全屏模态半透明页面的效果

http://www.open-open.com/lib/view/open1392707807819.html

 

5.2    法二(good)

backgroundView = [[UIView alloc] init];

    backgroundView.frame= CGRectMake(0, 0,kWidth,kHeight);

    backgroundView.backgroundColor= [UIColor colorWithRed:(40/255.0f) green:(40/255.0f) blue:(40/255.0f)alpha:1.0f];

    backgroundView.alpha= 0.4;

    [self.view.windowaddSubview:backgroundView];

建立一个view设置背景颜色  调整 alpha

 

iOS 模糊半透明效果实现

http://my.oschina.net/kevinvane/blog/129707

 

 

6    参考链接

 

IOS 启动页面制作

http://my.oschina.net/xiahuawuyu/blog/169113

 

ios用户引导页

http://blog.csdn.net/wanglj7525/article/details/43408809

 

IOS用户引导界面示例

http://www.open-open.com/lib/view/open1411201907593.html

 

ios 页面跳转

http://blog.csdn.net/yesjava/article/details/7894663

 

iOS开发UIScrollView制作APP引导页

http://jingyan.baidu.com/article/4dc40848a341dfc8d846f152.html

 

iOS引导页实现(一)

http://blog.csdn.net/lwjok2007/article/details/46516047

 

iOS启动时如何添加引导页面 小demo

http://blog.csdn.net/yudandan10/article/details/42009511

 

IOS闪屏制作——程序启动动画

http://my.oschina.net/amoyai/blog/94988

 

ios 实现引导页面效果

http://blog.csdn.net/leechee_1986/article/details/24850547

 

半透明遮罩是如何实现的(如图)

http://www.cocoachina.com/bbs/read.php?tid=94649


iOS 启动图尺寸大小

阅读数 12539

程序启动欢迎界面

博文 来自: alex_birdlion

Ios设计模式

阅读数 181

iOS设计规范

阅读数 909

没有更多推荐了,返回首页