1、效果展示
2、更新内容
2.1 优化配图显示方式,在Gif图片下方增加Gif图标;
2.2 优化微博显示方式:调节每条微博的边距,修改微博背景颜色;
2.3 增加微博功能菜单栏,每次微博下方添加三个按钮;
3、设计说明
3.1 设计配图处理类SAImageView,判断当前是否为Gif图片,Gif图片展示时在图片右下角增加一个Gif图标,即在原有的UIImageView上添加一个UIImageView
3.2. 修改SAStatusCell类,优化Cell展示方式
3.2.1 设置backgroundView,并拉伸图片
3.2.2 重写SAStatusCell的setFrame方法,缩小Cell的大小,留出边距
3.2.3 修改框架模型SAStatusFrame类,调整Cell中相关受影响的元素Frame值,并将Cell高度增加一个功能菜单栏的高度
3.3 设计一个SAStatusDock类,用来展示Cell的功能菜单栏
3.3.1 SAStatusDock初始化时设置尺寸位置,并设置autoresizingMask属性为UIViewAutoresizingFlexibleTopMargin,实现自动伸缩,使菜单栏永远在Cell的底部
3.3.2 设置三个按钮并设置按钮的尺寸文字图标,将按钮添加到功能菜单栏
3.3.3 微调美化
3.4 整体微调美化
4、关键代码
SACommon.h
[Objective-C] 纯文本查看 复制代码 //
// SACommon.h
// SianWeibo
//
// Created by yusian on 14-4-10.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
// 公共头文件
#ifndef __SACOMMON_H__
#define __SACOMMON_H__
// 判断是否为iphone5的宏
#define isIPhone5 ([UIScreen mainScreen].bounds.size.height == 568)
// 用MyLog替代NSLog,调试时输出日志,正式发布时自动取消日志输出代码
#ifdef DEBUG
#define MyLog(...) NSLog(__VA_ARGS__)
#else
#define MyLog(...)
#endif
// SAOAuthController:OAuth认证
#define kOAuthURL [kBaseURL stringByAppendingString:@"oauth2/authorize"] // 新浪OAuth认证URL
#define kAppKey @"660705995" // 开发者帐号AppKey
#define kAppSecret @"38d9d1d644844050dbb2703cb6bc6db6" // 开发者帐号AppSecret
#define kClient_id @"660705995" // 新浪OAuth认证ClientID
#define kRedirect_uri @"http://www.yusian.com" // 新浪OAuth认证回调页面
#define kBaseURL @"https://api.weibo.com/" // 新浪OAuth认证域名
// SAStatusFrame:微博Frame设置
#define kInterval 10 // 微博元素基本边距
#define kProfileWH 34 // 用户头像尺寸
#define kScreenNameFount [UIFont systemFontOfSize:15] // 用户昵称字号
#define kMBIconWH 12 // 会员图标尺寸
#define kTimeFont [UIFont systemFontOfSize:10] // 发表时间字号
#define kSourceFont kTimeFont // 微博来源字号
#define kTextFount [UIFont systemFontOfSize:15] // 微博正文字号
#define kReScreenNameFont [UIFont systemFontOfSize:14] // 转发微博体昵称字号
#define kReTextFont kReScreenNameFont // 转发微博体正文字号
// SAAvata:微博头像处理
#define kAvataSmallW 34 // 用户小头像尺寸宽度
#define kAvataSmallH kAvataSmallW // 用户小头像尺寸高度
#define kAvataDefaultW 50 // 用户中头像尺寸宽度
#define kAvataDefaultH kAvataDefaultW // 用户中头像尺寸高度
#define kAvataBigW 85 // 用户大头像尺寸宽度
#define kAvataBigH kAvataBigW // 用户大头像尺寸高度
#define kVerifiedW 18 // 用户类型图标尺寸宽度
#define kVerifiedH kVerifiedW // 用户类型图标尺寸高度
// SAStatusCell:会员昵称颜色设置
#define kColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define kBGColor kColor(239, 239, 244) // 全局背景颜色
#define kMBScreenNameColor kColor(240, 100, 20) // 会员用户昵称颜色
#define kScreenNameColor kColor(0, 0, 0) // 普通用户昵称颜色
#define kTimeColor kColor(200, 100, 30) // 微博发表时间显示颜色
#define kCellMargins (kInterval * 0.5) // 单元格两边边距
//#define kCellInterval kInterval // 单元格相互之间间隔
// SAImageListView 配图处理相关
#define kImageCount 9 // 微博配图最大配图数
#define kImageInterval 5 // 微博配图间隔
#define kStatusImageOneWH 100 // 一张配图尺寸
#define kStatusImageMuWH 80 // 多總配图尺寸
// SAStatusDock 功能菜单栏
#define kCellDefaultHeight 44 // TableViewCell默认高度
#define kStatusDockHeight 35 // 功能菜单栏高度
#endif // __SACOMMON_H__
SAImageView.h
[Objective-C] 纯文本查看 复制代码 //
// SAImageView.h
// SianWeibo
//
// Created by yusian on 14-4-20.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAImageView : UIImageView
@property (nonatomic, copy) NSString *picUrl;
@end
SAImageView.m
[Objective-C] 纯文本查看 复制代码 //
// SAImageView.m
// SianWeibo
//
// Created by yusian on 14-4-20.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAImageView.h"
#import "SAStatusTool.h"
@interface SAImageView()
{
UIImageView *_gifView;
}
@end
@implementation SAImageView
#pragma mark 初始化View,将gif图标附加到该View上
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_gifView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"timeline_image_gif.png"]];
[self addSubview:_gifView];
}
return self;
}
#pragma mark 设置图片url
-(void)setPicUrl:(NSString *)picUrl
{
_picUrl = picUrl;
[SAStatusTool statusToolInsteadView:self setImageWithURLString:picUrl placeholderImage:[UIImage imageNamed:@"timeline_image_loading.png"]];
// 在设置图片url同时判断该图是否为GIF图片,如果是则显示Gif图标
_gifView.hidden = ![picUrl.lowercaseString hasSuffix:@".gif"];
}
#pragma mark 重写setFrame方法
-(void)setFrame:(CGRect)frame
{
[super setFrame:frame];
// 设置图片Frame的时候将Gif图标的Frame设置好
CGSize gifViewSize = _gifView.frame.size;
_gifView.frame = CGRectMake(frame.size.width - gifViewSize.width, frame.size.height - gifViewSize.height, gifViewSize.width, gifViewSize.height);
}
@end
SAStatusDock.h
[Objective-C] 纯文本查看 复制代码 //
// SAStatusDock.h
// SianWeibo
//
// Created by yusian on 14-4-20.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
// 微博Dock
#import <UIKit/UIKit.h>
@interface SAStatusDock : UIImageView
@end
SAStatusDock.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatusDock.m
// SianWeibo
//
// Created by yusian on 14-4-20.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
// 微博Dock
#import "SAStatusDock.h"
#import "UIImage+SA.h"
#import "NSString+SA.h"
@interface SAStatusDock ()
{
UIButton *_left;
UIButton *_middle;
UIButton *_right;
}
@end
@implementation SAStatusDock
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 设置Dock的尺寸位置
CGFloat dockWidth = [UIScreen mainScreen].bounds.size.width - 2 * kCellMargins;
self.frame = CGRectMake(0, kCellDefaultHeight - kCellMargins - kStatusDockHeight, dockWidth, kStatusDockHeight);
// Dock贴紧父控件底部,即保持在Cell底部
self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
// 接受用户交互
self.userInteractionEnabled = YES;
// 添加3个按钮
[self addButtonWithTitle:@"转发" andImage:@"timeline_icon_comment.png" backgroundImage:@"timeline_card_leftbottom.png" buttonIndex:0];
[self addButtonWithTitle:@"评论" andImage:@"timeline_icon_retweet.png" backgroundImage:@"timeline_card_middlebottom.png" buttonIndex:1];
[self addButtonWithTitle:@"赞" andImage:@"timeline_icon_unlike.png" backgroundImage:@"timeline_card_rightbottom.png" buttonIndex:2];
}
return self;
}
#pragma mark 添加功能菜单栏按钮
- (void)addButtonWithTitle:(NSString *)title andImage:(NSString *)imageName backgroundImage:(NSString *)backgroundImageName buttonIndex:(NSInteger)index
{
// 按钮基本属性设置
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:title forState:UIControlStateNormal]; // 设置文字
[button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; // 文字颜色
button.titleLabel.font = [UIFont systemFontOfSize:12]; // 文字大小
[button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; // 按钮图标
button.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); // 图文间距
// 按钮背景图片
[button setBackgroundImage:[UIImage resizeImage:backgroundImageName] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage resizeImage:[backgroundImageName fileAppend:@"_highlight"]] forState:UIControlStateHighlighted];
// 按钮尺寸位置
CGFloat buttonWidth = self.frame.size.width / 3;
button.frame = CGRectMake(index * buttonWidth, 0, buttonWidth, kStatusDockHeight);
// 添加按钮间间隔图片
if (index) {
UIImageView *cardButton = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"timeline_card_bottom_line.png"]];
[self addSubview:cardButton];
cardButton.center = CGPointMake(button.frame.origin.x, kStatusDockHeight * 0.5);
}
[self addSubview:button];
}
@end
SAStatusCell.h
[Objective-C] 纯文本查看 复制代码 //
// SAStatusCell.h
// SianWeibo
//
// Created by yusian on 14-4-18.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
// 微博单元格类
#import <UIKit/UIKit.h>
#import "SAStatusFrame.h"
@interface SAStatusCell : UITableViewCell
@property (nonatomic, strong) SAStatusFrame *statusFrame;
+ (NSString *)ID;
@end
SAStatusCell.m
[Objective-C] 纯文本查看 复制代码 //
// SAStatusCell.m
// SianWeibo
//
// Created by yusian on 14-4-18.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
// 微博单元格类
#import "SAStatusCell.h"
#import "SAAvata.h"
#import "SAImageListView.h"
#import "SAStatusDock.h"
@interface SAStatusCell ()
{
SAAvata *_profile; // 头像
UILabel *_screenName; // 昵称
UIImageView *_mbIcon; // 会员图标
UILabel *_time; // 时间
UILabel *_source; // 来源
UILabel *_text; // 正文
SAImageListView *_image; // 配图
UIImageView *_retweet; // 转发体视图
UILabel *_reScreenName; // 转发体昵称
UILabel *_reText; // 转发体正文
SAImageListView *_reImage; // 转发体配图
SAStatusDock *_statusDock; // 功能菜单
}
@end
@implementation SAStatusCell
#pragma mark 初始化单元格元素
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.backgroundView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"common_card_background.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5]];
self.selectedBackgroundView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"common_card_background_highlighted.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5]];
// 1、头像
_profile = [[SAAvata alloc] init];
_profile.backgroundColor = [UIColor clearColor];
[self.contentView addSubview:_profile];
// 2、昵称
_screenName = [[UILabel alloc] init];
_screenName.backgroundColor = [UIColor clearColor];
_screenName.font = kScreenNameFount;
[self.contentView addSubview:_screenName];
// 2.1 会员图标
_mbIcon = [[UIImageView alloc] init];
_mbIcon.image = [UIImage imageNamed:@"common_icon_membership.png"];
[self.contentView addSubview:_mbIcon];
// 3、时间
_time = [[UILabel alloc] init];
_time.backgroundColor = [UIColor clearColor];
_time.font = kTimeFont;
_time.textColor = kTimeColor;
[self.contentView addSubview:_time];
// 4、来源
_source = [[UILabel alloc] init];
_source.backgroundColor = [UIColor clearColor];
_source.font = kSourceFont;
_source.textColor = [UIColor grayColor];
[self.contentView addSubview:_source];
// 5、正文
_text = [[UILabel alloc] init];
_text.backgroundColor = [UIColor clearColor];
_text.font = kTextFount;
_text.numberOfLines = 0;
[self.contentView addSubview:_text];
// 6、配图
_image = [[SAImageListView alloc] init];
_image.contentMode = UIViewContentModeScaleAspectFit;
[self.contentView addSubview:_image];
// 7、转发体视图
_retweet = [[UIImageView alloc] init];
_retweet.image = [[UIImage imageNamed:@"timeline_retweet_background.png"] stretchableImageWithLeftCapWidth:25 topCapHeight:10];
[self.contentView addSubview:_retweet];
// 8、转发体昵称
_reScreenName = [[UILabel alloc] init];
_reScreenName.font = kReScreenNameFont;
_reScreenName.backgroundColor = [UIColor clearColor];
_reScreenName.textColor = [UIColor blueColor];
[_retweet addSubview:_reScreenName];
// 9、转发体正文
_reText = [[UILabel alloc] init];
_reText.numberOfLines = 0;
_reText.font = kReTextFont;
_reText.backgroundColor = [UIColor clearColor];
[_retweet addSubview:_reText];
// 10、转发体配图
_reImage = [[SAImageListView alloc] init];
_reImage.contentMode = UIViewContentModeScaleAspectFit;
[_retweet addSubview:_reImage];
// 11、添加功能菜单
_statusDock = [[SAStatusDock alloc] init];
[self.contentView addSubview:_statusDock];
}
return self;
}
#pragma mark - 设置单元格
-(void)setStatusFrame:(SAStatusFrame *)statusFrame
{
_statusFrame = statusFrame;
// 1、设置子控件内容
[self statusFrameSettingView];
// 2、计算子控件Frame
[self statusFrameSettingFrame];
}
#pragma mark 设置单元格内容
- (void)statusFrameSettingView
{
SAStatus *status = self.statusFrame.status;
// 1、设置头像
[_profile setUser:status.user ofType:kAvataTypeSmall];
// 2、设置昵称
_screenName.text = status.user.screenName;
if (status.user.mbtype == kMbTypeNone) {
_screenName.textColor = kScreenNameColor;
} else {
_screenName.textColor = kMBScreenNameColor;
}
// 2.1 设置会员图标
if (status.user.mbtype == kMbTypeNone) {
_mbIcon.hidden = YES;
} else {
_mbIcon.hidden = NO;
}
// 3、设置时间
_time.text = status.createdAt;
// 4、设置来源
_source.text = status.source;
// 5、设置正文
_text.text = status.text;
// 6、设置配图
if (status.picUrls.count) { // 第一种情况:带有配图的微博
_image.hidden = NO;
_retweet.hidden = YES;
_image.imageList = status.picUrls;
} else if (status.retweetedStatus) { // 第二种情况:转发的微博
_image.hidden = YES;
_retweet.hidden = NO;
// 7、设置转发体昵称
_reScreenName.text = [NSString stringWithFormat:@"@%@", status.retweetedStatus.user.screenName];
// 8、转发体正文
_reText.text = status.retweetedStatus.text;
// 9、转发体配图
if (status.retweetedStatus.picUrls.count) { // 第二种情况:1、转发的微博带配图
// 设置转发体图片内容(暂时取一张为例)
_reImage.hidden = NO;
_reImage.imageList = status.retweetedStatus.picUrls;
} else { // 第二种情况:2、转发的微博不带配图
// 无配图则清空属性并隐藏
_reImage.hidden = YES;
}
} else { // 第三种情况:不带配图的微博
_image.hidden = YES;
_retweet.hidden = YES;
}
}
#pragma mark 单元格子控件布局
- (void)statusFrameSettingFrame
{
// 1、设置头像尺寸位置
_profile.frame = _statusFrame.profile;
// 2、设置昵称尺寸位置
_screenName.frame = _statusFrame.screenName;
// 2.1 设置会员图标尺寸位置
_mbIcon.frame = _statusFrame.mbIcon;
// 3、设置时间尺寸位置
CGRect timeDynamicFrame = _statusFrame.time;
timeDynamicFrame.size = [_statusFrame.status.createdAt sizeWithFont:kTimeFont]; // 时间动态显示,时间尺寸动态计算
_time.frame = timeDynamicFrame;
// 4、设置来源尺寸位置
CGRect sourceDynamicFrame = _statusFrame.source;
sourceDynamicFrame.origin.x = CGRectGetMaxX(timeDynamicFrame) + kInterval; // 时间尺寸动态计算,来源位置动态计算
_source.frame = sourceDynamicFrame;
// 5、设置正文尺寸位置
_text.frame = _statusFrame.text;
// 6、设置配图尺寸位置
_image.frame = _statusFrame.image;
// 7、设置转发体尺寸位置
_retweet.frame = _statusFrame.retweet;
// 8、设置转发体昵称尺寸位置
_reScreenName.frame = _statusFrame.reScreenName;
// 9、转发体正文尺寸位置
_reText.frame = _statusFrame.reText;
// 10、转发体配图尺寸位置
_reImage.frame = _statusFrame.reImage;
}
#pragma mark 重写frame方法设置Cell宽度
// 该方法会被调用2次
-(void)setFrame:(CGRect)frame
{
frame.origin.x += kCellMargins;
frame.size.width -= (2 *kCellMargins);
frame.origin.y += kCellMargins;
frame.size.height -= kCellMargins;
[super setFrame:frame];
}
#pragma mark 设置单元格标识
+ (NSString *)ID
{
return @"StatusCell";
}
@end
5、源码下载
相关主题链接
1、ios实战开发之仿新浪微博(第一讲:新特性展示)
2、ios实战开发之仿新浪微博(第二讲:主框架搭建)
3、ios实战开发之仿新浪微博(第三讲:更多界面搭建)
4、ios实战开发之仿新浪微博(第四讲:OAuth认证)
5、ios实战开发之仿新浪微博(第五讲:微博数据加载)
6、ios实战开发之仿新浪微博(第六讲:微博数据展示一)
7、ios实战开发之仿新浪微博(第七讲:微博数据展示二)
8、ios实战开发之仿新浪微博(第八讲:微博数据展示三)
9、ios实战开发之仿新浪微博(第九讲:微博功能完善一)
10、ios实战开发之仿新浪微博(第十讲:微博功能完善二)
11、ios实战开发之仿新浪微博(第十一讲:微博功能完善三)
12、ios实战开发之仿新浪微博(小龙虾发布版)
|