• iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)


    iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)

    说明: 该部分完成对自定义cell页面的基本搭建,尚未进行优化处理。且还存在很多问题,譬如每行的高度设置暂时是固定的,这些问题将会在下一篇文中解决。

    一、实现效果

               

    二、实现代码

    数据模型部分:

    YYweiboModel.h文件

     1 //
     2 //  YYweiboModel.h
     3 //  微博基本信息展示
     4 //
     5 //  Created by 孔医己 on 14-6-2.
     6 //  Copyright (c) 2014年 itcast. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 @interface YYweiboModel : NSObject
    12 /**
    13  *  昵称
    14  */
    15 @property(nonatomic,copy)NSString *name;
    16 /**
    17  *  正文
    18  */
    19 @property(nonatomic,copy)NSString *text;
    20 /**
    21  *  头像
    22  */
    23 @property(nonatomic,copy)NSString *icon;
    24 /**
    25  *  配图
    26  */
    27 @property(nonatomic,copy)NSString *picture;
    28 /**
    29  *  是否是vip
    30  */
    31 @property(nonatomic,assign)BOOL vip;
    32 
    33 //接口
    34 -(instancetype)initWithDict:(NSDictionary *)dict;
    35 +(instancetype)weiboModelWithDict:(NSDictionary *)dict;
    36 @end

    YYweiboModel.m文件

     1 //
     2 //  YYweiboModel.m
     3 //  微博基本信息展示
     4 //
     5 //  Created by 孔医己 on 14-6-2.
     6 //  Copyright (c) 2014年 itcast. All rights reserved.
     7 //
     8 
     9 #import "YYweiboModel.h"
    10 
    11 @implementation YYweiboModel
    12 
    13 -(instancetype)initWithDict:(NSDictionary *)dict
    14 {
    15     if (self = [super init]) {
    16         //使用KVC
    17         [self setValuesForKeysWithDictionary:dict];
    18     }
    19     return self;
    20 }
    21 
    22 /**
    23  *  工厂方法
    24  *
    25  *  @param dict 字典
    26  *
    27  *  @return 模型
    28  */
    29 +(instancetype)weiboModelWithDict:(NSDictionary *)dict
    30 {
    31     return [[self alloc]initWithDict:dict];
    32 }
    33 @end

    视图部分:

    YYweiboCell.h文件

     1 //
     2 //  YYweiboCell.h
     3 //  微博基本信息展示
     4 //
     5 //  Created by 孔医己 on 14-6-2.
     6 //  Copyright (c) 2014年 itcast. All rights reserved.
     7 //
     8 
     9 #import <UIKit/UIKit.h>
    10 
    11 @class YYweiboModel;
    12 @interface YYweiboCell : UITableViewCell
    13 
    14 
    15 @property(nonatomic,strong)YYweiboModel *weibo;
    16 @end

    YYweiboCell.m文件

      1 //
      2 //  YYweiboCell.m
      3 //  微博基本信息展示
      4 //
      5 //  Created by 孔医己 on 14-6-2.
      6 //  Copyright (c) 2014年 itcast. All rights reserved.
      7 //
      8 
      9 #import "YYweiboCell.h"
     10 #import "YYweiboModel.h"
     11 
     12 #define YYNameFont [UIFont systemFontOfSize:15]
     13 #define YYTextFont [UIFont systemFontOfSize:16]
     14 
     15 @interface YYweiboCell()
     16 /**
     17  *  头像
     18  */
     19 @property(nonatomic,weak)UIImageView *iconView;
     20 /**
     21  *  vip图标
     22  */
     23 @property(nonatomic,weak)UIImageView *vipView;
     24 /**
     25  *  微博昵称
     26  */
     27 @property(nonatomic,weak)UILabel *nameLabel;
     28 /**
     29  *  配图
     30  */
     31 @property(nonatomic,weak)UIImageView *pictureView;
     32 /**
     33  *  正文
     34  */
     35 @property(nonatomic,weak)UILabel *textLab;
     36 
     37 @end
     38 
     39 @implementation YYweiboCell
     40 
     41 //重写构造方法,让自定义的cell一创建出来就有五个子控件
     42 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
     43 {
     44     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
     45     if (self) {
     46         //1.添加头像
     47         UIImageView *img=[[UIImageView alloc]init];
     48         [self.contentView addSubview:img];
     49         self.iconView=img;
     50         
     51         //2.添加昵称
     52         UILabel *namelab=[[UILabel alloc]init];
     53         //在创建昵称的时候就要告诉它,将来要用15号字体显示
     54         namelab.font=YYNameFont;
     55         [self.contentView addSubview:namelab];
     56         self.nameLabel=namelab;
     57         
     58         //3.vip
     59         UIImageView  *vipview=[[UIImageView alloc]init];
     60         vipview.image=[UIImage imageNamed:@"vip"];
     61         [self.contentView addSubview:vipview];
     62         self.vipView=vipview;
     63      
     64         //4.正文
     65         UILabel *textlab=[[UILabel alloc]init];
     66         //在创建正文的时候就要告诉它,将来要用16号字体显示
     67         textlab.font=YYTextFont;
     68         //设置正文在进行显示的时候进行换行
     69         textlab.numberOfLines=0;
     70         [self.contentView addSubview:textlab];
     71         self.textLab=textlab;
     72         
     73         //5.图片
     74         UIImageView *picture=[[UIImageView alloc]init];
     75         [self.contentView addSubview:picture];
     76         self.pictureView=picture;
     77     }
     78     return self;
     79 }
     80 
     81 /**
     82  *  重写set方法
     83  *
     84  *  @param weibo 微博
     85  */
     86 -(void)setWeibo:(YYweiboModel *)weibo
     87 {
     88     //不要忘了,记录传递进来的模型
     89     _weibo=weibo;
     90     //给子控件赋值数据
     91     [self settingData];
     92     //设置子控件的frame
     93     [self settingFrame];
     94 }
     95 
     96 /**
     97  *  对子控件的数据进行设置
     98  */
     99 -(void)settingData
    100 {
    101     //1.设置头像的数据
    102     self.iconView.image=[UIImage imageNamed:_weibo.icon];
    103     
    104     //2.设置vip图标的数据
    105     //判断是否是vip,如果是那么就显示图标,并把字体设置为红色
    106     //注意这里的判断
    107     if (_weibo.vip) {
    108         self.vipView.hidden=NO;
    109 //        [self.textLab setTintColor:[UIColor redColor]];
    110         self.nameLabel.textColor=[UIColor redColor];
    111     }else
    112     {
    113         self.vipView.hidden=YES;
    114         self.nameLabel.textColor=[UIColor blackColor];
    115     }
    116 
    117     
    118     //所以的vip图标都是一样的,没有必要每次都设置,只需要在构造方法中设置一次就可以了。
    119    // self.vipView.image=[UIImage imageNamed:@"vip"];
    120     
    121     //3.设置正文内容的数据
    122     self.textLab.text=_weibo.text;
    123     
    124     //4.设置配图的数据
    125     self.pictureView.image=[UIImage imageNamed:_weibo.picture];
    126     
    127     //5.设置微博昵称数据
    128     self.nameLabel.text=_weibo.name;
    129 }
    130 
    131 
    132 /**
    133  *  设置子控件的Frame
    134  */
    135 -(void)settingFrame
    136 {
    137     //1.设置头像的frame
    138     CGFloat padding=10;
    139     CGFloat iconViewX=padding;
    140     CGFloat iconViewY=padding;
    141     CGFloat iconViewW=30;
    142     CGFloat iconViewH=30;
    143     
    144     self.iconView.frame=CGRectMake(iconViewX, iconViewY, iconViewW, iconViewH);
    145     
    146     //2.设置微博昵称的frame
    147     //昵称的X值=头像的最大的x值+padding
    148     CGFloat nameLabelX=CGRectGetMaxX(self.iconView.frame)+padding;
    149     CGSize nameSize=[self sizeWithString:_weibo.name font:YYNameFont maxSize:CGSizeMake(MAXFLOAT,MAXFLOAT)];
    150     //昵称的Y值=(头像高度-整个文本字体的高度)*0.5+头像的Y值
    151     CGFloat nameLableY=(iconViewH-nameSize.height)*0.5+iconViewY;
    152     self.nameLabel.frame=CGRectMake(nameLabelX, nameLableY, nameSize.width, nameSize.height);
    153     
    154     //3.设置vip图标的frame
    155     //vip图标的x值=昵称的最大x值+间隙
    156     CGFloat vipX=CGRectGetMaxX(self.nameLabel.frame)+padding;
    157     CGFloat vipY=nameLableY;
    158     CGFloat vipW=14;
    159     CGFloat vipH=14;
    160     self.vipView.frame=CGRectMake(vipX, vipY, vipW, vipH);
    161     
    162     //4.设置正文的frame
    163     CGFloat textLabX=iconViewX;
    164     CGFloat textLabY=CGRectGetMaxY(self.iconView.frame)+padding;
    165     CGSize textSize=[self sizeWithString:_weibo.text font:YYTextFont maxSize:CGSizeMake(300,MAXFLOAT)];
    166     self.textLab.frame=CGRectMake(textLabX, textLabY, textSize.width, textSize.height);
    167     
    168     //5.设置配图的frame
    169     if (_weibo.picture) {
    170         CGFloat pictureX=iconViewX;
    171         CGFloat pictureY=CGRectGetMaxY(self.textLab.frame)+padding;
    172         CGFloat pictureW=100;
    173         CGFloat pictureH=100;
    174         self.pictureView.frame=CGRectMake(pictureX, pictureY, pictureW, pictureH);
    175     }
    176    
    177 #warning 未完成
    178 }
    179 
    180 
    181 /**
    182  *  计算文本的宽高
    183  *
    184  *  @param str     需要计算的文本
    185  *  @param font    文本显示的字体
    186  *  @param maxSize 文本显示的范围
    187  *
    188  *  @return 文本占用的真实宽高
    189  */
    190 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
    191 {
    192     NSDictionary *dict = @{NSFontAttributeName : font};
    193     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
    194     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
    195     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
    196     return size;
    197 }
    198 @end

    主控制器部分:

    YYViewController.m文件

     1 //
     2 //  YYViewController.m
     3 //  微博基本信息展示
     4 //
     5 //  Created by 孔医己 on 14-6-2.
     6 //  Copyright (c) 2014年 itcast. All rights reserved.
     7 //
     8 
     9 #import "YYViewController.h"
    10 #import "YYweiboModel.h"
    11 #import "YYweiboCell.h"
    12 
    13 @interface YYViewController ()
    14 @property(nonatomic,strong)NSArray *weibos;
    15 
    16 @end
    17 
    18 @implementation YYViewController
    19 
    20 - (void)viewDidLoad
    21 {
    22     [super viewDidLoad];
    23 }
    24 
    25 #pragma mark -懒加载
    26 -(NSArray *)weibos
    27 {
    28     if (_weibos==Nil) {
    29         NSString *fullpath=[[NSBundle mainBundle]pathForResource:@"statuses.plist" ofType:nil];
    30         NSArray *arrayM=[NSArray arrayWithContentsOfFile:fullpath];
    31         
    32         NSMutableArray *models=[NSMutableArray arrayWithCapacity:arrayM.count];
    33         for (NSDictionary *dict in arrayM) {
    34             YYweiboModel *weibomodel=[YYweiboModel weiboModelWithDict:dict];
    35             [models addObject:weibomodel];
    36         }
    37         _weibos=[models copy];
    38     }
    39     return _weibos;
    40 }
    41 
    42 #pragma mark- 数据源方法
    43 //返回多少组
    44 //这里可以不写,默认返回一组
    45 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    46 {
    47     return 1;
    48 }
    49 //每组多少行
    50 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    51 {
    52     return self.weibos.count;
    53 }
    54 //每组每行的数据-设置cell
    55 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    56 {
    57     //1.到缓存中去取cell
    58     static NSString *ID=@"ID";
    59      //2.没有则创建cell
    60     YYweiboCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    61     if (cell==nil) {
    62         cell=[[YYweiboCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    63     }
    64    
    65     //3.设置cell的数据
    66     cell.weibo=self.weibos[indexPath.row];
    67     //4.返回cell
    68     return cell;
    69     
    70 }
    71 
    72 #pragma mark-设置每一组的高度
    73 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    74 {
    75     //这里暂时给出一个高度,以后会做进一步的处理
    76     return 200;
    77 }
    78 #pragma mark- 隐藏状态栏
    79 -(BOOL)prefersStatusBarHidden
    80 {
    81     return YES;
    82 }
    83 @end

    三、实现思路整理

    设置frame时的思路和一些注意点:

    (1)

    一个控件没有frame肯定显示不出来

    设置frame的过程中需要从哪里入手呢?以后遇到要为很多控件设置frmae的时候。建议先找控件之间的关系,先找准一个固定不变的点,然后再计算不确定的控件的frmae.总要有一个点,再来计算其他的东西。

    在这个应用中找到规律,先设置头像的,再设置其他的。

    在真实开发中间隙等是由美工提供的。计算x,y,w,h等得值。分别计算所有控件的frame,注意这是依赖于数据的。

    (2)

    获取控件的最大值CGRectMaxX(SELF.ICONvIEW.FRAME)或取头像最大的x值。

    在ios7中计算文字的宽度和高度?

    需要传递一个字体。 影响文本的宽度和高度的因素:(1)字体的大小;(2)存放文本的最大的范围。 在计算文本的宽高时,应该告诉这两个。

    _weibo.name sizewithFont:nil    ios7以前的方法

    ios7以后要传4个参数

    boundingRectWthSize:(cgsize).....将来能够显示文本的范围,宽和高 。

    nsdictionary  *dict=@{NSfontattributename:宏}

    在创建昵称的时候就要告诉它,将来以15号的字体显示。(注意不要忘了这一点,否则计算出来的不准确)

    不限制其宽度和高度的大小:MAXFLOAT

    计算文本的宽高,把这个功能封装。接受三个参数,字符串,字体,Maxsize.返回值为CGSIZE.

    需要计算的文本
    文本显示的字体
    文本显示的范围

    文本占用的真实宽高。

    注意: 有关字体的计算,在创建的时候就要指定其将要显示的字号是多大。

    内容文本的宽高和昵称不一样,正文会换行,那么就限制一下其宽度,不限制高度就可以了。

    cell的高度不够,需要在viewdioad中设置cell的高度 (大失所望)

    默认label只显示一行。当创建正文的时候,还要设置让其自定换行。设置为0

     (3)

    如果没有配图的话就不计算它的宽高,把计算的过程放到if大括号里边。

    设置配图的问题:有的又配图,有的没有配图(cell滚动离开视野放到缓存池中)。问题在于,如果需要一个没有配图的,这时候去缓存中去取,取到的是一个有配图的那不是就冲突了么?

    如何解决这个问题:

    在设置数据的时候进行判断,如果有配图,那么就设置数据,.hidden=no;

    如果没有配图的话那就不让它显示。hidden=YES.

    注意点: 在tableview中有一个复用的问题,有显示就要有隐藏。这是一个陷阱。一定要记住。

     (4)

    所有的vip图标都是同一个,可以在init初始化方法中对vip图标进行设置。

    此时出现了一个新的问题。所有的宽高计算一次就可以了,但是这里每次滚动都会调用计算,没有必要。

    四、重要说明

    IOS7以后计算文本的宽度和高度:

         //4. 设置正文的 frame

        CGFloat textLabX=iconViewX;

        CGFloat textLabY= CGRectGetMaxY ( self . iconView . frame )+padding;

        CGSize textSize=[self sizeWithString:_weibo.text font:YYTextFont maxSize:CGSizeMake(300,MAXFLOAT)];

        self . textLab . frame = CGRectMake (textLabX, textLabY, textSize. width , textSize. height );

        这里把计算过程封装在了下面的方法中:

    /**
     *  计算文本的宽高
     *
     *  @param str     需要计算的文本
     *  @param font    文本显示的字体
     *  @param maxSize 文本显示的范围
     *
     *  @return 文本占用的真实宽高
     */
    - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
    {
        NSDictionary *dict = @{NSFontAttributeName : font};
        // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
        // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
        CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
        return size;
    }
  • 相关阅读:
    Java图片裁剪
    jvm参数
    Druid数据源监控配置
    执行jar包或执行其中的某个类
    十进制和二进制之间的相互转化
    Java位运算
    获取网络资源保存本地
    前端PHP入门-010-内部函数
    前端PHP入门-011-可变函数
    前端PHP入门-009-匿名函数
  • 原文地址:https://www.cnblogs.com/iosblogx/p/4474162.html
Copyright © 2020-2023  润新知