iOS知识收集iOS专题资源__UI专题产品手札

网易新闻实战总结

2015-12-02  本文已影响2238人  阿拉斯加的狗
为期两天的网易新闻简单完成,其中还有许多模糊的点,在此发文:

示例demo:(ps:最后做分类模块字体滑动有个阴影bug 有懂得大牛求帮忙解决感谢感谢)

网易新闻.gif

好咯,接下来就开始我的实现之路吧~

####第一步:环境的配置(cocoaPods安装指南)
#安装CocoaPods
### 查看当前的源
sudo gem sources -l

### 添加源
sudo gem sources -a https://ruby.taobao.org/

### 删除源
sudo gem sources -r https://rubygems.org/
### 安装
sudo gem install cocoapods  
pod setup

***
#使用CocoaPods

### 搜索
pod search AFNetworking
### 生成 Podfile
echo "pod 'AFNetworking'" > Podfile
### 安装
pod install
### 升级
pod update
由于本demo为抓包获取网易新闻的JSON 我所采用的是第三方框架<AFN> 异步下载网络图片也是使用它自带的UIImage的分类

监听网易新闻发送的HTTP请求,获取请求数据的地址.根据获取的数据创建图片轮播器使用的模型类HeadLine

#import <Foundation/Foundation.h>

@interface HMHeadLine : NSObject

//定义属性
@property (nonatomic,copy)NSString *title;

@property (nonatomic,copy)NSString *imgsrc;

+ (instancetype)headlineWithDict:(NSDictionary *)dict;

//放松异步请求获取数据
+ (void)headlineWithSucess:(void(^)(NSArray *array))sucess error:(void(^)())error;

@end

异步发送请求获取模型对象
#import "HMHeadLine.h"
#import "HMNetworkTools.h"
@implementation HMHeadLine

+ (instancetype)headlineWithDict:(NSDictionary *)dict{

HMHeadLine *headline = [self new];

[headline setValuesForKeysWithDictionary:dict];

return headline;

}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{

}

//获取数据
+ (void)headlineWithSucess:(void (^)(NSArray *))sucess error:(void (^)())error{



[[HMNetworkTools sharedNetworkTools] GET:@"ad/headline/0-4.html" parameters:nil success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) {
    
    //字典转模型获取数据
    //获取第一个KEY
    NSString *rootKey = responseObject.keyEnumerator.nextObject;
    NSArray *array = responseObject[rootKey];
    
    NSMutableArray *marray = [NSMutableArray arrayWithCapacity:4];
    
    //循环遍历获取模型
    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        HMHeadLine *model = [HMHeadLine headlineWithDict:obj];
        
        [marray addObject:model];
        
    }];
    
    if (sucess) {
        
        sucess(marray.copy);
    }
    
    
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    
    if (error) {
        
    }
    
}];

}

@end

自定义cell

#import "HMHeadlineCell.h"
#import "HMHeadLine.h"
#import <UIImageView+AFNetworking.h>
@interface HMHeadlineCell ()

@property (weak, nonatomic) IBOutlet UIImageView *imgsrcView;

@property (weak, nonatomic) IBOutlet UILabel *titleView;

@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@end

@implementation HMHeadlineCell

//从写headline的方法
- (void)setHeadline:(HMHeadLine *)headline{

_headline = headline;

//解决重用问题
self.imgsrcView.image = nil;
self.titleView.text = nil;

//设置图片
[self.imgsrcView setImageWithURL:[NSURL URLWithString:headline.imgsrc]];

//设置标题
self.titleView.text = headline.title;

self.pageControl.currentPage = self.tag;

}

@end

自定义CollectionViewControllView控制器实现数据源方法 加载数据实现图片轮播器的效果

#import "HMImageLoopController.h"
#import "HMHeadLine.h"
#import "HMHeadlineCell.h"
@interface HMImageLoopController ()
@property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *flowLaout;

//当前图片的索引
@property (nonatomic, assign) NSInteger currentIndex;

//声明一个属性
@property (nonatomic,strong)NSArray *array;

@end

@implementation HMImageLoopController

- (void)viewDidLoad {
[super viewDidLoad];

//设置背景颜色
self.collectionView.backgroundColor = [UIColor whiteColor];

[HMHeadLine headlineWithSucess:^(NSArray *array) {
   
    self.array = array;
    
} error:^{
    
    NSLog(@"请求数据失败");
    
}];

[self setCollectionViewStyle];

}

#pragma mark - 刷新数据
    - (void)setArray:(NSArray *)array{

_array = array;

[self.collectionView reloadData];

//永远显示第二个CELL
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:0];

[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:0 animated:NO];
}

- (void)viewDidLayoutSubviews{

[super viewDidLayoutSubviews];

//设置cell的大小
self.flowLaout.itemSize = self.collectionView.frame.size;


}

#pragma mark - 设置collectionView的样式
- (void)setCollectionViewStyle{


//设置滚动方向
self.flowLaout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

self.flowLaout.minimumInteritemSpacing = 0;
self.flowLaout.minimumLineSpacing = 0;

self.collectionView.bounces = NO;
self.collectionView.pagingEnabled = YES;
self.collectionView.showsHorizontalScrollIndicator = NO;

    }

#pragma mark - 数据源方法
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

return self.array.count;
    }

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

//创建cell
HMHeadlineCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"headline" forIndexPath:indexPath];

//在滚动过程中下一张图片的索引
//当滚动的过程中item的值可能是 0 或者 2
NSInteger index = (self.currentIndex + indexPath.item - 1 + self.array.count) % self.array.count;

cell.backgroundColor = [UIColor whiteColor];

cell.headline = self.array[index];

cell.tag = index;

return cell;
}
  //collectionView的代理方法
//滚动停止之后,把cell换成第二个cell
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
//计算下一张图片的索引 (+1  -1)
//返回的值始终是 (0  2) - 1
int offset = scrollView.contentOffset.x / scrollView.bounds.size.width - 1;
self.currentIndex = (self.currentIndex + offset + self.array.count ) % self.array.count;


//始终显示第二个cell
//主队列的执行特点:先等待主线程上的代码都执行完毕,再执行队列中的任务
dispatch_async(dispatch_get_main_queue(), ^{
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:0];
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:0 animated:NO];
});


        }

@end

第三步:实现新闻列表模块-实现数据的显示及刷新数据(图文混排效果,单图,大图,及三张图片显示的效果)

news.png

同理- 创建新闻列表模型对象,发送异步请求获取数据,自定义tabelViewControllerView控制器及自定义cell加载数据

#import <Foundation/Foundation.h>

@interface HMNews : NSObject

//声明属性
@property (nonatomic,copy)NSString *imgsrc;
@property (nonatomic,copy)NSString *digest;
@property (nonatomic,copy)NSNumber *replyCount;
@property (nonatomic,copy)NSString *title;

//声明一个大图属性
@property (nonatomic,assign)BOOL imgType;

//声明三张图的属性
@property (nonatomic, copy) NSArray *imgextra;

//定义方法
+ (instancetype)newsWithDict:(NSDictionary *)dict;

//发送异步请求获取数据
+ (void)newsWithurlString:(NSString *)urlString Sucess:(void(^)(NSArray *array))sucessBlock error:(void(^)())errorBlock;

@end
#import "HMNews.h"
#import "HMNetworkTools.h"
@implementation HMNews

+ (instancetype)newsWithDict:(NSDictionary *)dict{

HMNews *news = [HMNews new];

[news setValuesForKeysWithDictionary:dict];

return news;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{

}

//发送异步请求获取数据
+ (void)newsWithurlString:(NSString *)urlString Sucess:(void(^)(NSArray *array))sucessBlock error:(void(^)())errorBlock{

[[HMNetworkTools sharedNetworkTools] GET:urlString parameters:nil success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) {
    
    //获取KEY
    NSString *rootKey = responseObject.keyEnumerator.nextObject;
    
    //获取数组
    NSArray *array = responseObject[rootKey];
    
    NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10];
    
    //遍历数组获取模型
    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        HMNews *model = [HMNews newsWithDict:obj];
        
        [mArray addObject:model];
        
    }];
    
    if (sucessBlock) {
        
        sucessBlock(mArray.copy);
        
    }
    
    
} failure:^(NSURLSessionDataTask *task, NSError *error) {
   
    if (errorBlock) {
    
        errorBlock();
    }
    
}];

}

@end

在此-我会从写创建一个StrobBord用来设置页面到时候会从这里传回数据

home.png
  #import "HMHomeController.h"
  #import "HMChannel.h"
  #import "HMChannelLabel.h"
  #import "HMHomeCell.h"
  @interface HMHomeController ()      <UICollectionViewDataSource,UICollectionViewDelegate>

  //声明一个数组用来保存数据
  @property (nonatomic,strong)NSArray *channels;
  @property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

  @property (weak, nonatomic) IBOutlet UICollectionView *cooectionView;

  @property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *flowLaout;

  //记录当前lbl的的索引
  @property (nonatomic,assign)int currenIndex;
  @end

  @implementation HMHomeController

  #pragma mark - 懒加载
  - (NSArray *)channels{

      if (_channels == nil) {
    
          _channels = [HMChannel channelWithArray];
      }      

      return _channels;
  }

  - (void)viewDidLoad {
      [super viewDidLoad];

      //创建分类
      [self loadChannels];

      //设置item的大小及collettionView的属性
      [self getCollectionView];

      //加载新闻分类
      [self loadChannels];

  }

  #pragma mark - 设置item的大小及collettionView的属性
  - (void)getCollectionView{


      //设置间距
      self.flowLaout.minimumInteritemSpacing = 0;
      self.flowLaout.minimumLineSpacing = 0;
      self.flowLaout.scrollDirection =       UICollectionViewScrollDirectionHorizontal;

      //设置collectionView一些属性
      self.cooectionView.bounces = NO;
      //分页
      self.cooectionView.pagingEnabled = YES;
      //水平条
      self.cooectionView.showsHorizontalScrollIndicator = NO;

  }

  - (void)viewDidLayoutSubviews{

      [super viewDidLayoutSubviews];
      //设置cell大小
      self.flowLaout.itemSize = self.cooectionView.frame.size;

  }

  #pragma mark - 创建频道中的分类
  - (void)loadChannels{

      //不让控制器自动生成64的偏移
      self.automaticallyAdjustsScrollViewInsets = NO;

      CGFloat marginX = 5;
      CGFloat x = marginX;
      CGFloat y = 0;
      CGFloat h = self.scrollView.bounds.size.height;

      //利用循环获取分类的名称
      for (HMChannel *channel in self.channels) {
    
          //自定义label获取数据
          HMChannelLabel *lbl = [HMChannelLabel channelLabelWithTName:channel.tname];
    
          //添加到scrollView中
          [self.scrollView addSubview:lbl];
    
          //设置frame  宽度就为字体本身的宽度
          lbl.frame = CGRectMake(x, y, lbl.bounds.size.width, h);
    
          x += lbl.bounds.size.width + marginX;
    
      }

      //scrollView滚动的范围
      self.scrollView.contentSize = CGSizeMake(x, h);
      //取消水平滑动条
      self.scrollView.showsHorizontalScrollIndicator = NO;

      HMChannelLabel *lbl = self.scrollView.subviews[0];
      lbl.scale = 1;
  }

  #pragma mark - 寻找滚动时候下一个lbl
  //当collectionView滚动时候计算lbl的顺序
  - (void)scrollViewDidScroll:(UIScrollView *)scrollView{

      //当前lbl
      HMChannelLabel *currentlbl = self.scrollView.subviews[self.currenIndex];

      //下一个lbl
      HMChannelLabel *nextlbl = nil;

      //遍历当前可见cell的索引
for (NSIndexPath *indexPath in self.cooectionView.indexPathsForVisibleItems) {
    
          if (indexPath.item != self.currenIndex) {
        
              //就是下一个lbl
              nextlbl = self.scrollView.subviews[indexPath.item];
              break;
        
          }
    
          if (nextlbl == nil) {
        return;
          }
    
      }

      //获取滚动的比例
      CGFloat nextScale = ABS(scrollView.contentOffset.x / scrollView.bounds.size.width - self.currenIndex);
      CGFloat currentScale = 1- nextScale;

      currentlbl.scale = currentScale;
      nextlbl.scale = nextScale;

      //计算currentlbl的位置
      self.currenIndex = scrollView.contentOffset.x /             scrollView.bounds.size.width;

  }

  #pragma mark - 当滚动结束后计算currentlbl
  - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

      //居中显示当前显示的标签
      HMChannelLabel *label = self.scrollView.subviews[self.currenIndex];
      CGFloat offset = label.center.x - self.scrollView.bounds.size.width * 0.5;
      CGFloat maxOffset = self.scrollView.contentSize.width - label.bounds.size.width - self.scrollView.bounds.size.width;

      if (offset < 0) {
          offset = 0;
      } else if (offset > maxOffset) {
          offset = maxOffset + label.bounds.size.width;
      }

      [self.scrollView setContentOffset:CGPointMake(offset, 0) animated:YES];



  }

  #pragma mark - 数据源方法
  - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

      return self.channels.count;
  }      

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

      //获取数据
      HMChannel *channel = self.channels[indexPath.item];

      //创建cell
      HMHomeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"home" forIndexPath:indexPath];

      cell.urlString = channel.urlString;

      return cell;

  }

  @end

由于第一次在简书上写项目 正如我开头说的那样 不求其他,只想对项目的整个思路再次贯穿一遍,顺便分享分享给各位书友们,学习之路任重道远,在乎是的对自己自身的要求跟习惯,只有在不断的前行之中发现自己的舍与得,希望大家在这条充满创新的道路上找到自己的那条殊途~

本人github地址:https://github.com/aryehToDog

iOS技术成长群:255032637 有愿意的小伙伴可以长期学习共勉!

                                                                        2015.12.02
上一篇 下一篇

猜你喜欢

热点阅读