亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS仿微博客戶端一條微博的展示效果

2020-07-26 02:55:04
字體:
來源:轉載
供稿:網友

前言

做一個微博客戶端的第三方是自學的第一個實踐的項目,自從從事iOS工作之后,就把這個項目給擱置了。趁現在過年回來有些空閑時間,再次修改(總覺得項目就是不停地修改)。并且記錄一點東西,以后可再回頭看看從前走過的路,挖過的坑。這是一條微博的展示,不是整個項目。

廢話不多說,先上效果圖:


拆分控件

在開始動手寫代碼之前,我們得先確定怎么去實現這樣子的布局,也就是分析需要用到哪些控件。

觀察微博客戶端,整體是可滑動的,而且界面展示比較規律的,所以應該是使用UITableView實現的。那么一條微博應該是用UITableViewCell 來實現的,這個由點擊時,整條微博都變色可以肯定。
一條微博與其他的微博之間是有大約10PX的間距,可以認為每個Section就只有一個Cell。

每條微博的共同部分包括:頭像,用戶名稱,發布時間與發布來源,微博正文,底部的轉發,評論,贊。不同的部分有:配圖,非原創微博的正文。(視頻,文章等在這個項目中不做考慮)所以共同部分可以直接在xib上固定,不同部分則需要在.m文件用代碼來寫。

控件的確定:頭像和配圖使用UIImageView,用戶名稱,發布時間與來源,微博正文,非原創微博的正文都是使用UILabel,而底部的轉發,評論,贊使用UIButton。

當一條微博是非原創微博(轉發微博),根據點擊被轉發的微博的變色情況,可以確定轉發微博是一個整體,可以確定轉發微博是放在一個UIView上再添加到Cell上面的。

布局

放上一張xib的布局圖:(button是與底部進行約束的)


共同的部分,先設置一些參數。

- (void)awakeFromNib {[super awakeFromNib];_contentLabel.numberOfLines = 0;//正文多行//圓形頭像_headImageView.layer.masksToBounds = YES;_headImageView.layer.cornerRadius = HeadImageHeight / 2;//設置tag,為了后面識別點擊哪個按鈕_repostButton.tag = RepostButtonTag;_commentButton.tag = CommentButtonTag;_likeButton.tag = LikeButtonTag;}

先說配圖,微博的配圖最多9張。首先先根據配圖的張數和屏幕的寬度確定圖片的大小imageWidth,然后再確定行數和列數。

1、只有一張配圖時,imageWidth = 屏幕寬度 * 0.55;
2、配圖超過一張時,imageWidth = (屏幕寬度 - 間隙) / 3;
3、配圖是2張或者4張時,分為兩列布局,而配圖3張或者大于4張時,則分為三列布局。
LeadingSpace 是圖片與兩側屏幕的間隙,為8PX, ImageSpace是圖片之間的間隙為4PX。UI_SCREEN_WIDTH是屏幕寬度。

 //根據圖片數量獲得列數 if (_imageArray.count == 1) { //一列 column = 1; imageWidth = UI_SCREEN_WIDTH * 0.55; } else if (_imageArray.count == 2 || _imageArray.count == 4) { //兩列 column = 2; imageWidth = (UI_SCREEN_WIDTH - (LeadingSpace + ImageSpace) * 2) / 3; } else { //三列 column = 3; imageWidth = (UI_SCREEN_WIDTH - (LeadingSpace + ImageSpace) * 2) / 3; } //根據圖片的數量和列數獲得行數 if (_imageArray.count % column == 0) { row = _imageArray.count / column; } else { row = _imageArray.count / column + 1; }

確定了配圖的大小,再根據位置,就可以創建UIImageView。 配圖的位置則在正文起始位置 + 正文的高度 + 間隙,而獲取正文的高度由以下方法來完成:

 * 計算label的高度 * * @param text 文字 * @param width label寬度 * @param font 字體 * * @return label高度+ (CGFloat)getLabelHeightWithText:(NSString *)text width:(CGFloat)width font:(UIFont *)font {CGSize size = CGSizeMake(width, MAXFLOAT);//設置一個行高的上限CGSize returnSize;NSDictionary *attribute = @{ NSFontAttributeName : font };returnSize = [text boundingRectWithSize:size                options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading               attributes:attribute                context:nil].size;return returnSize.height;}

對于原創微博正文的起始位置可以由xib看出來,頭像的高度固定為48,而上下的間隙為8, 則起始位置Y坐標為 48 + 16 = 64;而對于非原創微博,正文的起始位置Y坐標為8 (此處的8是相對于配圖的父容器UIView的位置,對于非原創微博而言,更重要的是計算出父容器UIView在Cell中的位置);

然后根據配圖的位置和大小創建UIImageView,如下圖,其中originY為第一張配圖的起始位置的Y坐標。

//根據位置創建imageViewfor (int i = 0; i < row; i++) {  for (int j = 0; j < column; j++) {    //用來判斷數據是否越界    if (i * column + j < _imageArray.count) {      imageUrl = _imageArray[i * column + j];      if (imageUrl) {        TapImageView *imageView = [[TapImageView alloc] initWithFrame:CGRectMake(LeadingSpace + j * (ImageSpace + imageWidth), originY + LeadingSpace + i * (ImageSpace + imageWidth), imageWidth, imageWidth)];        imageView.tag = ImageViewTag + i * column + j;        //block通知,點擊了圖片,展示大圖        __weak typeof(self) weakSelf = self;        imageView.didTouchImage = ^(NSInteger index) {          [weakSelf showFullScreenImage:index];        };        [imageView setImageUrl:imageUrl index:i * column + j];        //原創微博直接添加的cell中,非原創則加入一個容器中UIView,再將容器加入cell中        if (isForward) {          [_forwardedContainerView addSubview:imageView];        }        else {          [self addSubview:imageView];        }      }    }    else {      //越界后跳出for循環      break;    }  }}

TapImageView是UIImageView的子類,主要是添加了手勢,實現點擊圖片展開大圖的效果,后面再做詳細介紹。

非原創微博有兩個正文,分別用“上文”和“下文”來區分吧。上文已經在xib中,而下文和配圖是放在_forwardedContainerView(UIView)中,然后再添加到Cell中的,所以要計算它的起始位置Y坐標。上文的Y坐標已經確定為64了,而_forwardedContainerView與上文之間的間隙為8,所以下文的Y坐標 = 64 + 上文的高度 + 8。其中ContentLabelOriginY = 64

CGFloat contentHeight = [FitBoUI getLabelHeightWithText:_weibo.text width:UI_SCREEN_WIDTH - LeadingSpace * 2 font:FontSize12];CGFloat originY = ContentLabelOriginY + contentHeight;originY += LeadingSpace;_forwardedContainerView = [[UIView alloc] initWithFrame:CGRectMake(0, originY, UI_SCREEN_WIDTH, 40)];_forwardedContainerView.tag = ForwardedContainerViewTag;_forwardedContainerView.backgroundColor = [UIColor colorWithWhite:0.75 alpha:0.35];//添加單擊手勢,點擊原創微博,進入該微博的詳情頁面[self forwardedContainerViewAddGesture];[self addSubview:_forwardedContainerView];

_forwardedContainerView的高度是隨便給的,需要在計算實際高度之后再重新賦值。

//下文是用戶名稱和文字拼湊而來。NSString *forwardText = [NSString stringWithFormat:@"@%@:%@", forwardWeibo.user.name, forwardWeibo.text];CGFloat forwardContentHeight = [FitBoUI getLabelHeightWithText:forwardText width:UI_SCREEN_WIDTH - LeadingSpace * 2 font:FontSize12];UILabel *forwardedContentLabel = [[UILabel alloc] initWithFrame:CGRectMake(LeadingSpace, LeadingSpace, UI_SCREEN_WIDTH - LeadingSpace * 2, forwardContentHeight)];forwardedContentLabel.font = FontSize12;forwardedContentLabel.numberOfLines = 0;forwardedContentLabel.text = forwardText;[_forwardedContainerView addSubview:forwardedContentLabel];//創建imageview,并根據修改實際高度,pic_urls是圖片的網址數組。得到的imageHeight為所有圖片以及圖片之間的間隙總和。CGFloat imageHeight = [self initImageView:forwardWeibo.pic_urls originY:forwardContentHeight + LeadingSpace isForward:YES];//此處無論有沒有配圖,都預留了配圖上下兩個間隙的高度。所以,如果沒有配圖,上面返回的imageHeight = - LeadingSpace才合適。_forwardedContainerView.frame = CGRectMake(0, originY, UI_SCREEN_WIDTH, forwardContentHeight + imageHeight + LeadingSpace * 3);

TapImageView是UIImageView的子類,主要是添加了手勢,實現點擊圖片展開大圖的效果

TapImageView.h文件:

#import <UIKit/UIKit.h>@interface TapImageView : UIImageView@property (copy, nonatomic) void (^didTouchImage)(NSInteger index);- (instancetype)initWithFrame:(CGRect)frame;/** 設置圖片地址 @param url  圖片地址 @param index 圖片下標 */- (void)setImageUrl:(NSString *)url index:(NSInteger)index;@end

TapImageView.m文件

#import "TapImageView.h"#import "UIImageView+WebCache.h"@interface TapImageView ()@property (assign, nonatomic) NSInteger index;@end@implementation TapImageView- (instancetype)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {  [self initView];}return self;}- (void)initView {//添加單擊手勢UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewTapAction:)];gesture.numberOfTapsRequired = 1;self.userInteractionEnabled = YES;[self addGestureRecognizer:gesture];}//發送點擊圖片的通知,并傳回下標- (void)imageViewTapAction:(UITapGestureRecognizer *)gesture {if (_didTouchImage) {  _didTouchImage(_index);}}/** 設置圖片地址 @param url  圖片地址 @param index 圖片下標 */- (void)setImageUrl:(NSString *)url index:(NSInteger)index {if (url) {  [self sd_setImageWithURL:[NSURL URLWithString:url]];}_index = index;}

在Cell中,會根據傳回的點擊圖片下標展示相應圖片的大圖。

注意:

因為下文和配圖等是運行時動態添加上去的,而cell是復用的,則每次使用cell的時候,需要將它們先移除。如果沒有移除,則復用cell的時候就會發生cell位置錯亂的情況。

- (void)removeView {//移除轉發微博for (UIView *view in self.subviews) {if (view.tag == ForwardedContainerViewTag) {[view removeFromSuperview];break;}}//移除圖片for (UIView *view in self.subviews) {if ([view isKindOfClass:[TapImageView class]]) {[view removeFromSuperview];}}}

在控制器中的實現

在控制器的xib中只有一個UITableView,可以直接在xib中指定UITableView的dataSource 和delegate,也可以在.m文件中再指定。

//注冊cell,WeiboCellIdentifier是cell復用時用到的UINib *weiboNib = [UINib nibWithNibName:@"FitBoCell" bundle:nil];[_mainTableView registerNib:weiboNib forCellReuseIdentifier:WeiboCellIdentifier];//移除分割線_mainTableView.separatorStyle = UITableViewCellSeparatorStyleNone;_mainTableView.delegate = self;_mainTableView.dataSource = self;

接著實現UITableViewDataSource, UITableViewDelegate里面的方法。

//返回section的個數 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return _weiboArray.count;}//返回每個section里面的行數- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return 1;}//返回每個section底部的高度,默認為20PX, 就是如果不實現該方法或者return 0,實際都是返回20PX- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {return 0.001;}//返回每個section頭部的高度,默認為20PX, 就是如果不實現該方法或者return 0,實際都是返回20PX- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {return 10;}//返回每一行的高度- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {NSInteger section = indexPath.section;WeiboModel *weibo = _weiboArray[section];return [FitBoCell getCellHeight:weibo];}//在這個方法里面設置cell的內容- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {NSInteger section = indexPath.section;//這個辦法是模型轉化,利用MJExtension框架 WeiboModel *weibo = [WeiboModel mj_objectWithKeyValues:_weiboArray[section]];FitBoCell *cell = [tableView dequeueReusableCellWithIdentifier:WeiboCellIdentifier];if (cell == nil) {  cell = [[FitBoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:WeiboCellIdentifier];}//這里是點擊非原創微博里面的原創微博的回調,也就是_forwardedContainerView的點擊回調__weak typeof(self) weakSelf = self;cell.didTouchForwardedWeibo = ^(WeiboModel *weibo) {  //跳轉到微博的詳情頁面  [weakSelf forwardedWeiboTouch:weibo];};[cell setWeiboInfo:weibo];return cell;}//cell的點擊響應事件,跳轉到微博的詳情頁面- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {[tableView deselectRowAtIndexPath:indexPath animated:YES];NSInteger section = indexPath.section;WeiboModel *weibo = [WeiboModel mj_objectWithKeyValues:_weiboArray[section]];CommentOrRepostListViewController *listVC = [CommentOrRepostListViewController new];[listVC setWeibo:weibo offset:NO];[self.navigationController pushViewController:listVC animated:YES];}

其中,因為cell的高度是根據實際情況不定的,所以使用了類方法來獲取。[FitBoCell getCellHeight:weibo]

/** * 獲取cell的高度 * * @param weibo weibo * * @return height */+ (CGFloat)getCellHeight:(WeiboModel *)weibo {CGFloat contentHeight = [FitBoUI getLabelHeightWithText:weibo.text width:UI_SCREEN_WIDTH - LeadingSpace * 2 font:FontSize12];CGFloat originY = ContentLabelOriginY + contentHeight + LeadingSpace;if (weibo.retweeted_status == nil) {  //原創微博  CGFloat imageHeight = [self getImageHeight:weibo.pic_urls.count];  return originY + imageHeight + LeadingSpace + ButtonHeight;}else {  //非原創微博  WeiboModel *forwardWeibo = weibo.retweeted_status;  NSString *forwardText = [NSString stringWithFormat:@"@%@:%@", forwardWeibo.user.name, forwardWeibo.text];  CGFloat imageHeight = [self getImageHeight:forwardWeibo.pic_urls.count];  CGFloat forwardContentHeight = [FitBoUI getLabelHeightWithText:forwardText width:UI_SCREEN_WIDTH - LeadingSpace * 2 font:FontSize12];  return originY + LeadingSpace + forwardContentHeight + imageHeight + LeadingSpace * 2 + ButtonHeight;}}//獲取圖片的整體高度+ (CGFloat)getImageHeight:(NSInteger)count {if (count < 1) {  //上面計算高度的時候預留了配圖上下兩個間隙的高度。所以,如果沒有配圖,返回 - LeadingSpace才合適。  return - LeadingSpace;}else if (count == 1) {  return UI_SCREEN_WIDTH * 0.55;}else if (count / 3 < 1 || count == 3) {  //一行  return (UI_SCREEN_WIDTH - (LeadingSpace + ImageSpace) * 2) / 3;}else if (count > 3 && count <= 6) {  //兩行  return (UI_SCREEN_WIDTH - (LeadingSpace + ImageSpace) * 2) / 3 * 2 + ImageSpace;}else {  //三行  return (UI_SCREEN_WIDTH - (LeadingSpace + ImageSpace) * 2) + ImageSpace * 2;}}

其他的點擊事件的響應方法等,就不累贅了。最后再放一張非原創微博的效果圖:


以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品中文字幕在线观看| 色噜噜狠狠色综合网图区| 欧美午夜激情在线| 久久99视频免费| 欧美乱大交xxxxx另类电影| 欧美激情乱人伦| 性欧美xxxx交| 成人妇女免费播放久久久| 亚洲免费人成在线视频观看| 国产91九色视频| 5252色成人免费视频| 日韩美女av在线| 国产小视频国产精品| 欧美成人午夜影院| 欧美天天综合色影久久精品| 一二美女精品欧洲| 正在播放亚洲1区| 欧美大片在线看免费观看| 91最新在线免费观看| 国产精品自拍偷拍视频| 欧美成人激情视频| 久久精品这里热有精品| 成人久久精品视频| 亚洲人午夜精品| 国产欧美日韩91| 日韩视频一区在线| 成人激情在线播放| 性视频1819p久久| 国产成人精品一区二区| 亚洲成人在线视频播放| 91久久在线观看| 57pao国产成人免费| 国产精品一区二区在线| 日韩女优人人人人射在线视频| 日韩精品视频在线免费观看| 国产精品青青在线观看爽香蕉| 成人激情在线观看| 91禁国产网站| 日韩精品免费看| 日韩欧美一区二区三区久久| 欧美日韩中文字幕| 国产精品v日韩精品| 亚洲精品视频二区| 精品亚洲一区二区三区四区五区| 91国产视频在线播放| 97人人爽人人喊人人模波多| 亚洲最大av网站| 精品调教chinesegay| 欧美成人黄色小视频| 亚洲永久免费观看| 日韩欧美在线视频免费观看| 成人动漫网站在线观看| 欧美制服第一页| 久久免费视频观看| 欧美成人黑人xx视频免费观看| 欧美与黑人午夜性猛交久久久| 中文字幕亚洲综合久久| 久久久久国色av免费观看性色| 成人午夜在线观看| 国产97在线播放| 2021国产精品视频| 国产精品久久91| 亚洲最大av网站| 亚洲网在线观看| 亚洲男人第一av网站| 久久久久久久电影一区| 久久国产精品久久久久| 久久激情视频免费观看| 国产精品久久久久久久久借妻| 欧美国产日产韩国视频| 日韩视频免费在线观看| 亚洲自拍另类欧美丝袜| 日韩有码在线电影| 91免费国产网站| 欧美肥婆姓交大片| 亚洲第一精品福利| 久久91超碰青草是什么| 欧美区二区三区| 美女扒开尿口让男人操亚洲视频网站| 国产精品美女视频网站| 日韩免费黄色av| 欧美精品一本久久男人的天堂| 亚洲成avwww人| 亚洲第一av网站| 91久久夜色精品国产网站| 国产亚洲精品一区二区| 欧美日韩国产精品一区二区不卡中文| 国产欧美日韩中文字幕在线| 亚洲欧洲免费视频| 国产成人高清激情视频在线观看| 日韩精品视频免费在线观看| 欧美极品欧美精品欧美视频| 国产精品一久久香蕉国产线看观看| 日韩av免费看网站| 亚洲欧美国产一本综合首页| 粗暴蹂躏中文一区二区三区| 亚洲aⅴ日韩av电影在线观看| 亚洲mm色国产网站| 欧美超级乱淫片喷水| 国产成人福利视频| 久久亚洲精品小早川怜子66| 日本在线观看天堂男亚洲| 久久免费国产视频| 日韩av中文字幕在线| 欧美激情aaaa| 欧美亚洲在线播放| 成人写真福利网| 97av在线视频免费播放| xvideos成人免费中文版| 精品人伦一区二区三区蜜桃免费| 国产亚洲一区二区精品| 亚洲石原莉奈一区二区在线观看| 色综合五月天导航| 日本精品视频在线播放| 最近2019好看的中文字幕免费| 亚洲电影在线看| 亚洲欧美日韩一区在线| 成人精品久久一区二区三区| 亚洲欧美中文另类| 最新亚洲国产精品| 亚洲自拍偷拍色片视频| 精品视频在线播放免| 91在线观看免费网站| 国产精品吊钟奶在线| 性欧美长视频免费观看不卡| 欧美日韩在线视频一区二区| 亚洲天堂男人的天堂| 国产精品久久久av| 亚洲欧美国产一区二区三区| 日韩国产欧美区| 久久久成人av| 亚洲国产精品成人va在线观看| 美女视频久久黄| 欧洲成人性视频| 亚洲精品一区二区久| 欧美在线视频一区二区| 日韩av电影在线播放| 欧美性视频精品| 亚洲欧洲在线播放| 91精品啪aⅴ在线观看国产| 久久国产精品99国产精| 日韩在线观看精品| 在线播放日韩av| 成人国产精品日本在线| 国产成人精品免费视频| 亚洲天堂久久av| 久久99热这里只有精品国产| 欧美极品欧美精品欧美视频| 欧美xxxx18性欧美| 欧美诱惑福利视频| 成人免费淫片aa视频免费| 久久久久久91香蕉国产| 性金发美女69hd大尺寸| 国产97在线|日韩| 97视频国产在线| 91成人国产在线观看| 一本久久综合亚洲鲁鲁| 亚洲一级黄色av| 欧美性猛交xxxx富婆弯腰| 亚洲美女久久久| 成人有码在线视频| 色噜噜亚洲精品中文字幕| 久久噜噜噜精品国产亚洲综合| 日韩在线视频一区|