ios实战开发之仿新浪微博(第八讲:微博数据展示三)

1、效果展示

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//
//? 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//
//? 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//
//? 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

1
2
3
4
5
6
7
8
9
10
11
12
13
//
//? 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//
//? 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</per>
SAStatusCell.h
<pre lang="objc" line="1">//
//? 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
//
//? 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、源码下载

链接: http://pan.baidu.com/s/1jGDRhI2 密码: 5ilj

Leave a Reply