zoukankan      html  css  js  c++  java
  • 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);

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

     1 /**
     2  *  计算文本的宽高
     3  *
     4  *  @param str     需要计算的文本
     5  *  @param font    文本显示的字体
     6  *  @param maxSize 文本显示的范围
     7  *
     8  *  @return 文本占用的真实宽高
     9  */
    10 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
    11 {
    12     NSDictionary *dict = @{NSFontAttributeName : font};
    13     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
    14     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
    15     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
    16     return size;
    17 }
  • 相关阅读:
    Leetcode Binary Tree Level Order Traversal
    Leetcode Symmetric Tree
    Leetcode Same Tree
    Leetcode Unique Paths
    Leetcode Populating Next Right Pointers in Each Node
    Leetcode Maximum Depth of Binary Tree
    Leetcode Minimum Path Sum
    Leetcode Merge Two Sorted Lists
    Leetcode Climbing Stairs
    Leetcode Triangle
  • 原文地址:https://www.cnblogs.com/dondre/p/4093317.html
Copyright © 2011-2022 走看看