团购01 基本数据
效果展示:
Snip20160322_2.png01 展示基本数据
题外话: 我们上面有一个播放广告的地方是利用我们的
tableView
的一个head...控件实现的, 后面也有一个foot....
其实自定义cell
有两种方法:
- 通过
Xib
创建 - 通过代码创建
决定是用这两种的方法的其中一种的根据我们的所写的程序决定的
如果是像上面的这种(所有的cell
都比较类似, 我们就用Xib
, 如果每一个cell
不一样, 我们就用代码来创建)
**开始编写: **
1. 界面设计:
storyboard
就是一个简单的tableView直接拖进去就行了
Xib文件
: 我们在创建Xib
之后, 注意的是这里面不是我们以前说的将一个UIView
拖进去, 而是选择UITableViewCell
然后, 设置它里面的控件: 具体的格式是:
2. 代码的编写:
上一个程序中, 我们介绍过有关于cell
的缓存池, 当然也是需要标识的. 观察一下我们在加载我们的Xib
的时候, 貌似没有告诉我们的系统, 我们加载的这个自定义cell
没有标识: (这个里面同样也牵扯到封装的原理: 我们将创建cell
的方式给封装了起来, 后面我将介绍到)
所以我们要在Xib
的这个位置设置标识:
剩下的都是我们在应用管理中的Xib
的一些步骤:
创建新的类, 用来封装我们的cell
相关代码
这里面也包括了一些新的代码, 在最后, 我会将所有的代码全部写在这个上面的
团购 02 添加加载更多功能
2. 1 我们利用TableView
的footerView
来完成我们后面的加载数据
**第一种方法: **
就是直接使用footerView
创建一个加载更多的按钮:
设置tableView尾部显示的控件(tableFooterView的宽度永远是tableView的宽度)
tableFooterView只需要设置高度
UIButton *footerBtn = [UIButton buttonWithType:UIButtonTypeSystem];
footerBtn.frame = CGRectMake(0, 0, 0, 35);
footerBtn.backgroundColor = [UIColor orangeColor];
[footerBtn setTitle:@"加载更多团购" forState:UIControlStateNormal];
但是这样做的不好的地方在于, 显示的宽度是我们的整个手机的屏幕. 而且是我们无法修改的
**第二种方法: **
第二种方法就是创建Xib
直接创建一个Xib
文件, 将我们想要界面用Xib
给描述出来就可以了
UINib *nib = [UINib nibWithNibName:@"MJTgFooterView" bundle:[NSBundle mainBundle]];
// 创建nib对象
UINib *nib = [UINib nibWithNibName:@"GJTgFooterView" bundle:nil];
// 加载xib\nib
UIView *footerView = [[nib instantiateWithOwner:nil options:nil] lastObject];
self.tableView.tableFooterView = footerView;
**第三种方法: **
也是利用Xib
创建footerView
但是这个与上一个方法之间的区别就是很完美的封装在不同的类中, 这个我们的控制器就只需一行代码就可以直接调用了,这个封装还有效的将我们后面的加载更多数据的内容也给很好的封装了
题外话:
现在的我们只是做一些简单的程序所以我们的代码文件都是随意放置的, 今天就说一下关于文件的如果放置
首先, 放置不同的文件夹规律是按照我们的MVC的来放置例如:
Snip20160322_6.png02. 2. 关于我们footerView
的 Xib的创建步骤:
首先是Xib
的直接创建
1. 上面中的1就是加载更多的数据而这个控件是直接是这个`Xib的子类
而我们后面的两个控件: (菊花\正在拼命加载)是我们的正在加载提示的子控件
这样做是为了, 将来在数据加载的时候, 这两个控件, 要么一起出来 , 要么就不出来, 注意的是, 我们的正在加载提示这个控件是个UIView
但是这个控件默认情况下是hidden
无法显示, 唯有我们点击了 加载数据这个按钮, 他才会显示出来
这里我们再回忆一次如果用Xib
来封装一个view
:
我们牵扯到一个如何更新数据, 更新什么数据???
/**
* 加载更多的数据
*/
- (void)loadingMoreData
{
// 1.添加更多的模型数据
GJTg *tg = [[GJTg alloc] init];
tg.icon = @"ad_01";
tg.title = @"新增加的团购数据..";
tg.price = @"100";
tg.buyCount = @"0";
[self.tgs addObject:tg];
// 2.刷新表格(告诉tableView重新加载模型数据, 调用tableView的reloadData)
[self.tableView reloadData];
}
这个是我们UIView控制器中的代码, 这个方法就是更新数据的
方法
/**
* 点击"加载"按钮
*/
- (IBAction)loadBtnClick {
// 1.隐藏加载按钮
self.loadBtn.hidden = YES;
// 2.显示"正在加载"
self.loadingView.hidden = NO;
// 3.显示更多的数据
// GCD
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 3.0s后执行block里面的代码
[self.controller loadingMoreData];
// 4.显示加载按钮
self.loadBtn.hidden = NO;
// 5.隐藏"正在加载"
self.loadingView.hidden = YES;
});
}
注意, 这里面是牵扯到一个界面的变换
如果我们点击了, 下面的加载更多数据, 就会显示正在加载提示的那个UIView
然后进过三秒钟之后(这个使用我们的block实现的)显示出新的数据.
而更新数据的方法在我们的UIView的控制器中, 我们在Xib
控制器中的这个方法是如果拿到, 我们的UIView
的方法呢???
这个有两种方法:
- 直接将我们的控制器给我们的
Xib
控制器:
- 首先, 让我们的这个方法暴露在外面(使任何类都可以访问)
#import <UIKit/UIKit.h>
@interface GJViewController : UIViewController
- (void)loadingMoreData;
@end
- 然后拿到我们的
UIView
的控制器:
#import <UIKit/UIKit.h>
@class GJViewController;
@interface GJTgFooterView : UIView
/**
* 快速创建一个footerView对象
*/
+ (instancetype)footerView;
@property (nonatomic , strong) GJViewController *controller;
@end
就可以调用我们的这个方法了, 代码如上面
但是上面的这种方法, 会导致我们的代码耦合性强, 所以不建议使用
所以我们要推荐使用第二种方法:
第二种方法就是利用代理模式即是我们下面要讲的内容:
团购 03 代理设计模式
谁代理谁???
其实是我们的控制器代理我们的Xib
控制器(footerView`)
只有当我们的footerView`被点击之后 , 我们的控制器监听这个点击事件, 然后做出反应(调用相应的方法)
**代码分析: **
GJFooterView.h文件
/**
1.协议名称: 控件类名 + Delegate
2.代理方法普遍都是@optional
3.
*/
@protocol GJTgFooterViewDelegate <NSObject>
@optional
- (void)tgFooterViewDidClickedLoadBtn:(GJTgFooterView *)tgFooterView;
@end
@interface GJTgFooterView : UIView
@property (nonatomic, weak) id<GJTgFooterViewDelegate> delegate;
@end
*GJViewController.m文件代码: *
footer.delegate = self;
这个就是我们利用代理的一部分代码:
首先, 说明这只是一层重构, 后面我们会继续重构
其次:
@property (nonatomic, weak) id<GJTgFooterViewDelegate> delegate;
这一段代码的中为什么要用id
和遵守这个协议<GJTgFooterViewDelegate>
???
- 用
id
可以让我们充当footerView
的代理的类, 不受限制.就是任何类都可以充当我们footerView
的代理 - 遵守这个协议, 是为了告诉我们的
footerView
调用代理的哪一个方法
[self.delegate loadingMoreData];
而我们上面所写的协议,只有这一个方法, 而这个方法名称和我们的控制器里面的方法名称一样 .
而且, 我们在控制器中的代码:
@interface GJViewController () <UITableViewDataSource, GJTgFooterViewDelegate>
footer.delegate = self;
这个代码的含义就是告诉我们的控制器, 我们的footerView
的代理就是他自己
那么, 当我们的footerView
的按钮被点击之后 , 它就会直接调用这个方法了.
团购 04 头部控件
头部文件其实就是一个图片轮播器, 这个我们就不多介绍了, 但是我们要说的是那个图片轮播器下面的猜你喜欢是怎么做出来的
其实就是一个简单的UIView
做出来的, 只是这个UIView
的高度为1而已, 当你将UIView
的高度设置为1的时候, 可能发现他的线条比较粗,所以, 建议再将他的透明度设为0.5这个就可以达到效果了,
还有就是我们的图片轮播器的代码在哪里写???
#import "GJTgHeaderView.h"
@interface GJTgHeaderView()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@end
@implementation GJTgHeaderView
+ (instancetype)headerView
{
return [[[NSBundle mainBundle] loadNibNamed:@"GJTgHeaderView" owner:nil options:nil] lastObject];
// headerView.scrollView
}
/**
* 当一个对象从xib中创建初始化完毕的时候就会调用一次
*/
- (void)awakeFromNib
{
// 在这里面添加图片轮播器
}
@end
我们图片轮播器的代码就在上面的那个方法中写:
作者说:
这次讲的是团购, 来了解如果自定义一个简单的cell
下次我们介绍的是如果利用自定义cell
做一个微博的简单界面.
网友评论