iOS UI基础-9.2 UITableView 简单微博列表

概述

我们要实现的效果:

这个界面布局也是UITableView实现的,其中的内容就是UITableViewCell,只是这个UITableViewCell是用户自定义实现的。虽然系统自带的UITableViewCell已经够强大了,但是这个界面布局并不能满足我们的需求。

在上面的cell布局里,我们可以知道,每个cell的高度都是不固定的。因此,我们通过代码来自定义cell.

代码自定义cell

步骤:

1.新建一个继承自UITableViewCell的类

2.重写initWithStyle:reuseIdentifier:方法

  • 添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中)
  • 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)

3.提供2个模型

  • 数据模型: 存放文字数据\图片数据
  • frame模型: 存放数据模型\所有子控件的frame\cell的高度

4.重写frame模型里的数据模型的Setter方法:在这个方法中,设置子控制的frame和每个cell高度

5.cell拥有一个frame模型(不要直接拥有数据模型)

6.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame

7.frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)

下面分步来写相应的代码

Cell视图设置

1.新建一个继承自UITableViewCell的类,重写initWithStyle:reuseIdentifier:方法

2.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame

StatusCell.h

#import <UIKit/UIKit.h>
@class StatusFrame;

@interface StatusCell : UITableViewCell
@property (nonatomic, strong) StatusFrame *statusFrame;

+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end

StatusCell.m

//
//  StatusCell.m
//  9.2 - 简单微博
//
//  Created by apple on 15/9/18.
//  Copyright (c) 2015年 weconex. All rights reserved.
//

// 昵称的字体
#define MJNameFont [UIFont systemFontOfSize:14]
// 正文的字体
#define MJTextFont [UIFont systemFontOfSize:15]

#import "StatusCell.h"
#import "Status.h"
#import "StatusFrame.h"

@interface StatusCell()
/**
 *  头像
 */
@property (nonatomic, weak) UIImageView *iconView;
/**
 *  昵称
 */
@property (nonatomic, weak) UILabel *nameView;
/**
 *  会员图标
 */
@property (nonatomic, weak) UIImageView *vipView;
/**
 *  正文
 */
@property (nonatomic, weak) UILabel *textView;
/**
 *  配图
 */
@property (nonatomic, weak) UIImageView *pictureView;
@end

@implementation StatusCell

/**
 *  重写initWithStyle:reuseIdentifier:方法
 *  添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中)
 *  进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
 */
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self==[super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        // 1.头像
        UIImageView *iconView = [[UIImageView alloc] init];
        [self.contentView addSubview:iconView];
        self.iconView = iconView;//相当于xib的拉线

        // 2.昵称
        UILabel *nameView = [[UILabel alloc] init];
        nameView.font = MJNameFont;
        [self.contentView addSubview:nameView];
        self.nameView = nameView;

        // 3.会员图标
        UIImageView *vipView = [[UIImageView alloc] init];
        vipView.image = [UIImage imageNamed:@"vip"];
        [self.contentView addSubview:vipView];
        self.vipView = vipView;

        // 4.正文
        UILabel *textView = [[UILabel alloc] init];
        textView.numberOfLines = 0;
        textView.font = MJTextFont;
        [self.contentView addSubview:textView];
        self.textView = textView;

        // 5.配图
        UIImageView *pictureView = [[UIImageView alloc] init];
        [self.contentView addSubview:pictureView];
        self.pictureView = pictureView;
    }
    return self;
}

/**
 *  在这个方法中设置子控件的frame和显示数据
 */
-(void)setStatusFrame:(StatusFrame *)statusFrame
{
    _statusFrame = statusFrame;

    // 1.设置数据
    [self settingData];

    // 2.设置frame
    [self settingFrame];
}

/**
 *  设置数据
 */
- (void)settingData
{
    // 微博数据
    Status *status = self.statusFrame.status;

    // 1.头像
    self.iconView.image = [UIImage imageNamed:status.icon];

    // 2.昵称
    self.nameView.text = status.name;

    // 3.会员图标
    if (status.vip) {
        self.vipView.hidden = NO;

        self.nameView.textColor = [UIColor redColor];
    } else {
        self.vipView.hidden = YES;

        self.nameView.textColor = [UIColor blackColor];
    }

    // 4.正文
    self.textView.text = status.text;

    // 5.配图
    if (status.picture) { // 有配图
        self.pictureView.hidden = NO;
        self.pictureView.image = [UIImage imageNamed:status.picture];
    } else { // 没有配图
        self.pictureView.hidden = YES;
    }
}

/**
 *  设置frame
 */
- (void)settingFrame
{
    // 1.头像
    self.iconView.frame = self.statusFrame.iconF;

    // 2.昵称
    self.nameView.frame = self.statusFrame.nameF;

    // 3.会员图标
    self.vipView.frame = self.statusFrame.vipF;

    // 4.正文
    self.textView.frame = self.statusFrame.textF;

    // 5.配图
    if (self.statusFrame.status.picture) {// 有配图
        self.pictureView.frame = self.statusFrame.pictureF;
    }
}

+ (instancetype)cellWithTableView:(UITableView *)tableView
{
    static NSString *ID = @"status";
    StatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        cell = [[StatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

@end

模型定义

提供2个模型

  • 数据模型(Status): 存放文字数据\图片数据
  • frame模型(StatusFrame): 存放数据模型\所有子控件的frame\cell的高度

重写frame模型里的数据模型(Status)的Setter方法:在这个方法中,设置子控制的frame和每个cell高度

Status.h

//
//  Status.h
//  9.2 - 简单微博
//
//  Created by apple on 15/9/18.
//  Copyright (c) 2015年 weconex. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface Status : UICollectionViewCell
@property (nonatomic, copy) NSString *text; // 内容
@property (nonatomic, copy) NSString *icon; // 头像
@property (nonatomic, copy) NSString *name; // 昵称
@property (nonatomic, copy) NSString *picture; // 配图
@property (nonatomic, assign) BOOL vip;

- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)statusWithDict:(NSDictionary *)dict;
@end

Status.m

//
//  Status.m
//  9.2 - 简单微博
//
//  Created by apple on 15/9/18.
//  Copyright (c) 2015年 weconex. All rights reserved.
//

#import "Status.h"

@implementation Status

- (instancetype)initWithDict:(NSDictionary *)dict
{
    if (self = [super init]) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

+ (instancetype)statusWithDict:(NSDictionary *)dict
{
    return [[self alloc] initWithDict:dict];
}
@end

StatusFrame.h

//
//  StatusFrame.h
//  9.2 - 简单微博
//
//  Created by apple on 15/9/18.
//  Copyright (c) 2015年 weconex. All rights reserved.
//  frame模型: 存放数据模型\所有子控件的frame\cell的高度

#import <UIKit/UIKit.h>
@class Status;

@interface StatusFrame : UITableViewCell

/**
 *  头像的frame
 */
@property (nonatomic, assign, readonly) CGRect iconF;
/**
 *  昵称的frame
 */
@property (nonatomic, assign, readonly) CGRect nameF;
/**
 *  会员图标的frame
 */
@property (nonatomic, assign, readonly) CGRect vipF;
/**
 *  正文的frame
 */
@property (nonatomic, assign, readonly) CGRect textF;
/**
 *  配图的frame
 */
@property (nonatomic, assign, readonly) CGRect pictureF;

/**
 *  cell的高度
 */
@property (nonatomic, assign, readonly) CGFloat cellHeight;

/**
 *  存放数据模型
 */
@property (nonatomic, strong) Status *status;

@end

StatusFrame.m

//
//  StatusFrame.m
//  9.2 - 简单微博
//
//  Created by apple on 15/9/18.
//  Copyright (c) 2015年 weconex. All rights reserved.
//
// 昵称的字体
#define MJNameFont [UIFont systemFontOfSize:14]
// 正文的字体
#define MJTextFont [UIFont systemFontOfSize:15]

#import "StatusFrame.h"
#import "Status.h"

@implementation StatusFrame

/**
 *  计算文字尺寸
 *
 *  @param text    需要计算尺寸的文字
 *  @param font    文字的字体
 *  @param maxSize 文字的最大尺寸
 */
- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
{
    NSDictionary *attrs = @{NSFontAttributeName : font};
    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}

/**
 *  设置每一条微博的Frame 及cell的高度
 *
 *  @param status 微博模型
 */
-(void)setStatus:(Status *)status
{
    _status = status;

    // 子控件之间的间距
    CGFloat padding = 10;

    // 1.头像
    CGFloat iconX = padding;
    CGFloat iconY = padding;
    CGFloat iconW = 30;
    CGFloat iconH = 30;
    _iconF = CGRectMake(iconX, iconY, iconW, iconH);

    // 2.昵称
    // 文字的字体
    CGSize nameSize = [self sizeWithText:self.status.name font:MJNameFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
    CGFloat nameX = CGRectGetMaxX(_iconF) + padding;
    CGFloat nameY = iconY + (iconH - nameSize.height) * 0.5;
    _nameF = CGRectMake(nameX, nameY, nameSize.width, nameSize.height);

    // 3.会员图标
    CGFloat vipX = CGRectGetMaxX(_nameF) + padding;
    CGFloat vipY = nameY;
    CGFloat vipW = 14;
    CGFloat vipH = 14;
    _vipF = CGRectMake(vipX, vipY, vipW, vipH);

    // 4.正文
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(_iconF) + padding;
    CGSize textSize = [self sizeWithText:self.status.text font:MJTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
    _textF = CGRectMake(textX, textY, textSize.width, textSize.height);

    // 5.配图
    if (self.status.picture) {// 有配图
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(_textF) + padding;
        CGFloat pictureW = 100;
        CGFloat pictureH = 100;
        _pictureF = CGRectMake(pictureX, pictureY, pictureW, pictureH);

        _cellHeight = CGRectGetMaxY(_pictureF) + padding;
    } else {
        _cellHeight = CGRectGetMaxY(_textF) + padding;
    }
}
@end

控制器使用Cell

cell拥有一个frame模型(不要直接拥有数据模型)

frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)

ViewController.m

//
//  ViewController.m
//  9.2 - 简单微博
//
//  Created by apple on 15/9/18.
//  Copyright (c) 2015年 weconex. All rights reserved.
//

#import "ViewController.h"
#import "StatusFrame.h"
#import "Status.h"
#import "StatusCell.h"

@interface ViewController ()
/**
 *  存放所有cell的frame模型数据
 */
@property (nonatomic, strong) NSArray *statusFrames;
@end

@implementation ViewController

-(NSArray *)statusFrames
{
    if (_statusFrames==nil) {
        // 初始化
        // 1.获得plist的全路径
        NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];

        // 2.加载数组
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];

        // 3.将dictArray里面的所有字典转成模型对象,放到新的数组中
        NSMutableArray *statusFrameArray = [NSMutableArray array];
        for (NSDictionary *dict in dictArray) {
            // 3.1.创建Status模型对象
            Status *status = [Status statusWithDict:dict];

            // 3.2.创建StatusFrame模型对象
            StatusFrame *statusFrame = [[StatusFrame alloc] init];
            statusFrame.status = status;

            // 3.2.添加模型对象到数组中
            [statusFrameArray addObject:statusFrame];
        }

        // 4.赋值
        _statusFrames = statusFrameArray;
    }

    return _statusFrames;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

// 隐藏导航栏
- (BOOL)prefersStatusBarHidden
{
    return YES;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.statusFrames.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.创建cell
    StatusCell *cell = [StatusCell cellWithTableView:tableView];

    // 2.在这个方法算好了cell的高度
    cell.statusFrame = self.statusFrames[indexPath.row];

    // 3.返回cell
    return cell;
}

/**
 *  返回每个单元格的高度
 */
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    StatusFrame *statusFrame=self.statusFrames[indexPath.row];
    return statusFrame.cellHeight;
}

@end

请按照步骤来,当然,上面的代码有一些步骤是混合在一起了。

源码下载:点击下载

时间: 2024-10-13 10:59:47

iOS UI基础-9.2 UITableView 简单微博列表的相关文章

iOS UI基础-9.0 UITableView基础

在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView.UITableView继承自UIScrollView,因此支持垂直滚动,而且性能极佳. UITableView有两种样式: 一列显示:UITableViewStylePlain 分组显示:UITableViewStyleGrouped tableView展示数据的过程 1.调用数据源的下面方法得知一共有多少组数据 - (NSInteger)numberOfSectionsInTableView:(UITableView

iOS UI基础-9.1 UITableView 团购

概述 接下来,我们要做的是团购界面的设计,最张要实现的效果图及项目结构图      团购数据的展示 思路: 系统自带的tableCell不能展示三个文本,不能满足条件,自定义tableCell 每一个tableCell样式固定不变,使用xib来实现. 数据来源通过加载plist文件 定义展示数据模型 Tuangou.h // // Tuangou.h // 9.1团购 // // Created by jiangys on 15/9/16. // Copyright (c) 2015年 uxia

iOS开发——UI篇OC篇&amp;UITableView简单封装

UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也提到了,在后面的文章中将会详细解释. 当然这篇文档并不是介绍证明去使用它,只是说说怎么去封装活着更好的使用. 这里主要是关于UItableView中Cell中的多功能实现 一:新建一个模型数据,用于Cell的实现 1 /** 2 * 覆盖系统的枚举 3 */ 4 typedef enum { 5 C

IOS SWIFT UITableView 实现简单微博列表

// // Weibo.swift // UITableViewCellExample // // Created by XUYAN on 15/8/15. // Copyright (c) 2015年 com.world. All rights reserved. // import Foundation class Weibo { //属性 var id : UInt32 var img : String! var username : String! var mbtype : String

iOS UI控件7(UITableView)

1.表格(UITableView)与表格控制器(UITableViewController) UITableView是iOS开发中常见的UI控件,本质是一个列表(单列的表格).UITableView允许自由控制行的控件,包括在表格行中添加多个字控件.UITableView继承了UIScrollView,具有UIScrollView的功能,这个UIScrollView主要封装了UITableViewCell单元格控件,因此UITableView默认可以对单元格进行滚动.默认情况下,所有UITabl

IOS UI基础07

TableView 属性 // 设置每一行cell的高度 @property (nonatomic)CGFloat rowHeight; // 设置每一组头部的高度 @property (nonatomic)CGFloat sectionHeaderHeight; // 设置分割线颜色 @property (nonatomic, retain) UIColor *separatorColor // 设置表头控件 @property (nonatomic, retain) UIView *tabl

iOS UI基础-7.0 UIScrollView

概述 移动设备的屏幕大小是极其有限的,因此直接展示在用户眼前的内容也相当有限.当展示的内容较多,超出一个屏幕时,用户可通过滚动手势来查看屏幕以外的内容,普通的UIView不具备滚动功能,不能显示过多的内容.UIScrollView是一个能够滚动的视图控件,可以用来展示大量的内容,并且可以通过滚动查看所有的内容 UIScrollView的常见属性 UIScrollView的常用代理方法 UIScrollView的缩放 UIScrollView使用 基本使用 UIScrollView的用法很简单,将

IOS UI基础08

自定义等高cell // 创建自定义cell添加子控件的方法initWithStyle(note:子控件要添加到contentView上) - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier NS_AVAILABLE_IOS(3_0); // 传统创建自定义view添加子空间的方法 //- (instancetype)initWithFrame:

iOS UI基础-17.0 UILable之NSMutableAttributedString

在iOS开发中,常常会有一段文字显示不同的颜色和字体,或者给某几个文字加删除线或下划线的需求.之前在网上找了一些资料,有的是重绘UILabel的textLayer,有的是用html5实现的,都比较麻烦,而且很多UILabel的属性也不起作用了,效果都不理想.后来了解到NSMuttableAttstring(带属性的字符串),上面的一些需求都可以很简便的实现. NSMuttableAttstring 方法 为某一范围内文字设置多个属性 - (void)setAttributes:(NSDictio