07_UI基础_UITableView实战- 支付宝口碑

软件设计 2017-05-11

此篇为针对ios中的UI基础知识,为了能让大家更清楚的理解,此整理中编写了采用知识点+案例的方式,配有非常详细的截图和代码注释,添加了许多大白话进行解释,如有错误之处,望指正,愿与您相互交流学习,共同进步!---"会飞的猴子_阿新"

本篇案例修改图为(后面会逐步优化细节问题)

07_UI基础_UITableView实战- 支付宝口碑

主要内容从支付宝案例开始,重点在后面哦!

07_UI基础_UITableView实战- 支付宝口碑

使用UITableViewControler控制器实现支付宝口碑案例 UITableViewControler 缺陷: 现阶段只适合全屏的..

01-UITableViewController体验

  • 相当于一个控制器自带tableView
  • viewController管理的是view
  • tableViewController管理的是tableView
  • 也就是在tableViewController下,self.view = self.tableView

02-tableView的HeaderView和FooterView

  • tableView的header - (x, y, width) 可以随便指定,(height) 实际数值
  • tableView的footer - (y, width) 可以随便指定,(x, height) 实际数值

创建一个demo体验一下: 1.准备:新建文件-->把默认的的viewController删掉-->新建LJXTableViewController-->把Main.storyboard中默认的控制器删掉-->重写拖拽一个UITableViewController-->指定初始箭头,指定class. 2.添加头部视图

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *headerView = [[UIView alloc]init];
    headerView.backgroundColor =[UIColor redColor];
    //把某个控件设置到tableHeaderView上时,只有高度需要我们自己设置,前面 X , Y ,Width都可以直接给个0
    headerView.frame = CGRectMake(0, 0, 0, 100);
    
    //设置tableView的最顶部视图  
    self.tableView.tableHeaderView  = headerView;
    //-->这里只需要headerView赋值给tableHeaderView 这个属性,内部就在添加到父控件上我们就不用addSubview:

}

3.添加数据验证一下头部视图跟 "一组和多组" 没有关系

//
//  LJXTableViewController.m
//  LJX_tableView的头部和尾部视图

#import "LJXTableViewController.h"

@interface LJXTableViewController ()

@end

//重用标识
static NSString *ID = @"cell";

@implementation LJXTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *headerView = [[UIView alloc]init];
    headerView.backgroundColor =[UIColor redColor];
    //把某个控件设置到tableHeaderView上时,只有高度需要我们自己设置,前面 X , Y ,Width都可以直接给个0
    headerView.frame = CGRectMake(0, 0, 0, 100);
    
    
    //设置tableView的最顶部视图    注意:跟一组和多组没有关系
    self.tableView.tableHeaderView  = headerView;
    //-->这里只需要headerView赋值给tableHeaderView 这个属性,内部就在添加到父控件上我们就不用addSubview:
    
    //注册cell
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
}
//2组
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return  2;
}
//每组4行
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 4;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];
    
    cell.textLabel.text =@(indexPath.row).description;//简单设置数据,每个cell显示一个行数
    
    return cell;
}
@end

07_UI基础_UITableView实战- 支付宝口碑

4.添加底部视图

UIButton *footerBtn = [[UIButton alloc]init];
    footerBtn.backgroundColor = [UIColor purpleColor]; //紫色背景
    //把某个控件设置到tableHeaderView上时,只有高度需要我们自己设置,前面 X , Y ,Width都可以直接给个0,但是x是可以改的,改了会有影响但不建议去改
    footerBtn.frame = CGRectMake(0, 0, 0, 100);
    //设置tableView的最底部视图
    self.tableView.tableFooterView = footerBtn;

07_UI基础_UITableView实战- 支付宝口碑

03-星级评价-需求分析

07_UI基础_UITableView实战- 支付宝口碑

1.满星个数 "分数强转成整形,如4.5转成整形是4 那就表示有4颗满星"
2.半星个数 "分数 - 整星个数如果不为0那说明就有一个半星"
3.空心个数  "for(NSInteger i = 已添加星星个数; i < 5; i++)"

每一个商家的评分不一样,所以分值要动态传入,去动态设置星星样子

04-星级评价

4.1星级评价实现

创建实体文件夹,方便日后移植 为了方便最后整合代码时的移植,不直接在控制器中实现,而是单独创建继承UIView的类,

07_UI基础_UITableView实战- 支付宝口碑

//
//  ZFBLeverStar.h
//  LJX_星级评价

#import <UIKit/UIKit.h>

@interface ZFBLeverStar : UIView
///接收评分
@property (nonatomic, assign) CGFloat lever;

@end

07_UI基础_UITableView实战- 支付宝口碑

//
//  ZFBLeverStar.m
//  LJX_星级评价

#import "ZFBLeverStar.h"

@implementation ZFBLeverStar

//重写set方法在里面处理显示星星图片的细节
-(void)setLever:(CGFloat)lever{
    _lever = lever;
    
    //1.满星
    //把传过来的分数强转为整型,整数值就是满星的个数
    NSInteger fullStartCount = (NSInteger)lever;
    for(NSInteger i = 0 ; i < fullStartCount ; i++){
        [self makeLeverStarWithImageName:@"full_star" andPosition:i];
    }
    //2.半星
    // (取传过来的个数) - (强转后的整数),如果 > 0   就表示有半星
    if((lever - fullStartCount)>0){
        [self makeLeverStarWithImageName:@"half_star" andPosition:fullStartCount];
        //如果添加了一个半星那把满星个数的值做加1 用它当做 目前已经添加星星的总个数了
        fullStartCount++;
    }

    //3.空星 "如果到这来还不够5颗星 那剩下的就是空星的个数了"
    for (NSInteger i = fullStartCount; i < 5; i++) {
        [self makeLeverStarWithImageName:@"empty_star" andPosition:i];
    }
}

/**
 创建星星imageView

 @param imageName 星星图片
 @param position 星星位置 从0开始
 */
-(void)makeLeverStarWithImageName:(NSString *)imageName andPosition:(NSInteger)position{
    //1.创建imageView设置图片,那么imageView创建出来的就有尺寸
    UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:imageName]];
    //2.设置图片的x
    CGFloat imageViewX = position * imageView.image.size.width;
    imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
    [self addSubview:imageView];    
}

@end

07_UI基础_UITableView实战- 支付宝口碑

//
//  ViewController.m
//  LJX_星级评价


#import "ViewController.h"
#import "ZFBLeverStar.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    ZFBLeverStar *leverStar = [[ZFBLeverStar alloc]init];
    leverStar.frame = CGRectMake(100, 100, 60, 12);//素材中图片2X的是大小24*24,高24/2=12, 宽为5颗*12=60
    leverStar.backgroundColor = [UIColor purpleColor];
    
    leverStar.lever = 2.5;//先传一个2.5分验证一下
    [self.view addSubview:leverStar];
}

@end

4.2解决星星重复创建问题

我们只创建添加,没有管过移除啥的,顾导致传一次分,创建一次....

07_UI基础_UITableView实战- 支付宝口碑

解决重复创建的问题 重写初始化方法(初始化方法它只会调一次),那样一创建leverStar这个控件,里面就自带5颗星星imageView, 07_UI基础_UITableView实战- 支付宝口碑07_UI基础_UITableView实战- 支付宝口碑

即对ZFBLeverStar.m做了修改

//
//  ZFBLeverStar.m
//  LJX_星级评价

#import "ZFBLeverStar.h"

@implementation ZFBLeverStar

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //来了 直接把5个imageView创建添加好
        for (NSInteger i = 0; i < 5; i++) {
            UIImageView *imageView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"full_star"]];//这个目的不是拿图片,目的是随便拿一张图片,图片就有了大小了
        //设置图片的x
         CGFloat imageViewX = i * imageView.image.size.width;
            imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
         
             [self addSubview:imageView];
           
        }
    }
    return self;
}

//重写set方法在里面处理显示星星图片的细节
-(void)setLever:(CGFloat)lever{
    _lever = lever;
    
    //1.满星
    //把传过来的分数强转为整型,整数值就是满星的个数
    NSInteger fullStartCount = (NSInteger)lever;
    for(NSInteger i = 0 ; i < fullStartCount ; i++){
        [self makeLeverStarWithImageName:@"full_star" andPosition:i];
    }
    //2.半星
    // (取传过来的个数) - (强转后的整数),如果 > 0   就表示有半星
    if((lever - fullStartCount)>0){
        [self makeLeverStarWithImageName:@"half_star" andPosition:fullStartCount];
        //如果添加了一个半星那把满星个数的值做加1 用它当做 目前已经添加星星的总个数了
        fullStartCount++;
    }

    //3.空星 "如果到这来还不够5颗星 那剩下的就是空星的个数了"
    for (NSInteger i = fullStartCount; i < 5; i++) {
        [self makeLeverStarWithImageName:@"empty_star" andPosition:i];
    }
}

/**
 创建星星imageView

 @param imageName 星星图片
 @param position 星星位置 从0开始
 */
-(void)makeLeverStarWithImageName:(NSString *)imageName andPosition:(NSInteger)position{
    //获取相应位置的子控件
    UIImageView *imageView = self.subviews[position];
    //设置图片
    imageView.image = [UIImage imageNamed:imageName];
}

@end

4.3 最后深入的优化

这次优化的目的是:日后星级评价更加的方便.--->外部不管用纯代码还有用xib还是用storyboard都比较方便.

07_UI基础_UITableView实战- 支付宝口碑

如何不想使用代码方式 07_UI基础_UITableView实战- 支付宝口碑 使用storyboard 07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

运行ok

支付宝口碑案例开始

自定义cell有3种方式,分别是storyboard,xib,手写代码. 我们都使用一遍.这里我们先使用第一种方式使用-->storyboard方式

需求分析

1.顶部是一个TableViewHeaderView
2.组的头部标题可以停留,说明tableView是plain样式
3.cell中的数据比较多,系统无法满足,自定义cell

[blockquote]

1.项目准备: 指定类前缀(例如ZFB),分文件夹(目的是为了后面集成到一个项目中),删除原有Main.storyboard 自己创建一个storyboard(指定class进行关联,设置为启动界面),并别忘指定 Main interface

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑 创建控制器: 注意继承UITableViewController(因为storyboard中我们拖拽的UITableViewControler,所以创建的类也要继承UITableViewControler)

如果运行后,是白色面板. 排错方法:打断点 ------>给数据源方法打断点------->(没执到时)-往上打断点 ------->[super viewDidLoad]----->(也没有执行到时) ------>查看有没有指定控制器class;

把准备好的plist文件和图片素材拖入案例中

07_UI基础_UITableView实战- 支付宝口碑

使用了UITableViewController后,指定数据源和遵守协议都不用我们管了.下一步我们来实现相应的数据源方法

[blockquote]

2.实现相应的数据源方法

[/blockquote]

需要的数据,通过第4步会得到.

[blockquote]

3.有多少行应该根据数据来

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

4.加载plist字典转换模型

[/blockquote]

去modal文件夹中,创建模型类

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

//--------------------ZFBBusinessModel.h------------------------
#import <Foundation/Foundation.h>

@interface ZFBBusinessModel : NSObject
///头像
@property (nonatomic, copy) NSString *icon;
///优惠信息
@property (nonatomic, copy) NSString *discount;
///人均消费
@property (nonatomic, strong)  NSNumber *averagePrice;
///距离
@property (nonatomic, strong)  NSNumber *distance;
///打折
@property (nonatomic, strong)  NSNumber *offNum;
///评分
@property (nonatomic, strong)  NSNumber *level;
///店名
@property (nonatomic, copy) NSString *name;

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

@end
//--------------------ZFBBusinessModel.m------------------------
#import "ZFBBusinessModel.h"

@implementation ZFBBusinessModel

+(instancetype)businessWithDict:(NSDictionary *)dict{
    id obj = [[self alloc]init];
    
    [obj setValuesForKeysWithDictionary:dict];
    //--->注意使用KVC编码,属性名和字典中的key的名字一定要相同.
    return obj;
}

@end

[blockquote]

5.在storyboard中给自带的UITableViewCell指定重用标识 一定要和返回cell的数据源方法是的标识要一样

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

UITableView *cell = [tableView dequeueReusableCellWithIdentifier:@"business" forIndexPath:indexPath];

[blockquote]

6.在storyboard中给cell添加拖拽相应的控件,并添加约束

[/blockquote]

6.1拖拽imageView (plus是3X的在这除以3 工作中一般都2x的,到时候除以2)

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

因为各个商家图片不一样大,顾为了统一

07_UI基础_UITableView实战- 支付宝口碑

Scale:拉伸图片 Aspect:图片长宽的比例,保持图形的长宽比,保持图片不变形。

Aspect Fill:在保持长宽比的前提下,缩放图片,使图片充满容器。 Aspect Fit:在保持长宽比的前提下,缩放图片,使得图片在容器内完整显示出来。 Scale to Fill: 缩放图片,使图片充满容器。图片未必保持长宽比例协调,有可能会拉伸至变形。

6.1拖拽lable设置店名

07_UI基础_UITableView实战- 支付宝口碑

6.3 先拖个view给星星占个位,后面再处理 07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

6.4拖拽lable设置评分

07_UI基础_UITableView实战- 支付宝口碑

设置约束

07_UI基础_UITableView实战- 支付宝口碑

6.4拖拽lable设置人均消费 设置字体大小,设置约束

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

运行一下看效果,然后再继续

07_UI基础_UITableView实战- 支付宝口碑

6.5拖拽lable设置折扣

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

设置约束 07_UI基础_UITableView实战- 支付宝口碑07_UI基础_UITableView实战- 支付宝口碑 6.6拖拽lable设置距离 设置约束 x和Y 07_UI基础_UITableView实战- 支付宝口碑07_UI基础_UITableView实战- 支付宝口碑 6.7拖拽lable设置减字 07_UI基础_UITableView实战- 支付宝口碑 设置约束(上边距8,与上面左边对齐,)略 减字外面的是正方形,我们设置一下宽高比为1:1,文字居中就ok了

07_UI基础_UITableView实战- 支付宝口碑

6.8拖拽lable设置随机立减... (设置字体及颜色,设置约束,略..) 6.9 修改一下cell的高度 07_UI基础_UITableView实战- 支付宝口碑 上面修改了business中的高度,只是修改了模型的大小,运行起来还得看 table View的高度大小,所以还得修改table View的高度 07_UI基础_UITableView实战- 支付宝口碑 6.10 把背景颜色去掉运行一下看看

[blockquote]

7.创建一个继承至UITableViewCell的类,并且指定SB中的UITableViewCell的class为自己创建出来的这个类

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

8.把SB中Cell内部的子控件连线到指定class的.m中的延展中

[/blockquote]

8.1增加一个延展

07_UI基础_UITableView实战- 支付宝口碑

8.2指定class 07_UI基础_UITableView实战- 支付宝口碑 8.3 子控件连线 07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

9.把模型变成属性定义在自定义cell类的.h中,在.m重写模型属性的set方法在此方法设置数据

[/blockquote]

9.1 把模型变成属性定义在自定义cell类的.h中

07_UI基础_UITableView实战- 支付宝口碑

//  ZFBBusinessCell.h

#import <UIKit/UIKit.h>
@class ZFBBusinessModel;
@interface ZFBBusinessCell : UITableViewCell
///模型属性    注意模型是个对象 用strong
@property (nonatomic , strong) ZFBBusinessModel *businessModel;

@end

9.2 在.m重写模型属性的set方法在此方法设置数据

07_UI基础_UITableView实战- 支付宝口碑

//
//  ZFBBusinessCell.m


#import "ZFBBusinessCell.h"
#import "ZFBBusinessModel.h"//注意导入头文件
@interface ZFBBusinessCell ()
///商店的头像
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
///店名
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
///评分
@property (weak, nonatomic) IBOutlet UILabel *levelLabel;
///人均消费
@property (weak, nonatomic) IBOutlet UILabel *averagePriceLabel;
///打折
@property (weak, nonatomic) IBOutlet UILabel *offNumLabel;
///距离
@property (weak, nonatomic) IBOutlet UILabel *distanceLabel;
///优惠信息 
@property (weak, nonatomic) IBOutlet UILabel *discountLabel;

@end

@implementation ZFBBusinessCell

//重写模型属性的set方法在此方法中给子控件设置数据
-(void)setBusinessModel:(ZFBBusinessModel *)businessModel{
    _businessModel =businessModel;
    
    _iconView.image = [UIImage imageNamed:businessModel.icon];
    _nameLabel.text = businessModel.name;
    _levelLabel.text = businessModel.level.description;//level是NSNumber类型的,转字符串掉description方法
    _averagePriceLabel.text = [NSString stringWithFormat:@"人均消费 %@ 元",businessModel.averagePrice];  //plist中只存了个数字,要显示人均消费**元,顾要拼接字符串
    _offNumLabel.text = [NSString stringWithFormat:@"%@ 折",businessModel.offNum];
    _distanceLabel.text = [NSString stringWithFormat:@"距离北京石油化工学院 %@ m",businessModel.distance];
    _discountLabel.text = businessModel.discount;
}


@end

回到ZFBBusinessController.m中 修改创建的cell类型

07_UI基础_UITableView实战- 支付宝口碑

设置数据 07_UI基础_UITableView实战- 支付宝口碑

//2.设置数据        (传递模型,这里是单组数据展示, 当只有一组数据的时候用row,多组的时候才先用section再用row)
    cell.businessModel = self.businessData[indexPath.row];

运行看现阶段效果

07_UI基础_UITableView实战- 支付宝口碑

数据类型有点小问题,8.8折和9.8折后面都一大串,接下来修改

[blockquote]

10.打折 把模型中的offNum 改float类型,前提要改一下引入系统框架 UIKit

[/blockquote]

10.1修改ZFBBusinessModel.h文件

07_UI基础_UITableView实战- 支付宝口碑

10.2修改ZFBBusinessCell.m文件 07_UI基础_UITableView实战- 支付宝口碑

运行看效果

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

11.集成星星,把星星的文件拖拽出来后,指定Storyboard中代表星星的那个View的Class

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

12.把用来表示星星view连线在自定义cell.m中,引入星星类的头文件

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

13.在模型属性的set方法中,给星星view传level

[/blockquote]

_leverView.lever = businessModel.level;

07_UI基础_UITableView实战- 支付宝口碑

上面报错是因为我们传的是CGFloat类型导致的 07_UI基础_UITableView实战- 支付宝口碑07_UI基础_UITableView实战- 支付宝口碑 顾改一下 07_UI基础_UITableView实战- 支付宝口碑 这是这里又报错 07_UI基础_UITableView实战- 支付宝口碑 还要改一下 07_UI基础_UITableView实战- 支付宝口碑 把星星后面黄色背景颜色去掉,运行看效果

[blockquote]

14.创建了一个xib 把xib中的view 宽361 高960

[/blockquote]

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

15.在里面拖入一个imageView并且设置好图片, 注意先 com + = 自适应下 为了后面使用Aspect ratio后图片不会变形 16. 第一个imageView 上 左 右 8间距 + 宽高比

[/blockquote]

先使用 com + = 自适应 ,后面再设置宽高比,这样他会根据真实的尺寸算比例,图片不会变形

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

17.再复制3个imageView 但注意它身上约束

[/blockquote]

即复制完后,clear复制的约束

[blockquote]

18.全部选中(com+a) 左对齐 等宽等高 上下间距8

[/blockquote]

左对齐

07_UI基础_UITableView实战- 支付宝口碑

等宽等高 07_UI基础_UITableView实战- 支付宝口碑

上下间距8:

注意在设置上下间距前,要保证两个图片之间不要有重合

[blockquote]

19.创建一个继承 至UIView的类,并且给xib指定class

[/blockquote]

继承关系是跟最顶层有关系的,最顶层是UIView,就继续UIView,最顶层是UIButton,那就继续UIButton. 这里是顶层是UIView.

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

给xib指定class(其实不指定也可以,因为之间没有连线,但最好指定一下,说明它们之间是同一类型)

07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

20.把加载xib细节封装在刚才创建的类中,提供一个可以让外部调用的类方法,目的降低耦合度.

[/blockquote]

//#########################
//  ZFBBusinessPictureView.h
#import <UIKit/UIKit.h>

@interface ZFBBusinessPictureView : UIView

/**
 加载xib创建头部视图
 */
+(instancetype)businessPictureView;

@end


//#########################
//  ZFBBusinessPictureView.m
#import "ZFBBusinessPictureView.h"

@implementation ZFBBusinessPictureView


/*
 
 知识点回顾--两种加载xib的方式
 1.NSBundle加载XIB  iOS 2.0 的方法
 2.使用UINib加载XIB  iOS 4.0 的方法   做了内存优化"如果内存紧张"内存警告,可以自动释放,如果有需要会重新自动加载""
 */

+(instancetype)businessPictureView{

    UINib *nib = [UINib nibWithNibName:@"ZFBBusinessPicture" bundle:nil];
    return [[nib instantiateWithOwner:nil options:nil]firstObject];
}

@end

[blockquote]

21.给tableView设置tableHeaderView 注意要计算它将来真实的高度

[/blockquote]

回到ZFBBusinessController.m 回到控制器中,导入刚才创建类的头文件ZFBBusinessPictureView.h

在控制器设置tableView的头部 视图.

07_UI基础_UITableView实战- 支付宝口碑

//2.设置tableView的头部视图
    ZFBBusinessPictureView *pictureView = [ZFBBusinessPictureView businessPictureView];
    //375 * 960 / 361
    CGFloat pictureViewHeight = self.tableView.bounds.size.width * pictureView.bounds.size.height / pictureView.bounds.size.width;  //根据比例计算真实高度
        pictureView.frame = CGRectMake(0, 0, self.tableView.bounds.size.width, pictureViewHeight); //宽度最好不要给了,以防有问题
  
    self.tableView.tableHeaderView = pictureView;  //设置为头部视图

[blockquote]

22.给tableView设置tableFooterView

[/blockquote]

//3.设置tableView的尾部视图
    UIButton *footerBtn = [[UIButton alloc]init];
    [footerBtn setTitle:@"点击加载更多" forState:UIControlStateNormal];
    
    [footerBtn setTitleColor:[UIColor colorWithWhite:0.3 alpha:1] forState:UIControlStateNormal];
    [footerBtn setTitleColor:[UIColor colorWithWhite:0.7 alpha:1] forState:UIControlStateHighlighted];
    
    footerBtn.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1];
    footerBtn.frame = CGRectMake(0, 0, 0, 30);
    
    
    self.tableView.tableFooterView = footerBtn;//设置为尾部视图

[blockquote]

23.实现没点击加载更多一次,多输出一个cell

[/blockquote]

把之前定义是不可变数组,修改为可变数组,不然就会报警告

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑07_UI基础_UITableView实战- 支付宝口碑07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

24.优化让其自动滚动

[/blockquote]

1.atScrollPosition: 的参数为UITableViewScrollPositionMiddle时 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.businessData.count-1 inSection:0]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

07_UI基础_UITableView实战- 支付宝口碑

2.atScrollPosition: 的参数为UITableViewScrollPositionBottom时 07_UI基础_UITableView实战- 支付宝口碑

[blockquote]

25.细节处理 让cell的分割线从最左边开始

[/blockquote]

self.tableView.separatorInset = UIEdgeInsetsZero;

后面还没会慢慢对细节进行处理

检测自己

看看哪些没掌握:

1、能够说出tableViewController的view属性和tableView是一样的

2、能够使用xib布局口碑的头部视图

3、能够说出使用代码重新设置nib高度的含义是为了适配不同宽度的屏幕

4、能够使用代码设置尾部的按钮

5、能够说出代码会调用view的initWithFrame方法

6、能够说出sb/xib会调用view的aweakFromNib方法

7、能够将星级评价小框架移植到口碑控制器中

8、能够解决浮点数转字符串精度的问题

9、能够使用代码解析plist数据 ) 10、能够使用代码将字典转化成模型

11、能够使用代码设置tableView的headerView和footerView

简单回顾过程

1.口碑-数据分析

2.口碑-创建模型

  • 类前缀
  • 分文件夹
  • 素材

3.口碑-解析数据

4.口碑-通过sb加载cell

  • 通过sb加载cell,需要设置cell的Identifier,给sb中的cell设置重用标识即完成注册单元格

5.口碑-cell的布局

1.商家配图图片大小不一样,所以最好给imageView设置宽高约束,达到配图尺寸统一
2.label如果只有一行时,只用设置位置即可,尺寸让它自适应
3.评分view,它的大小不能自适应,所以必须设置宽高约束"60,12"
4.减是个方形的,所以最好设置个宽高比


店名字体:14字体
其它是12号字体
到cell边距15
内部边距11

6.口碑-自定义cell控件连线

1.cell中的子控件不能连线到控制器,因为当前控制器只有一个,但是将来cell有很多个,所以会报重复连接"连线"错误
2.正确作法,应该创建一个继承至UITableViewCell的类,来管理"描述/表示",设置cell的customClass
3.把cell中子控件的连线,连入到管理cell类的.m的延展中

7.口碑-设置cell数据

引入模型属性"strong"
重写模型属性set方法给cell内部子控件设置数据

8.口碑-移植星级评价

  • 拖拽文件,设置sb中的view为自定义view,连线并在set数据的方法中把数据放在控件上
  • 用自定义星星的类来描述cell中的星星view,加载sb中的小星星view创建出来的对象,就是他指定类创建来出的对象"他们是同一个东西了"
  • 再给level传入分值即可

9.口碑-头部视图-布局

  • 第一个视图分别设置 上,左,右,宽高比
  • 后面的视图与前一个等宽,等高,垂直间距,水平居中

10.口碑-头部视图-代码设置缩放比例

- 在xib中调整好位置高度,并在视图加载完成之后根据'宽度'和'屏幕的宽度'和'屏幕的高度'设置**高度**
- tableView的宽 / xib中HeaderView的宽 * xib中HeaderView的高 得到按比例缩放后的realHeaderView的高
- xib中的高 * tableView的宽 / xib中的宽
- xib的高 / xib的宽  * tableView的宽
2: 3 == 4: 6?

11.口碑-尾部视图

  • 灰度,R=G=B
  • 1为白色 0为黑色

12.口碑-组头

  • tableview两种样式组头的区别? grouped跟着tableView滚动出去
  • plain可以悬停在上方

13.口碑-添加导航控制器

Editor -> Embedin -> Navgation Contorller

20-MarkMan测量截图位置

21-KVC

// 方法1 传统写法
        _name = dict[@"name"];
        // 字典不能保存基本数据类型
        _age = [dict[@"age"] integerValue];
// 方法2 KVC - `间接`通过 key 设置数值
        // 注意:基本数据类型,不需要转换,KVC 可以自动实现转换!
        [self setValue:dict[@"name"] forKey:@"name"];
        [self setValue:dict[@"age"] forKey:@"age"];
// 方法3 KVC - 进阶,循环遍历字典
        for (NSString *key in dict) {
            // 1. 通过 key 取值
            id value = dict[key];

            // 2. 通过 KVC 方法设置数值
            // -key 对应对象的 `属性`,如果属性不存在就崩溃
            [self setValue:value forKey:key];
        }
// 方法4 KVC 字典转模型大招 -> 内部实际上就是方法3的实现
        [self setValuesForKeysWithDictionary:dict];
  • 在保证模型的属性和字典中的key相同的情况下,字典转模型使用setValuesForKeysWithDictionary:方法
  • keys value coding 键值编码

附整体代码

/**总步骤:
 1.指定类前缀,分文件夹'删除原有Main.sb' 自己创建一个,并别忘指定 Main interface
 2.实现相应的数据源方法
 3.有多少行应该根据数据来
 4.加载plist字典转换模型
 5.在sb中给自带的UITableViewCell指定重用标识 一定要和返回cell的数据源方法是的标识要一样
 6.在SB中给cell添加拖拽相应的控件,并添加约束
 7.创建一个继承至UITableViewCell的类,并且指定SB中的UITableViewCell的class为自己创建出来的这个类
 8.把SB中Cell内部的子控件连线到指定class的.m中的延展中
 9.把模型变成属性定义在自定义cell类的.h中,在.m重写模型属性的set方法在此方法设置数据
 10.打折 把模型中的offNum 改float类型,前提要改一下引入系统框架 UIKit
 11.集成星星,把星星的文件拖拽出来后,指定SB中代表星星的那个View的Class 
 12.把用来表示星星view连线在自定义cell.m中,引入星星类的头文件
 13.在模型属性的set方法中,给星星view传level
 14.创建了一个xib 把xib中的view 宽361 高960
 15.在里面拖入一个imageView并且设置好图片, com + = 自适应下 为了不用改宽高比约束值
 16. 第一个imageView  上  左 右  8间距  + 宽高比
 17. 复制3个imageView 但注意它身上约束
 18. 全部选中左对齐 等宽等高  上下间距8
 19. 创建一个继承 至UIView的类,并且指定class
 20. 把加载xib细节封装在此类中,提供一个可以让外部调用的类方法
 21.给tableView设置tableHeaderView  注意要计算它将来真实的高度
 22.给tableView设置tableFooterView
 23.实现没点击加载更多一次,多输出一个cell
 24.优化让其自动滚动
 25.细节处理  让cell的分割线从最左边开始
*/

07_UI基础_UITableView实战- 支付宝口碑

07_UI基础_UITableView实战- 支付宝口碑

//********************ZFBBusinessController.h*****************************
//  ZFBBusinessController.h
#import <UIKit/UIKit.h>

@interface ZFBBusinessController : UITableViewController

@end

//**********************ZFBBusinessController.m***************************
//
//  ZFBBusinessController.m
//  LJX_支付宝口碑(stroyboard搭建)

#import "ZFBBusinessController.h"
#import "ZFBBusinessModel.h"
#import "ZFBBusinessCell.h"
#import "ZFBBusinessPictureView.h"

@interface ZFBBusinessController ()
//数据在多个数据源方法中使用,顾声明一个属性
@property (nonatomic ,strong)NSMutableArray *businessData;
@end

@implementation ZFBBusinessController

- (void)viewDidLoad {
    [super viewDidLoad];
    //1.加载数据
    self.businessData = [self loadBusinessData];
    //-->使用方式2时,直接调用方法就行[self loadBusinessData];

    //2.设置tableView的头部视图
    ZFBBusinessPictureView *pictureView = [ZFBBusinessPictureView businessPictureView];
    
    //如果不设置,因为xib中设置的宽度是361,如果在375的手机屏幕上显示,因为xib中的图片的宽度没有写死,当到了宽屏幕下,变宽,高也会变高,导致图片会超出父控件, 出了头部视图的边界.
    //375 * 960 / 361
    CGFloat pictureViewHeight = self.tableView.bounds.size.width * pictureView.bounds.size.height / pictureView.bounds.size.width;  //计算真实高度
        pictureView.frame = CGRectMake(0, 0, self.tableView.bounds.size.width, pictureViewHeight); //宽度最好不要给了,以防有问题
  
    self.tableView.tableHeaderView = pictureView;  //设置为头部视图
    
    
    //3.设置tableView的尾部视图
    UIButton *footerBtn = [[UIButton alloc]init];
    [footerBtn setTitle:@"点击加载更多" forState:UIControlStateNormal];
    
    // colorWithWhite:0.3 alpha:1  通过灰度来设置颜色 第一个参数如果 传0就是黑色  如果传1就表示白色
    [footerBtn setTitleColor:[UIColor colorWithWhite:0.3 alpha:1] forState:UIControlStateNormal];
    [footerBtn setTitleColor:[UIColor colorWithWhite:0.7 alpha:1] forState:UIControlStateHighlighted];
    
    footerBtn.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1];
    footerBtn.frame = CGRectMake(0, 0, 0, 30);
    
    [footerBtn addTarget:self action:@selector(loadMoreData) forControlEvents:UIControlEventTouchUpInside]; //添加点击事件
    
    self.tableView.tableFooterView = footerBtn;//设置为尾部视图
    
    
    //小细节处理 :让分割线从最左边开始
    self.tableView.separatorInset = UIEdgeInsetsZero;

 }

#pragma mark -尾部按钮点击后会调用此方法
//1.加载更多数据
-(void)loadMoreData{
    //1.创建一个新的模型
    ZFBBusinessModel *businessModel = [[ZFBBusinessModel alloc]init];
    businessModel.icon = @"ss";
    
    businessModel.discount = @"全场大派送,2元一件,快来买!";
    businessModel.averagePrice = @2;
    businessModel.distance = @20;
    businessModel.offNum = 2;
    businessModel.level = 5;
    businessModel.name = @"西单大悦城!";
    
    //2.把新模型添加到保存所以数据的数组中
    [self.businessData addObject:businessModel];
    
    //3.让数据源方法重新执行
    [self.tableView reloadData];
    
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.businessData.count-1 inSection:0];
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    
}


#pragma mark -数据源方法
// 应该口碑案例表格就1组,默认就1组,所以不用再写
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
//    return 1;
//}

// 行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.businessData.count;
   //--->使用方式2时: return _businessList.count;
}

//
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    //1.创建cell
    ZFBBusinessCell *cell = [tableView dequeueReusableCellWithIdentifier:@"business" forIndexPath:indexPath];
    //-->这里在storyboard中进行注册cell
    
    //2.设置数据        (传递模型,这里是单组数据展示, 当只有一组数据的时候用row,多组的时候才先用section再用row)
    cell.businessModel = self.businessData[indexPath.row];
    
    //3.返回cell
    return cell;
}


#pragma mark -加载数据

- (NSMutableArray *)loadBusinessData{
    //1.加载plist
    NSMutableArray *dictArr = [NSMutableArray arrayWithContentsOfURL:[[NSBundle mainBundle]URLForResource:@"business.plist" withExtension:nil]];
    
    //2. 创建可变数组保存模型     /kə'pæsɪtɪ/ 容量
    NSMutableArray *arryM = [NSMutableArray arrayWithCapacity:dictArr.count];
    
    //3.字典转模型
    for(NSDictionary *dict in dictArr){
        
        [arryM addObject:[ZFBBusinessModel businessWithDict:dict]];

        /* 分步写
        //3.1 把字典传递给模型,让模型设置自己的属性
        ZFBBusinessModel *groupModel = [ZFBBusinessModel businessWithDict:dict];
        //3.2 把创建好的模型添加到可变数组中.
         [arryM addObject: groupModel];
        */
     }

    return arryM;
}

/*
 
 方式2. 加载数据方法的返回值设置为空 ,声明一个成员变量(给成员变量设置泛型),把可变数组赋值给成员变量
 
 1.  NSArray<ZFBBusinessModel *> *_businessList; //声明成员变量,设置泛型
 2.
 - (void)loadBusinessData{
    ...code略....
   _businessList = arryM;
 }
 
 */

@end

07_UI基础_UITableView实战- 支付宝口碑

//
//  ZFBBusinessModel.h
#import <UIKit/UIKit.h>

@interface ZFBBusinessModel : NSObject
///头像
@property (nonatomic, copy) NSString *icon;
///优惠信息
@property (nonatomic, copy) NSString *discount;
///人均消费
@property (nonatomic, strong)  NSNumber *averagePrice;
///距离
@property (nonatomic, strong)  NSNumber *distance;
///打折
//浮点数字转出成字符串时,可能会出现问题,把它转换成float 
@property (nonatomic, assign)  float offNum;
///评分
@property (nonatomic, assign)  CGFloat level;
///店名
@property (nonatomic, copy) NSString *name;

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

@end
#import "ZFBBusinessModel.h"

@implementation ZFBBusinessModel

+(instancetype)businessWithDict:(NSDictionary *)dict{
    id obj = [[self alloc]init];
    
    [obj setValuesForKeysWithDictionary:dict];
    //--->注意使用KVC编码,属性名和字典中的key的名字一定要相同.
    return obj;
}


@end

07_UI基础_UITableView实战- 支付宝口碑

//
//  ZFBLeverStar.h
//  LJX_星级评价

#import <UIKit/UIKit.h>

@interface ZFBLeverStar : UIView
///接收评分
@property (nonatomic, assign) CGFloat lever;

@end
//
//  ZFBLeverStar.m
//  LJX_星级评价

#import "ZFBLeverStar.h"

@implementation ZFBLeverStar

//当一个视图从xib或storyboard中创建完成之后就会调用此方法
-(void)awakeFromNib{
    [super awakeFromNib];
   
    //来了 直接把5个imageView创建添加好
    for (NSInteger i = 0; i < 5; i++) {
        UIImageView *imageView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"full_star"]];//这个目的不是拿图片,目的是随便拿一张图片,图片就有了大小了
        //设置图片的x
        CGFloat imageViewX = i * imageView.image.size.width;
        imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);

        [self addSubview:imageView];
    }
}

//此方法只有用代码创建时才会调用
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //来了 直接把5个imageView创建添加好
        for (NSInteger i = 0; i < 5; i++) {
            UIImageView *imageView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"full_star"]];//这个目的不是拿图片,目的是随便拿一张图片,图片就有了大小了
        //设置图片的x
         CGFloat imageViewX = i * imageView.image.size.width;
            imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
         
             [self addSubview:imageView];
           
        }
    }
    return self;
}


//重写set方法在里面处理显示星星图片的细节
-(void)setLever:(CGFloat)lever{
    _lever = lever;
    
    //1.满星
    //把传过来的分数强转为整型,整数值就是满星的个数
    NSInteger fullStartCount = (NSInteger)lever;
    for(NSInteger i = 0 ; i < fullStartCount ; i++){
        [self makeLeverStarWithImageName:@"full_star" andPosition:i];
    }
    //2.半星
    // (取传过来的个数) - (强转后的整数),如果 > 0   就表示有半星
    if((lever - fullStartCount)>0){
        [self makeLeverStarWithImageName:@"half_star" andPosition:fullStartCount];
        //如果添加了一个半星那把满星个数的值做加1 用它当做 目前已经添加星星的总个数了
        fullStartCount++;
    }

    //3.空星 "如果到这来还不够5颗星 那剩下的就是空星的个数了"
    for (NSInteger i = fullStartCount; i < 5; i++) {
        [self makeLeverStarWithImageName:@"empty_star" andPosition:i];
    }
}

/**
 创建星星imageView

 @param imageName 星星图片
 @param position 星星位置 从0开始
 */
-(void)makeLeverStarWithImageName:(NSString *)imageName andPosition:(NSInteger)position{
    //获取相应位置的子控件
    UIImageView *imageView = self.subviews[position];
    //设置图片
    imageView.image = [UIImage imageNamed:imageName];
}

@end

/*
 //1.创建imageView设置图片,那么imageView创建出来的就有尺寸
 UIImageView *imageView = [[UII 

相关推荐