UICollectionViewController与引导页

  • 在项目的作用:引导页的使用
  • 怎么来插入引导页
    • 当第一次进入程序时,为了给用户一个良好的体验,所以需要进行介绍,让用户更好的了解程序的功能。
    • 如果是用户第二次后者说是以后再次点开程序时,则不需要再进行介绍,直接跳转到主程序即可。
    • 还有,当程序版本进行更新的时候,启动程序的时候,再次进入引导页,当然此时的引导页应该显示新的内容。
    • 所以,进行构想。 记录版本号,当前版本号与旧版本号进行比较,如果相同则直接进入程序,如果不一样则进入引导页。
    • 代码实现如下
- (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个页面的宽度,并且中间位置始终指示当前图片。 怎么说呢,无论进行左移还是右移,如果出现要出现新的图片,则把缓存池中的页面取出来放在要移的方向上,如果图片全部移至到新的页面的话,则就页面放入缓存池,并且把新页面和移动的位置到再次放置到中心。

Snip20150726_19.png

Snip20150726_21.png

Snip20150726_22.png
  • 对于新控件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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值