- 在项目的作用:引导页的使用
- 怎么来插入引导页
- 当第一次进入程序时,为了给用户一个良好的体验,所以需要进行介绍,让用户更好的了解程序的功能。
- 如果是用户第二次后者说是以后再次点开程序时,则不需要再进行介绍,直接跳转到主程序即可。
- 还有,当程序版本进行更新的时候,启动程序的时候,再次进入引导页,当然此时的引导页应该显示新的内容。
- 所以,进行构想。 记录版本号,当前版本号与旧版本号进行比较,如果相同则直接进入程序,如果不一样则进入引导页。
- 代码实现如下
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1.创建窗口
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 判断下当前有没有最新的版本
// 最新的版本保存到info.plist文件
NSString *curVersion = [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"];
// 获取上一次保存的最新版本号
NSString *lastVersion = [[NSUserDefaults standardUserDefaults] objectForKey:@"vision"];
NSLog(@"%@",[NSUserDefaults standardUserDefaults]);
UIViewController *rootVc;
if ([curVersion isEqualToString:lastVersion]) { // 相等
// 没新版本,进入主框架界面
// 创建tabBarVc
rootVc = [[LXLTabBarController alloc] init];
}else{ // 表示有最新的版本号,进入新特性界面
// 如果有,进入新特性界面
rootVc = [[UIViewController alloc] init];
rootVc.view.backgroundColor = [UIColor greenColor];
// 保存当前的最新的版本号
[[NSUserDefaults standardUserDefaults] setObject:curVersion forKey:@"vision"];
}
// 2.设置窗口的根控制器
self.window.rootViewController = rootVc;
// 3.让窗口显示
[self.window makeKeyAndVisible];
return YES;
}
- 关于新特性界面的选择
- 新特性界面是有几张图片组成的
- 如果有多张的话,节约内存,希望能进行循环使用最好。
- 实现方案
- 在UIViewController上加入UIScrollView,并让UIScrollView的尺寸同屏幕尺寸一样大小,在其上面加载图片,并加入分页功能。
- 可以加入UITableViewController它内部是UITableView,因为它的cell是可以显示图片,也能显示内容。所以设想,如果能把其横过来放置,然后cell的尺寸为屏幕尺寸的话,这样的话,也是可以显示的。并且对于UITableViewController的cell是能循环利用的,这样的话,也就节约了内容。使用效果很好。
- 学习一个新的控制器UICollectionViewController 内部是 UICollectionView,个人觉得它是有scrollview的分页功能,又可以在里面放尺寸随意的控件。
- 对于特定控制器,它的内部的view则为它的特定view,不要调用self.view需要调用它的特定的view,因为有时候两个view真的不一样。 需要注意,(真的不好理解,后面有一点代码进行说明)。
- 循环思想的说明
- 缓存池思想,出现新的控件或者说要显示新的内容,不直接进行创建,应该现从缓存池中读取,如果缓存池中没有则进行创建。
- 所以根据上面的思想,要进行无限循环的话,只需要两个页面就可以了,内容尺寸为3个页面的宽度,并且中间位置始终指示当前图片。 怎么说呢,无论进行左移还是右移,如果出现要出现新的图片,则把缓存池中的页面取出来放在要移的方向上,如果图片全部移至到新的页面的话,则就页面放入缓存池,并且把新页面和移动的位置到再次放置到中心。
-
对于新控件UICollectionView的学习
- 必须要先进行布局的设置。
- 在布局设置中可以进行,其cell(它和tableView和相似)的尺寸,边距,以及组距等设置。还可以对其滚动方向进行设
- 为了方便管理,再次创建自定义控制器进行管理
- 代码实现
对与初始化,因为要设置布局,那么就将布局设置在其初始化方法的内部,并且调用
- init
方法时,同时调用- initWithCollectionViewLayout:
方法,来设置布局
- (instancetype)init
{
// 创建一个流水布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
// 设置cell的尺寸
layout.itemSize = [UIScreen mainScreen].bounds.size;
// 设置滚动的方向
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 行间距
layout.minimumLineSpacing = 0;
// 设置cell之间的间距
layout.minimumInteritemSpacing = 0;
//
// // 组间距
// layout.sectionInset = UIEdgeInsetsMake(100, 20, 0, 30);
return [super initWithCollectionViewLayout:layout];
}
- 和tableView相似的是:collection的cell也需要注册,但是只能注册,因为它创建的时候
没有方法绑定标识
。所以需要注册才能完成重用。注册在- viewDidLoad
方法中实现
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化
[self setUp];
// 在UICollectionViewController中self.view != self.collectionView
// [self.view registerClass:[XMGNewFeatureCell class] forCellWithReuseIdentifier:ID];
// 注册cell
[self.collectionView registerClass:[XMGNewFeatureCell class] forCellWithReuseIdentifier:ID];
// 搭建布局
[self setUpChildViewLayout];
}
- 对于初始化其特性的设置(建议另起方法为之,为了封装)(继承于scrollView )
- 是否有弹簧作用
- 是否展示水平或者垂直标识符
- 是否具有分页功能
- 代理等
- 代码如下
- (void)setUp
{
self.collectionView.bounces = NO;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.collectionView.pagingEnabled = YES;
self.collectionView.delegate = self;
}
- 对于其子控件的设置,cell展示的内容等等
- 类似于tableView的做法,自定义cell ,定义模型等等,但是观察实现的功能,发现cell中只需要有一个图片即可。所以模型属性就是一张图片。
- 自定义cell,用来接受图片,并将图片添加到它的contentView种。
- cell内部不能直接添加view,只能通过contentView添加 ,提供接口用来接受图片
- 有图片来才进行赋值,所以用懒加载。
- 代码如下
- (void)setImage:(UIImage *)image
{
_image = image;
self.imageView.image = image;
}
- (UIImageView *)imageView
{
if (_imageView == nil) {
UIImageView *imageV = [[UIImageView alloc] initWithFrame:self.bounds];
[self.contentView addSubview:imageV];
_imageView = imageV;
}
return _imageView;
}
- 所以对于其数据源方法实现如下
// Items对应cell
// Items在某种程度上就是模型
// 返回有多少个cell
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 20;
}
// 返回每一个cell长什么样
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 从缓存池里取
// UICollectionViewCell 没有UIImageView
LXLCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
// 取出每行的item,对应的背景名
NSString *imageName = [NSString stringWithFormat:@"guide%ldBackground",indexPath.item + 1];
// cell赋值
cell.image = [UIImage imageNamed:imageName];
return cell;
}
- 根据实现的效果图,来思考
- 出现的动画视图,并非是加载到cell上,如果加载到cell上则不会跳来跳去。
- 认为其加载的地方应该是在
collectionView
的最顶层
// 添加子控件
- (void)setUpChildViewLayout
{
// guide
UIImageView *guide = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"guide1"]];
_guide = guide;
guide.x += 50;
[self.collectionView addSubview:guide];
// largerText
UIImageView *largerText = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"guideLargeText1"]];
largerText.center = CGPointMake(self.view.width * 0.5, self.view.height * 0.7);
[self.collectionView addSubview:largerText];
// smallText
UIImageView *smallText = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"guideSmallText1"]];
smallText.center = CGPointMake(self.view.width * 0.5, self.view.height * 0.8);
[self.collectionView addSubview:smallText];
// guideLine
UIImageView *guideLine = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"guideLine"]];
guideLine.x -= 150;
[self.collectionView addSubview:guideLine];
}
- 我们的实现效果中,有一个是滑动结束后,从滑动的反方向推出视图的效果。
- 思考
- 什么时候推出
- 滑动结束后推出(说明需要调用滑动代理方法减速完成)
- 怎么才能从滑动反方向推出。
- 可以先将图片移到位置上,然后再推出来。所以滑动是有距离的(当前偏移量和上一次偏移量的差值),滑动了一个页面,图片若偏移两个界面,然后再推回一个界面就应该能够完成这么一个效果了。
- 需要展示哪张图片呢
- 对于图片的选择,可以根据滑动偏移量,偏移一个界面,就展示第一个界面的,偏移两个界面,就展示第二个界面的。
- 如何得到上一次的偏移量
- 这一次的偏移量 ,就是下一次的上一次的偏移量。
// 减速完成的时候调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
// 移动子控件的位置,并且做动画
NSLog(@"%f",scrollView.contentOffset.x);
// 获取scrollView滚动的X
CGFloat offsetX = scrollView.contentOffset.x;
// 计算偏移量的差值
CGFloat delta = offsetX - _lastOffsetX;
// 平移子控件
_guide.x += 2 * delta;
[UIView animateWithDuration:0.25 animations:^{
_guide.x -= delta;
}];
// 计算页数
int page = offsetX / scrollView.width + 1;
// 切换子控件的显示
NSString *imageName = [NSString stringWithFormat:@"guide%d",page];
_guide.image = [UIImage imageNamed:imageName];
_lastOffsetX = offsetX;
}