献给初学iOS的小盆友们——微博app项目开发之五新特性界面

上几节课我们完成了更改系统tabBar 到完全自定义tabBar的转变,也完美的解决了导航条的功能和内容。本节课程,将会讲解新特性界面的搭建。顾名思义,新特性界面就是在用户第一次下载使用或者更新程序后,给用户展示并介绍应用程序的新功能的界面。程序需要判断用户是否是第一次使用本程序,如果是就展示新特性界面,如果不是,就直接展示程序界面。

本节主要内容

  • 新特性界面的搭建
  • 构建业务逻辑

本节资料下载

第五节代码下载

5.1 创建并展示新特性界面

通过观察新特性界面,我们推测出UICollectionViewController就可以完成其功能。而且在新特性最后一页会需要其他控件,所以我们要自定义一个UICollectionViewCell供UICollectionViewController使用。
使用UICollectionViewController有几点注意事项,一个是,其CollectionView上的Cell尺寸需要一个布局对象决定,所以我们要在初始化函数中创建一个布局参数。第二点,要给CollectionView注册一个cell,这点不能忘记。
然后思考自定义cell怎么设置,首先我们需要给自定义cell设置图片,还要重写其布局方法。为了不让外部更改cell内的imageView,我们在cell接口文件中仅仅暴露一个UIImage属性,根据image再设置执行文件中的UIImageView。
YGNewFeatureCell代码如下:

@interface YGNewFeatureCell ()

@property (nonatomic, weak) UIImageView *imageView;

@end

@implementation YGNewFeatureCell

- (UIImageView *)imageView
{
    if (_imageView == nil) {

        UIImageView *imageV = [[UIImageView alloc] init];

        _imageView = imageV;

        // 注意:一定要加载contentView
        [self.contentView addSubview:imageV];
    }
    return _imageView;
}

// 布局子控件的frame
- (void)layoutSubviews
{
    [super layoutSubviews];

    self.imageView.frame = self.bounds;
}

- (void)setImage:(UIImage *)image
{
    _image = image;

    self.imageView.image = image;
}

@end

代码说明:首先cell的imageView懒加载的时候一定要加到cell的content View里。在image的set方法里,把image传值给imageView,并在布局函数中,设置其frame。

然后上UICollectionViewController执行代码:

static NSString * const reuseIdentifier = @"Cell";

- (instancetype)init
{

    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

    // 设置cell的尺寸
    layout.itemSize = [UIScreen mainScreen].bounds.size;

    // 清空行距
    layout.minimumLineSpacing = 0;

    // 设置滚动的方向
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    return [super initWithCollectionViewLayout:layout];

}


- (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = NO;

    // Register cell classes
    [self.collectionView registerClass:[YGNewFeatureCell class] forCellWithReuseIdentifier:reuseIdentifier];

    // Do any additional setup after loading the view.
    // 分页
    self.collectionView.pagingEnabled = YES;
    self.collectionView.bounces = NO;
    self.collectionView.showsHorizontalScrollIndicator = NO;

}
#pragma mark <UICollectionViewDataSource>
// 返回有多少组

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}
// 返回第section组有多少个cell
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 4;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    YGNewFeatureCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
    NSString *imageName = [NSString stringWithFormat:@"new_feature_%ld",indexPath.row + 1];
    NSLog(@"%@",imageName);
    cell.image = [UIImage imageNamed:imageName];
    return cell;
}

在初始化函数中,创建并设置controller的布局参数。在viewDidLoad中注册一个自定义cell,然后就是按部就班把collectionViewController的dataSource函数写完整。这里说明下dequeue的执行过程,首先是先从缓存池中取cell,如果缓存池里没有,就判断当前是否注册了cell,如果有就自己创建一个cell,没有注册,就会报错。

这里如果我们想验证新特性界面是否能正常显示,可以修改AppDelegate函数,把窗口的根控制器暂时替换为新特性界面,代码如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSLog(@"%s",__func__);

    // 创建窗口

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

    //判断当前是否有新的版本,如果有新特性,进入新特性界面
    YGNewFeatureController *newFeature = [[YGNewFeatureController alloc]init];

    //创建自定义tabbarcontroller

    //YGTabBarController *tabBarVc = [[YGTabBarController alloc]init];

    // 设置窗口的根控制器

    self.window.rootViewController = newFeature;

    // 显示窗口

    [self.window makeKeyAndVisible];
    return YES;
}

5.2 新特性界面的优化

这个小节需要完成两个任务,一是用红色的亮点去表示现在在第几个界面。二是在新特性界面最后一个页面内添加其他控件,包括一个分享按钮和一个直接开始微博按钮。
先从设置UIPageControl 开始,首先要添加一个UIPageControl的属性。

@property (nonatomic, weak) UIPageControl *control;

然后在viewDidLoad代码内添加[self setUpPageControl]; ,把其单独抽取出来,代码如下:

// 添加pageController
- (void)setUpPageControl
{
    // 添加pageController,只需要设置位置,不需要管理尺寸
    UIPageControl *control = [[UIPageControl alloc] init];

    control.numberOfPages = 4;
    control.pageIndicatorTintColor = [UIColor blackColor];
    control.currentPageIndicatorTintColor = [UIColor redColor];

    // 设置center
    control.center = CGPointMake(self.view.width * 0.5, self.view.height);
    _control = control;
    [self.view addSubview:control];
}

每当我们滑动图片的时候,其indicator都会改变,这就需要使用UIScrollView的代理方法:

#pragma mark - UIScrollView代理
// 只要一滚动就会调用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // 获取当前的偏移量,计算当前第几页
    int page = scrollView.contentOffset.x / scrollView.bounds.size.width + 0.5;

    // 设置页数
    _control.currentPage = page;
}

现在运行项目,则会显示我们很完美的解决了PageControl的问题。
下面就讲解如何在最后一个界面内添加合适的按钮。
首先添加两个按钮属性:

@property (nonatomic, weak) UIButton *shareButton;

@property (nonatomic, weak) UIButton *startButton;

然后重写各自懒加载方法:

- (UIButton *)shareButton
{
    if (_shareButton == nil) {

        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        [btn setTitle:@"分享给大家" forState:UIControlStateNormal];
        [btn setImage:[UIImage imageNamed:@"new_feature_share_false"] forState:UIControlStateNormal];
        [btn setImage:[UIImage imageNamed:@"new_feature_share_true"] forState:UIControlStateSelected];
        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [btn sizeToFit];

        [self.contentView addSubview:btn];

        _shareButton = btn;

    }
    return _shareButton;
}

- (UIButton *)startButton
{
    if (_startButton == nil) {
        UIButton *startBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [startBtn setTitle:@"开始微博" forState:UIControlStateNormal];
        [startBtn setBackgroundImage:[UIImage imageNamed:@"new_feature_finish_button"] forState:UIControlStateNormal];
        [startBtn setBackgroundImage:[UIImage imageNamed:@"new_feature_finish_button_highlighted"] forState:UIControlStateHighlighted];
        [startBtn sizeToFit];
        [startBtn addTarget:self action:@selector(start) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:startBtn];
        _startButton = startBtn;

    }
    return _startButton;
}

这里我们只添加了点击打开微博按钮后的方法,没有设置分享按钮的功能,@selector(start) 的代码如下:

// 点击开始微博的时候调用
- (void)start
{
    // 进入tabBarVc
    YGTabBarController *tabBarVc = [[YGTabBarController alloc] init];

    // 切换根控制器:可以直接把之前的根控制器清空
    YGKeyWindow.rootViewController = tabBarVc;  
}

然后我们为这两个按钮设置位置和大小,在layOutSubviews里添加如下代码:

 // 分享按钮
    self.shareButton.center = CGPointMake(self.width * 0.5, self.height * 0.8);
    // 开始按钮
    self.startButton.center = CGPointMake(self.width * 0.5, self.height * 0.9);

最后我们要给cell增加一个方法,用来判断是否到最后一页,如果到最后一页就显示按钮,不是的话就隐藏按钮,自定义cell增加的方法为:

// 判断当前cell是否是最后一页
- (void)setIndexPath:(NSIndexPath *)indexPath count:(int)count
{
    if (indexPath.row == count - 1) { // 最后一页,显示分享和开始按钮
        self.shareButton.hidden = NO;
        self.startButton.hidden = NO;   
    }else{ // 非最后一页,隐藏分享和开始按钮
        self.shareButton.hidden = YES;
        self.startButton.hidden = YES;
    }
}

别忘了在controller文件的代理方法内添加[cell setIndexPath:indexPath count:4];用来每次检查是否是最后一页。

5.3 业务逻辑的处理

可以知道,新特性界面只需要展示一次即可。当用户更新版本之后就展示,没有更新就不展示。稍微思考下就知道,这个业务逻辑需要在AppDelegate去完成。业务逻辑可以分为以下几个步骤,首先要获取当前版本号,然后要用用户偏好设置去获取上一个版本号。用户偏好设置有两个优点,一个是不需要关心文件名,另一个是可以快速进行键值对存储。最后判断当前版本号和上一个存储的版本号是否相同。代码如下:

 //1.获取当前版本号
     NSString *currentVerison = [NSBundle mainBundle].infoDictionary[@"CFBundleVersion"];
    //2.获取上一次版本号
    NSString *lastVersion = [[NSUserDefaults standardUserDefaults] objectForKey:YGVersionKey];
    //3.判断当前是否有新的版本,如果有新特性,进入新特性界面
    if ([currentVerison isEqualToString:lastVersion]) {//没有最新版本号

        //创建自定义tabbarcontroller

        YGTabBarController *tabBarVc = [[YGTabBarController alloc]init];
        // 设置窗口的根控制器

        self.window.rootViewController = tabBarVc;

    }else{//有最新版本号,进入新特性界面
        YGNewFeatureController *newFeature = [[YGNewFeatureController alloc]init];
        //保存当前版本
        [[NSUserDefaults standardUserDefaults] setObject:currentVerison forKey:YGVersionKey];
        // 设置窗口的根控制器

        self.window.rootViewController = newFeature;
    }

第一次运行程序的时候会显示新特性界面,再次按command+r运行程序就会直接显示微博界面。如果你想验证代码是否正确,可以打开info.plist文件,在BundleVersion里增加版本号如下图,
这里写图片描述
再次运行就会发现又进入新特性界面了。

至此我们就完成了新特性界面的搭建以及业务逻辑的实现,下节课我们将会讲解如何使用微博API接口获取微博数据,真正显示微博的时刻快要到来了,很兴奋吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值