在这个项目中,学习本地json文件的获取、collectionView和tabvleView的使用、KVO的使用等知识点
可以实现的效果是可以左右滑动也可以上下滑动,当在搜索框中输入文字点击return键时调到搜索界面,也可以点击其中的某一个cell跳到清单界面(未实现);点击下面的tabbar中的按钮可以切换界面。在这里我主要实现的是首页的功能,其他界面的功能将在后续中继续完成。
实现的过程主要是在ViewController上面首先创建一个标题栏的collectionView用来显示标题,下面的主要视图也是用collectionViewController来实现左右滑动.然后在collectionView中添加tableView来实现上下的滑动.
对导航栏中中的搜索框添加代理方法来监听当输入完成点击了return键后直接跳转到搜索界面。
给头部的collectionView和mainCollectionView分别添加KVO来监听滑动的范围,让头部视图和下面的视图一起滑动。
实现后的显示:
实现的主要代码为:
tabbarControl的实现代码:
#import "BaseTabbarController.h"
#import "Common.h"
@interface BaseTabbarController ()
@end
@implementation BaseTabbarController
- (void)viewDidLoad {
[super viewDidLoad];
[self creatTabbar];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self removeTabbar];
}
#pragma mark - 移除自带的tabbar
- (void) removeTabbar {
for (UIView *view in self.tabBar.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
[view removeFromSuperview];
}
}
}
#pragma mark - creat self tabbar
- (void) creatTabbar {
//设置背景图片
UIImageView *tabbarImage= [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kWidth,TabBarHeight)];
tabbarImage.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"tabBarViewBg"]];
// [self.tabBar addSubview:tabbarImage];
// self.tabBar.backgroundColor = [UIColor yellowColor];
self.tabBar.userInteractionEnabled = YES;
//创建数组来存数需要的图片
NSArray *normal = @[@"Home_normal",@"Message_normal",@"Show_normal",@"Square_normal",@"PersonCenter_normal"];
NSArray *selected = @[@"Home_selected",@"Message_selected",@"Show_normal",@"Square_selected",@"PersonCenter_normal"];
//利用for循环来创建item
for (int i = 0; i < normal.count; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(i*kWidth/normal.count, 0, kWidth/normal.count, TabBarHeight);
//获取item的名字
// NSString *normal = [NSString stringWithFormat:@"%@",imageArraynormal[i]];
[button setImage:[UIImage imageNamed:normal[i]] forState:UIControlStateNormal];
//获取选中状态
// NSString *selected = [ normal stringByReplacingOccurrencesOfString:@"normal" withString:@"selected"];
[button setImage:[UIImage imageNamed:selected[i]] forState:UIControlStateSelected];
button.tag = 1000 + i;
[button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.tabBar addSubview:button];
//设置默认选中状态
if (button.tag == 1000) {
button.selected = YES;
}
}
}
#pragma mark - button Action
- (void) buttonAction :(UIButton *) button {
NSInteger index = button.tag - 1000;
//切换视图控制器
self.selectedIndex = index;
//修改按钮的选中状态
for (int i = 0; i < self.viewControllers.count; i++) {
UIButton *btn = (UIButton *)[self.tabBar viewWithTag:1000+ i];
btn.selected = NO;
}
button.selected = !button.selected;
}
@end
//封装的获取本地json文件的方法(独立建立一个类来封装)
//创建类方法来获取json数据
+ (id) dataService:(NSString *)resource {
//获取路径
NSString *path = [[NSBundle mainBundle] pathForResource:resource ofType:@"json"];
//封装成data数据
NSData *nsdata = [[NSData alloc] initWithContentsOfFile:path];
//返回id类型的数据
id data = [NSJSONSerialization JSONObjectWithData:nsdata options:NSJSONReadingMutableContainers error:nil];
return data;
}
模型类的基类 (主要功能是将获取到的json数据和模型类连接)
//主要代码的实现
- (NSMutableDictionary *) buildRelationShip:(NSDictionary *) dic {
//取出字典中的所有键
NSArray *keys = [dic allKeys];
//创建一个可变的字典来存储所有的键值对
NSMutableDictionary *munDic = [NSMutableDictionary dictionary];
for (NSString *str in keys) {
if ([str isEqualToString:@"id"]) {
NSString *className = NSStringFromClass([self class]);
NSString *newID = [NSString stringWithFormat:@"%@Id",className];
[munDic setObject:newID forKey:@"id"];
}else {
[munDic setObject:str forKey:str];
}
}
return munDic;
}
//转化为方法
- (SEL) findSettermethod :(NSString *) name {
//1、截取字符串的首字母
NSString *firstLetter = [[name substringToIndex:1] uppercaseString];
//2、截取剩下的字母
NSString *lastLetter = [name substringFromIndex:1];
//3、拼接字符串
NSString *setterName = [NSString stringWithFormat:@"set%@%@",firstLetter,lastLetter];
//4、从一个字符串产生方法
SEL setter = NSSelectorFromString(setterName);
//返回
return setter;
}
- (void) setValueAttributeWithDictionary:(NSDictionary *)keyValue{
//1、获取字典映射
NSMutableDictionary *relationDic = [self buildRelationShip:keyValue];
//2、找到set方法
NSArray *allkeys = [relationDic allKeys];
for (NSString *key in allkeys) {
NSString *property = [relationDic objectForKey:key];
SEL method = [self findSettermethod:property];
//赋值
id value = [keyValue objectForKey:key];
//判断
if ([self respondsToSelector:method]) {
[self performSelector:method withObject:value];
}
}
}
模型类的创建:
#import "BaseModel.h"
@interface HomeModel : BaseModel
//创建属性
@property (nonatomic,copy) NSString *id;
@property (nonatomic,copy) NSString *title;
@property (nonatomic,copy) NSString *pic;
@property (nonatomic,copy) NSString *tags;
@property (nonatomic,assign) BOOL islike;
@property (nonatomic,copy) NSString *type;
@end
主界面的创建:
#import "HomeViewController.h"
#import "Common.h"
#import "SearchViewController.h"
#import "TitleCollectionView.h"
#import "MainCollectionView.h"
@interface HomeViewController ()<UITextFieldDelegate> {
//创建一个头视图的集合视图
TitleCollectionView *titleCollection;
//创建一个主视图
MainCollectionView *mainCollection;
}
@property (nonatomic,strong) NSArray *titleArray;
@property (nonatomic,strong) NSMutableArray *jsonArray;
@end
@implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置导航栏的样式
[self.navigationController hidesBarsWhenVerticallyCompact];
//设置背景颜色
self.view.backgroundColor = [UIColor colorWithRed:240.0/255 green:230.0/255 blue:1 alpha:1];
_titleArray = @[@"最新",@"文艺",@"礼物",@"指南",@"爱美",@"设计",@"吃货",@"厨房",@"上班",@"学生",@"聚会",@"节日",@"宿舍"];
[self loadData];
[self creatNavigation];
[self creatHeaderView];
[self creatSubView];
//添加观察者
[titleCollection addObserver:self forKeyPath:@"currentIndex" options:NSKeyValueObservingOptionNew context:nil];
[mainCollection addObserver:self forKeyPath:@"currentIndex" options:NSKeyValueObservingOptionNew context:nil];
}
- (void) loadData {
NSArray *array = @[@"app_JSON",@"json_Art",@"json_Gift",@"json_Guide",@"json_LoveBeauty",@"json_Design",@"json_Eater",@"json_Kitchen",@"json_WageEarners",@"json_Student",@"json_Party",@"json_Holiday",@"json_Dormitory"];
//初始化数据
_jsonArray = [NSMutableArray array];
//解析数据
for (int i = 0; i < array.count; i++) {
NSDictionary *dic = [DataService dataService:array[i]];
[_jsonArray addObject:dic];
}
}
- (void) creatNavigation {
//创建一个视图
UIView *searchView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
//创建一个button
UIButton *search = [UIButton buttonWithType:UIButtonTypeCustom];
search.frame = CGRectMake(0, 0, 30, 30);
[search setImage:[UIImage imageNamed:@"searchBtn"] forState:UIControlStateNormal];
[searchView addSubview:search];
//创建一个文本框
UITextField *searchText = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
//设置文本框的颜色
searchText.backgroundColor = [UIColor whiteColor];
searchText.alpha = 0.4;
//添加时间
searchText.delegate = self;
//[searchText addTarget:self action:@selector(textAction:) forControlEvents:UIControlEventAllTouchEvents];
//设置边框
searchText.layer.cornerRadius = 8;
[searchView addSubview:searchText];
//添加视图
self.navigationItem.titleView = searchView;
//创建右侧的item
UIButton *right= [UIButton buttonWithType:UIButtonTypeCustom];
right.frame = CGRectMake(0, 0, 30, 30);
[right setImage:[UIImage imageNamed:@"calendar-round"] forState:UIControlStateNormal];
//创建一个baritem
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithCustomView:right];
self.navigationItem.rightBarButtonItem = rightItem;
}
#pragma mark - 创建头视图
- (void) creatHeaderView {
UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, kWidth, 60)];
titleView.backgroundColor = [UIColor whiteColor];
titleView.userInteractionEnabled = YES;
[self.view addSubview:titleView];
//创建一个标题的集合视图
UICollectionViewFlowLayout *flowlayout = [[UICollectionViewFlowLayout alloc] init];
flowlayout.itemSize = CGSizeMake(50, 50);
flowlayout.minimumLineSpacing = 20;
flowlayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
titleCollection = [[TitleCollectionView alloc] initWithFrame:CGRectMake(0, 0, kWidth, 60) collectionViewLayout:flowlayout];
titleCollection.showsVerticalScrollIndicator = NO;
//titleCollection.pagingEnabled = YES;
titleCollection.array = _titleArray;
[titleView addSubview:titleCollection];
}
//创建下面的视图
- (void) creatSubView {
//开启用户交互界面
mainView.userInteractionEnabled = YES;
//创建一个集合视图
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.itemSize = CGSizeMake(kWidth, kHeight - 120 - 49 );
flowLayout.minimumLineSpacing = 0;
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
mainCollection = [[MainCollectionView alloc] initWithFrame:CGRectMake(0, 0, kWidth, mainView.height) collectionViewLayout:flowLayout];
//设置分页效果
mainCollection.pagingEnabled = YES;
//传递值
mainCollection.dataArray = _jsonArray;
//设置滑动条的隐藏
mainCollection.showsVerticalScrollIndicator = NO;
mainCollection.showsVerticalScrollIndicator = NO;
//开启用户交互
mainCollection.userInteractionEnabled = YES;
//添加到界面
[mainView addSubview:mainCollection];
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
NSInteger index = [[change objectForKey:@"new"] integerValue];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
if ([object isKindOfClass:[titleCollection class]] && mainCollection.currentIndex != index ) {
[mainCollection scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
} else if([object isKindOfClass:[mainCollection class]] && titleCollection.currentIndex != index){
[titleCollection scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(@"text = %@",textField.text);
SearchViewController *searchVC = [[SearchViewController alloc] init];
[self.navigationController pushViewController:searchVC animated:YES];
return YES;
}
//移除观察者
- (void) dealloc {
[titleCollection removeObserver:self forKeyPath:@"currentIndex"];
[mainCollection removeObserver:self forKeyPath:@"currentIndex"];
}
标题栏的collectionView
//.h文件
#import <UIKit/UIKit.h>
@interface TitleCollectionView : UICollectionView <UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
@property (nonatomic,strong) NSArray *array;
@property (nonatomic,assign) NSInteger currentIndex;
@end
//.m文件
#import "TitleCollectionView.h"
#import "Common.h"
#import "TitleCell.h"
@implementation TitleCollectionView
- (instancetype) initWithFrame:(CGRect)frame collectionViewLayout:(nonnull UICollectionViewLayout *)layout {
self = [super initWithFrame:frame collectionViewLayout:layout];
if (self) {
self.backgroundColor = [UIColor yellowColor];
self.dataSource = self;
self.delegate = self;
//注册
[self registerClass:[TitleCell class] forCellWithReuseIdentifier:@"title"];
}
return self;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _array.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TitleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"title" forIndexPath:indexPath];
cell.title = _array[indexPath.row];
//cell.backgroundColor = [UIColor redColor];
return cell;
}
- (void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
self.currentIndex = indexPath.row;
}
//设置偏移量
- (UIEdgeInsets) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, kWidth - 20);
}
- (void) scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
//获取偏移值
CGFloat offsetX = targetContentOffset->x;
// NSLog(@"偏移量:%f",offsetX);
//设置每一个cell的大小
CGFloat itemSize = 70;
//计算偏移的页数
NSInteger pageNum = (offsetX + itemSize/2)/itemSize;
// NSLog(@"page = %@",_array[pageNum]);
//根据显示的第几个item来改变偏移量
targetContentOffset->x = pageNum * itemSize;
self.currentIndex = pageNum;
}
@end
主界面的collectionView
//.h文件
#import <UIKit/UIKit.h>
@interface MainCollectionView : UICollectionView <UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
@property (nonatomic,strong) NSArray *dataArray;
//获取当前值
@property (nonatomic,assign) NSInteger currentIndex;
@end
//.m文件
#import "MainCollectionView.h"
#import "MainCell.h"
#import "Common.h"
@implementation MainCollectionView
- (instancetype) initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout {
self = [super initWithFrame:frame collectionViewLayout:layout];
if (self) {
self.backgroundColor = [UIColor redColor];
[self reloadData];
//设置数据源
self.dataSource = self;
self.delegate = self;
//注册
[self registerClass:[MainCell class] forCellWithReuseIdentifier:@"mainCell"];
}
return self;
}
- (void)setDataArray:(NSArray *)dataArray {
_dataArray = dataArray;
}
#pragma mark - collectionDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _dataArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MainCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"mainCell" forIndexPath:indexPath];
NSDictionary *dic = _dataArray[indexPath.row];
// NSLog(@"%@",_dataArray[indexPath.row][@"data"]);
cell.dic = dic;
return cell;
}
//根据滑动的范围来获取滑动的页数
- (void) scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
//1、根据偏移量来获取是第几个item
CGFloat offsetX = targetContentOffset->x;
//2、item的宽度
CGFloat itemSize = 414;
//3、计算是第几页
NSInteger pagNum = (offsetX + itemSize/2)/itemSize;
//NSLog(@"第%ld页",pagNum);
//传递值
self.currentIndex = pagNum;
//改变偏移量
targetContentOffset->x = pagNum * itemSize;
}
@end
mainCollectionView的Cell
//.h文件
#import <UIKit/UIKit.h>
#import "TableView.h"
@interface MainCell : UICollectionViewCell {
//创建一个视图
UIView *view;
//创建头部视图
TableView *tableView;
}
@property (nonatomic,weak) NSDictionary *dic;
@end
//.m文件
#import "MainCell.h"
#import "TableView.h"
#import "Common.h"
@implementation MainCell
- (instancetype) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.width, self.height)];
view.backgroundColor = [UIColor purpleColor];
//创建表视图
[self creatTableView];
[self.contentView addSubview:view];
}
return self;
}
- (void) setDic:(NSDictionary *)dic {
//NSLog(@"%@",dic[@"data"]);
_dic = dic;
tableView.data = _dic[@"data"];
[tableView reloadData];
}
#pragma mark - creat tableView
- (void) creatTableView {
tableView = [[TableView alloc] initWithFrame:CGRectMake(0, 0, view.width,view.height)];
//[tableView reloadData];
tableView.rowHeight = 300;
[view addSubview:tableView];
}
@end
mainCollectionView中的cell上面的tableView
//.h文件
#import <UIKit/UIKit.h>
@interface TableView : UITableView <UITableViewDataSource,UITableViewDelegate> {
//创建一个数组来存储显示的数据
NSArray *dataArray;
}
@property (nonatomic,weak) NSDictionary *data;
@end
//.m文件
#import "TableView.h"
#import "TableCell.h"
#import "HomeModel.h"
#import "ListViewController.h"
#import "Common.h"
@implementation TableView
- (instancetype) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
//设置数据源
self.dataSource = self;
self.delegate = self;
[self reloadData];
//注册
[self registerNib:[UINib nibWithNibName:@"TableCell" bundle:nil] forCellReuseIdentifier:@"tablecell"];
}
return self;
}
- (void) setData:(NSDictionary *)data {
_data = data;
dataArray = _data[@"topic"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tablecell"];
cell.dic = dataArray[indexPath.row];
// NSLog(@"%@",dataArray[indexPath.row]);
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController *view = [[UIViewController alloc] init];
view.view = self;
ListViewController *listVC = [[ListViewController alloc] init];
[view presentViewController:listVC animated:YES completion:nil];
//UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:view];
}
@end
tableCell的创建
//.h文件
#import <UIKit/UIKit.h>
@interface TableCell : UITableViewCell {
__weak IBOutlet UIImageView *picImage;
__weak IBOutlet UILabel *title;
__weak IBOutlet UILabel *selfTitle;
__weak IBOutlet UILabel *likes;
__weak IBOutlet UIButton *likeButton;
__weak IBOutlet UIButton *typebutton;
__weak IBOutlet UILabel *type;
}
//创建一个传值的字典
@property (nonatomic,weak) NSDictionary *dic;
@end
//.m文件
#import "TableCell.h"
#import "Common.h"
@implementation TableCell
- (void) setDic:(NSDictionary *)dic {
_dic = dic;
// NSLog(@"%@",dic);
//设置图片
NSURL *url = [NSURL URLWithString:dic[@"pic"]];
[picImage sd_setImageWithURL:url];
//标题
title.text = dic[@"title"];
selfTitle.text = @"小糖君";
//喜欢人数
likes.text = dic[@"likes"];
//类型
type.text = dic[@"type"];
}
@end
tableCell的xib文件如图:
搜索界面的实现
SearchViewController的代码
#import "SearchViewController.h"
#import "ListCell.h"
@interface SearchViewController () <UITableViewDelegate,UITableViewDataSource>
@property (nonatomic,strong) NSArray *dataArray;
@end
@implementation SearchViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self loadData];
[self creatTableView];
}
- (void)loadData {
NSString *path = [[NSBundle mainBundle]pathForResource:@"搜索列表" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
//转化为字典
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
//获取data
_dataArray = dic[@"data"];
}
- (void) creatTableView {
UITableView *tbView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30) style:UITableViewStylePlain];
//添加代理
tbView.dataSource = self;
tbView.delegate = self;
//设置背景颜色
tbView.backgroundColor = [UIColor whiteColor];
//设置行高
tbView.rowHeight = 70;
//添加
[self.view addSubview:tbView];
//注册一个listCell
[tbView registerNib:[UINib nibWithNibName:@"ListCell" bundle:nil] forCellReuseIdentifier:@"ListCell"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ListCell"];
cell.dic = _dataArray[indexPath.row];
return cell;
}
@end
cell的实现
//.h文件
#import <UIKit/UIKit.h>
@interface ListCell : UITableViewCell {
__weak IBOutlet UIImageView *iconImage;
__weak IBOutlet UILabel *titleLable;
}
@property (nonatomic,strong) NSDictionary *dic;
@end
//.m文件
#import "ListCell.h"
@implementation ListCell
- (void) setDic:(NSDictionary *)dic {
_dic = dic;
titleLable.text = dic[@"name"];
//获取url
NSURL *url = [NSURL URLWithString:dic[@"icon"]];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
dispatch_async(dispatch_get_main_queue(), ^{
iconImage.image = image;
});
});
}
@end