这个demo主要是使用到了MVC模式以及自定义一些现有的方法,从而进行改写,实现所需的功能,对应于本次demo,就是自定义表格的单元格cell。
界面如下所示。
其中,最上方是一个6张图的轮播图效果。
可以发现,整个界面是一个有着3个部分的UITableView的表格效果,第一部分有1行,第二部分也是1行,第三部分有5行,轮播图作为表头。
考虑到MVC模式使得代码管理更加高效,所以使用MVC模式。
M定义数据的属性,V关注视图部分,即屏幕上看到的组件,最终由C实现赋值。C就是ViewController.m。整个代码组成如下。
首先,在AppDelegate.m文件中初始化ViewController.m容器,然后初始化一个UINavigationController容器,这样界面有导航栏,代码如下。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ViewController *view=[[ViewController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:view];
[self.window setRootViewController:nav];
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
在ViewController.m文件中的viewDidLoad方法中初始化UITableview表格,实现轮播图,代码如下。
UITableView *table=[[UITableView alloc]initWithFrame:CGRectMake(0, 9, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) style:UITableViewStyleGrouped];
table.delegate=self;
table.dataSource=self; //设置数据源
[self.view addSubview:table];
UIScrollView *scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, MAINSCREENWIDTH, 230)]; //设置frame
scrollView.delegate=self; //设置代理,把权限给了这个视图
scrollView.contentSize=CGSizeMake(MAINSCREENWIDTH*6, 210); //设置滑动范围,6张图
scrollView.pagingEnabled=YES; //设置分页效果
scrollView.showsHorizontalScrollIndicator=NO; //关闭水平指示器
scrollView.showsVerticalScrollIndicator=NO; //关闭垂直指示器
NSMutableArray *scrollPicture=[[NSMutableArray alloc]initWithObjects:@"ad1.jpg",@"ad2.jpg",@"ad3.jpg",@"ad4.jpg",@"ad5.jpg",@"ad6.jpg", nil];
for(int i=0;i<6;i++)
{
CGFloat x=i*MAINSCREENWIDTH;
UIImageView *scrollImage=[[UIImageView alloc]init];
scrollImage.frame=CGRectMake(x, 0, MAINSCREENWIDTH, 210);
scrollImage.image=[UIImage imageNamed:scrollPicture[i]];
[scrollView addSubview:scrollImage];
}
self.pageControl=[[UIPageControl alloc]initWithFrame:CGRectMake(180, 210, 100, 20)];
self.pageControl.currentPage=0; //当前页面是0
self.pageControl.numberOfPages=6; //总共6个图片
table.tableHeaderView=scrollView; //将轮播图作为表头
[table addSubview:scrollView];
[table addSubview:self.pageControl];
注意加入下面这个方法,控制轮播图的滚动栏滑动。
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{//当滑动快要结束时,调用这个方法,控制下面那个滚动栏的滑动
CGFloat offset=scrollView.contentOffset.x;
int page=(offset+MAINSCREENWIDTH/2)/MAINSCREENWIDTH;
self.pageControl.currentPage=page;
}
至此,轮播图的设置基本完成,然后进行表格的设计。
将表格初始化为3个section,第一个section有一行,第二个section有一行,第三个section有五行,设置完毕各分区的行高,可以进行表格的初始化。
由界面可以看出,第一个section里8个相同模块,所以我们新建一个FoodOne类(继承自UIView)作为V,新建一个FoodModel类(继承自NSObject)作为M。在FoodModel.h(M)中声明属性,因为一个模块中只有一个图片、一个标签,所以声明图片名称、标签名称如下。
#import <Foundation/Foundation.h>
@interface FoodModel : NSObject
@property (nonatomic,strong)NSString *foodPhotoName;
@property (nonatomic,strong)NSString *foodName;
@end
然后在FoodOne.h(V)中声明组件,即图片UIImageV、标签UILabel,并暴露一个方法,如下。
#import <UIKit/UIKit.h>
#import "FoodModel.h"
@interface FoodOne : UIView
@property UIImageView *foodPhoto;
@property UILabel *foodNameLabel;
-(void)setFoodOne:(FoodModel *)foodModel;
@end
然后在FoodOne.m中写具体的组件布局以及暴露一个setFoodOne赋值方法,给C调用实现赋值,如下。
#define MAINSCREENWIDTH [UIScreen mainScreen].bounds.size.width
#import "FoodOne.h"
@implementation FoodOne
- (instancetype)initWithFrame:(CGRect)frame{ //重写方法
self= [super initWithFrame: frame]; //先初始化父类的方法
if(self){
[self creatUI]; //写自己定义的方法
}
return self;
}
-(void)creatUI{
self.foodPhoto=[[UIImageView alloc]initWithFrame:CGRectMake(20, 10, 70, 70)];
[self addSubview:self.foodPhoto];
self.foodNameLabel=[[UILabel alloc]initWithFrame:CGRectMake(5, _foodPhoto.frame.size.height+20, MAINSCREENWIDTH/4, 20)];
self.foodNameLabel.textAlignment=NSTextAlignmentCenter;
[self addSubview:self.foodNameLabel];
}
-(void)setFoodOne:(FoodModel *)foodModel{
self.foodNameLabel.text=foodModel.foodName;
self.foodPhoto.image=[UIImage imageNamed:foodModel.foodPhotoName];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
一个模块的初始化方法就完成了,然后新建一个FoodTableViewCell类,(注意这个类想要重写单元格的初始化方法,所以继承自UITableViewCell)在FoodTableViewCell类中实现八个模块的生成。因为总共有八个模块,考虑到便于代码的管理,所以使用数组,数组定义如下。数组中储存八个FoodModel,为每一个模型赋值。
FoodModel *food1 = [[FoodModel alloc] init];
food1.foodPhotoName = @"icon_grain-and-oil";
food1.foodName = @"粮油";
FoodModel *food2 = [[FoodModel alloc] init];
food2.foodPhotoName = @"icon_vegetables";
food2.foodName = @"蔬菜";
FoodModel *food3 = [[FoodModel alloc] init];
food3.foodPhotoName = @"icon_seasoning";
food3.foodName = @"调料干货";
FoodModel *food4 = [[FoodModel alloc] init];
food4.foodPhotoName = @"icon_egg";
food4.foodName = @"肉禽蛋";
FoodModel *food5 = [[FoodModel alloc] init];
food5.foodPhotoName = @"icon_fish";
food5.foodName = @"水冻产品";
FoodModel *food6 = [[FoodModel alloc] init];
food6.foodPhotoName = @"icon_dishware";
food6.foodName = @"餐具饮料";
FoodModel *food7 = [[FoodModel alloc] init];
food7.foodPhotoName = @"icon_drink";
food7.foodName = @"酒水饮料";
FoodModel *food8 = [[FoodModel alloc] init];
food8.foodPhotoName = @"icon_fruit";
food8.foodName = @"水果";
_foodArray=[[NSMutableArray alloc]initWithObjects:food1,food2,food3,food4,food5,food6,food7,food8, nil];
FoodTableViewCell.m的代码如下。
#define MAINSCREENWIDTH [UIScreen mainScreen].bounds.size.width
#import "FoodTableViewCell.h"
#import "FoodOne.h"
@implementation FoodTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier withArray:(NSMutableArray *)array{
//重写父类的方法,自定义的方法记得在.h文件中声明
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
for(int i=0;i<8;i++){ //用for循环实现八个模块的生成,注意上下的边界不同,所以用if语句分成两种情况
if(i<4){
FoodOne *food=[[FoodOne alloc]initWithFrame:CGRectMake( i* MAINSCREENWIDTH/4, 0, MAINSCREENWIDTH/4, 100)];
[self.contentView addSubview:food];
[food setFoodOne:array[i]];
}else{
FoodOne *food=[[FoodOne alloc]initWithFrame:CGRectMake( (i-4)* MAINSCREENWIDTH/4, 110, MAINSCREENWIDTH/4, 100)];
[self.contentView addSubview:food];
[food setFoodOne:array[i]];
}
}
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
至此,第一个section的自定义cell的方法基本完成,然后在ViewController.m文件中调用子类FoodTableViewCell自定义的方法实现第一个section的生成,代码如下。
static NSString *identifier=@"identifier";
if(indexPath.section==0){
FoodTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if(cell==nil){
cell=[[FoodTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier withArray:_foodArray];
}
return cell;
}
然后进行第二个section的布局。
第二个section总共有六个组件,四个UILabel和两个UIImageView。我们新建一个ActivityTableViewCell类(继承自UITableViewCell)作为V,新建一个ActivityModel类(继承自NSObject)作为M。在ActivityModel.h(M)中声明属性,因为一个模块中有两个图片、四个标签,所以声明图片名称、标签名称如下。
#import <Foundation/Foundation.h>
@interface ActivityModel : NSObject
@property (nonatomic,strong) NSString *activityPhoto1;
@property (nonatomic,strong) NSString *activityName1;
@property (nonatomic,strong) NSString *activityDetail1;
@property (nonatomic,strong) NSString *activityPhoto2;
@property (nonatomic,strong) NSString *activityName2;
@property (nonatomic,strong) NSString *activityDetail2;
@end
然后在ActivityTableViewCell.m重定义cell的实现方法,以及暴露一个setActivityModel方法给C调用,实现赋值,如下。
#define MAINSCREENWIDTH [UIScreen mainScreen].bounds.size.width
#import "ActivityTableViewCell.h"
@implementation ActivityTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
[self creatUI];
}
return self;
}
-(void)creatUI{
self.activityImage1=[[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 50, 50)];
[self.contentView addSubview:_activityImage1];
self.activityImage2=[[UIImageView alloc]initWithFrame:CGRectMake(MAINSCREENWIDTH/2, 10, 50, 50)];
[self.contentView addSubview:_activityImage2];
self.activityNameLabel1=[[UILabel alloc]initWithFrame:CGRectMake(70, 10, MAINSCREENWIDTH/2-50, 20)];
self.activityNameLabel1.font=[UIFont systemFontOfSize:21];
[self.contentView addSubview:_activityNameLabel1];
self.activityNameLabel2=[[UILabel alloc]initWithFrame:CGRectMake(MAINSCREENWIDTH/2+60, 10, MAINSCREENWIDTH/2-50, 20)];
self.activityNameLabel2.font=[UIFont systemFontOfSize:21];
[self.contentView addSubview:_activityNameLabel2];
self.activityDetailLabel1=[[UILabel alloc]initWithFrame:CGRectMake(70, 40, MAINSCREENWIDTH/2+50, 20)];
self.activityDetailLabel1.textColor=[UIColor grayColor];
self.activityDetailLabel1.font=[UIFont systemFontOfSize:16];
[self.contentView addSubview:_activityDetailLabel1];
self.activityDetailLabel2=[[UILabel alloc]initWithFrame:CGRectMake(MAINSCREENWIDTH/2+60, 40, MAINSCREENWIDTH/2-50, 20)];
self.activityDetailLabel2.textColor=[UIColor grayColor];
self.activityDetailLabel2.font=[UIFont systemFontOfSize:16];
[self.contentView addSubview:_activityDetailLabel2];
}
-(void)setActivityModel:(ActivityModel *)activityModel{
self.activityImage1.image=[UIImage imageNamed:activityModel.activityPhoto1];
self.activityImage2.image=[UIImage imageNamed:activityModel.activityPhoto2];
self.activityNameLabel1.text=activityModel.activityName1;
self.activityNameLabel2.text=activityModel.activityName2;
self.activityDetailLabel1.text=activityModel.activityDetail1;
self.activityDetailLabel2.text=activityModel.activityDetail2;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
至此,第二个section的自定义cell的方法基本完成,然后在ViewController.m文件中调用子类ActivityTableViewCell自定义的方法实现第二个section的生成,代码如下。
if(indexPath.section==1){
ActivityTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if(cell==nil){
cell=[[ActivityTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
[cell setActivityModel:self.activityModel];
return cell;
}
然后进行第三个section的布局。
第三个section总共有五个单元格,每个单元格里有四个组件,三个UILabel和一个UIImageView。我们新建一个StoreTableViewCell类(继承自UITableViewCell)作为V,新建一个StoreModel类(继承自NSObject)作为M。在StoreModel.h(M)中声明属性,因为一个模块中有一个图片、三个标签,所以声明图片名称、标签名称如下。
#import <Foundation/Foundation.h>
@interface StoreModel : NSObject
@property(nonatomic,strong)NSString *storePhotoName;
@property(nonatomic,strong)NSString *storeName;
@property(nonatomic,strong)NSString *storeDistance;
@property(nonatomic,strong)NSString *storeDeliveryCost;
@end
然后在StoreTableViewCell.m重定义cell的实现方法,以及暴露一个setStoreModel方法给C调用,实现赋值,如下。
#import "StoreTableViewCell.h"
@implementation StoreTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
[self creatUI];
}
return self;
}
-(void)creatUI{
self.view=[[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 100, 100)];
[self.contentView addSubview:self.view];
self.storeNameLabel=[[UILabel alloc]initWithFrame:CGRectMake(120, 20, 300, 20)];
self.storeNameLabel.font=[UIFont systemFontOfSize:21];
[self.contentView addSubview:self.storeNameLabel];
self.storeDistanceLabel=[[UILabel alloc]initWithFrame:CGRectMake(120, 50, 300, 20)];
self.storeDistanceLabel.font=[UIFont systemFontOfSize:16];
self.storeDistanceLabel.textColor=[UIColor grayColor];
[self.contentView addSubview:self.storeDistanceLabel];
self.storeDeliveryCostLabel=[[UILabel alloc]initWithFrame:CGRectMake(120, 80, 300, 20)];
self.storeDeliveryCostLabel.font=[UIFont systemFontOfSize:19];
[self.contentView addSubview:self.storeDeliveryCostLabel];
}
-(void)setStoreModel:(StoreModel *)storeModel{
self.view.image=[UIImage imageNamed:storeModel.storePhotoName];
self.storeNameLabel.text=storeModel.storeName;
self.storeDistanceLabel.text=storeModel.storeDistance;
self.storeDeliveryCostLabel.text=storeModel.storeDeliveryCost;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
至此,第三个section的自定义cell的方法基本完成,然后在ViewController.m文件中调用子类StoreTableViewCell自定义的方法实现第三个section的生成,代码如下。
StoreTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if(cell==nil){
cell=[[StoreTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
[cell setStoreModel:_storeArray[indexPath.row]];
return cell;
至此,所有代码基本完成。