不等高cell的搭建(一)

一.界面搭建

Paste_Image.png

1.確定開發(fā)模式

如果界面是固定的,可以用xib
界面的一些內(nèi)容不固定,就用純代碼
cell用什么方式去開發(fā)(我們采用純代碼和xib結(jié)合的方式)

2.劃分層次結(jié)構(gòu)

2.1 怎么劃分?

按照功能劃分
按照隱藏效果:在某些條件下,一些控件要一起隱藏,就可以放在同一模塊中(前提是這些控件集中在一起)

2.2 分析界面發(fā)現(xiàn)cell的middleView和commentView不確定要不要顯示

所以,cell采用純代碼方法搭建

3.自定義cell

3.1在創(chuàng)建cell的時候,就把所有可能顯示的模塊全部添加到cell上

把所有可能出現(xiàn)的模塊(控件)全部添加到cell里面,然后根據(jù)需求再決定某些模塊(控件)是顯示還是隱藏

3.2根據(jù)服務(wù)器數(shù)據(jù),決定某些模塊是否隱藏

3.3在哪里創(chuàng)建cell?

采用注冊的方法,底層會自動調(diào)用initWithStyle方法來創(chuàng)建cell

4.一個模塊一個模塊去搭建

4.1把cell分解為四個模塊,如上圖

4.2先把一個模塊所有的內(nèi)容(搭建界面)和業(yè)務(wù)邏輯處理完,在去處理下一個模塊

4.3模塊的處理方式:先搭建界面,再處理界面業(yè)務(wù)邏輯

4.4優(yōu)點:業(yè)務(wù)邏輯清晰,不容易混淆

二.topView模塊開發(fā)

1.xib搭建界面

1.1分析界面有哪些控件來搭建

1.2自定義uiview并創(chuàng)建xib,描述好界面后,把界面添加到cell里面

2.請求數(shù)據(jù)

2.1 查看接口文檔,使用afn發(fā)送網(wǎng)絡(luò)請求

2.2網(wǎng)絡(luò)請求成功時,把數(shù)據(jù)轉(zhuǎn)換成模型

2.3在模型中定義屬性(先自定義模型)
查看界面需要使用哪些數(shù)據(jù),就找到定義數(shù)據(jù)的屬性定義到模型中

2.3自定義視圖模型,視圖模型包含模型(就是在視圖模型中定義一個模型的屬性)

2.4遍歷模型,全部轉(zhuǎn)換為視圖模型
創(chuàng)建視圖模型對象
用視圖模型的模型屬性來接收模型
把視圖模型保存到數(shù)組中

3.在視圖模型中計算cell子控件的frame和高度

3.1什么時候計算的
在模型轉(zhuǎn)視圖模型的時候計算的

3.2在哪里計算的?
重寫視圖模型的模型屬性的set方法,在方法里面計算cell的frame和高度,并定義屬性保存起來
因為,在模型轉(zhuǎn)視圖模型的時候,會把模型傳給視圖模型的模型屬性,底層會觸發(fā)視圖模型的模型屬性set方法,這個時候就去計算了

3.3 cell的高度計算
cell的高度就是Y軸方向最后一個控件的最大Y值

4.展示數(shù)據(jù)

4.1怎么展示?

在自定義cell里面定義視圖模型屬性
創(chuàng)建cell之后,從數(shù)組中取出對應(yīng)的視圖模型,給cell的視圖模型屬性賦值(觸發(fā)視圖模型的set方法)

4.2模型怎么接收數(shù)據(jù)的?

在cell視圖模型屬性的set方法里面,設(shè)置cell的frame和cell的高度(直接從視圖模型中去)
在把視圖模型的數(shù)據(jù)直接賦值給模型(觸發(fā)模型的set方法)
重寫模型的set方法,然后給界面的UI元素賦值,這樣就能在界面上看到數(shù)據(jù)了

5.注意點

5.1 cell會循環(huán)利用,設(shè)置某項屬性后,一定要記得還原

5.2 運行會報一些莫名其妙的約束沖突

是系統(tǒng)的自動拉伸約束有沖突,取消掉就可以了

三.middleView模塊搭建

middleView模塊的樣式也分很多種
我們可以利用xib搭建不同樣式的middleView,然后根據(jù)服務(wù)器數(shù)據(jù)決定顯示哪種樣式的middleView
注意:一定要把其它樣式的middleView隱藏,還需要在其它地方還原,防止循環(huán)引用
根據(jù)需求我們可以把middleView分為四種樣式:

1.textView樣式

也就是沒有middleView,這種樣式只要不顯示middleView就可以了(把pictureView,videoView,voiceView隱藏)
也不需要計算frame的高度了

2.pictureView樣式

Paste_Image.png

2.1 分析界面有哪些控件組成, 界面怎么搭建?

加載圖片的時候:有一個gif圖標,用ImageView來搭建,進度條可以放在一個view里面
文字部分:如果是圖片用ImageView,如果是文字,用label或button都行, 需要與用戶交互就用button
顯示圖片時:圖片用ImageView搭建,下面的查看大圖用button(有圖片和文字,還有背景圖片,還要與用戶交互,只能用button)
由于界面是固定的,可以采用xib來搭建

2.2 把pictureView添加到cel里面

2.3 請求數(shù)據(jù)

2.4 在視圖模型中計算cell子控件的frame和高度

2.4.1首先判斷數(shù)據(jù)是什么類型的
返回的類型是NSInther,可讀性太差,可以定義枚舉來替代,可讀性就很好

typedef enum : NSUInteger {
XTThemeItemTypeAll = 1,
XTThemeItemTypeVideo = 41,
XTThemeItemTypeVoice = 31,
XTThemeItemTypePicture = 10,
XTThemeItemTypeText = 29
} XTThemeItemType;

注意:定義枚舉的快捷鍵是:enum

Paste_Image.png

2.4.2 如果是text類型的就不需要計算了

2.4.3 如果圖片實際高度太高,我們就在模型里面定義一個屬性來記錄是否是大圖

2.4.4 給大圖設(shè)置一個固定高度,不需要把大圖全部展示出來了

 // middleView:一樣計算方式
// 不是段子的時候,才需要計算中間View的Frame
if (item.type != XMGThemeItemTypeText) {
    CGFloat middleW = textW;
    CGFloat middleH = middleW / item.width * item.height;
    if (middleH > XTScreenH) {  // 大圖
        middleH = 300;
        item.is_bigPicture = YES;
    }
    CGFloat middleX = margin;
    CGFloat middleY = _cellH;
    _middleViewFrame = CGRectMake(middleX, middleY, middleW, middleH);
    _cellH = CGRectGetMaxY(_middleViewFrame) + margin;
}

2.5 運行發(fā)現(xiàn),如果是大圖,圖片就被壓縮了,很難看,怎么解決?

ImageView默認是圖片填充的,就是把圖片拉伸或壓縮成整個ImageView的大小
設(shè)置ImageView的內(nèi)容模式,不讓它壓縮 UIViewContentModeTop

2.6 設(shè)置內(nèi)容模式,發(fā)現(xiàn)雖然圖片不被壓縮,但是圖片不能填充ImageView(兩邊是空的) 怎么解決?

UIViewContentModeTop默認是圖片上面顯示到ImageView的頂部,但是不會進行拉伸或壓縮
我們需要先對圖片進行拉伸或壓縮處理,然后再設(shè)置 UIViewContentModeTop 就可以了

2.7 怎么對圖片進行拉伸或壓縮處理?

可以用繪圖,生成一張新的拉伸或壓縮好的圖片

2.8 怎么繪圖?

      2.8.1 開啟圖形上下文
      2.8.2 繪制圖片
      2.8.3 獲取新的圖片
      2.8.4 關(guān)閉圖形上下文

2.9 對圖片處理進行性能優(yōu)化

2.9.1 每次設(shè)置圖片,都要進行繪圖,有可能重復(fù)繪圖,性能不好,怎么優(yōu)化?
把處理好的圖片緩存到磁盤(沙盒)里面,下次再設(shè)置這張圖片時,直接從磁盤取

2.9.2 怎么對圖片緩存處理?
自己寫方法太麻煩, SDImageCache.h內(nèi)部有方法緩存圖片,直接調(diào)用它的方法來進行緩存

       [[SDImageCache sharedImageCache] storeImage:image forKey:item.image0];
      注意:要到入頭文件: #import <SDImageCache.h>

2.9.3 怎么從磁盤中去圖片?
同樣也是調(diào)用SDImageCache.h方法來取

    UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:item.image0];
      注意:key值就是圖片的url

2.10 剛開始加載圖片時,進度條怎么設(shè)置?

2.10.1 需要設(shè)置一個功能模塊的時候,我們要先去找有沒有做該功能模塊的框架,有就直接拿來用

2.10.2 沒有的話,就找一個功能差不多的模塊來修改一下

2.10.3 怎么去查找一個框架?

Paste_Image.png
圖片設(shè)置源代碼
-(void)awakeFromNib
{
_progressView.progressLabel.textColor = [UIColor whiteColor];
_progressView.progressTintColor = [UIColor whiteColor];
_progressView.roundedCorners = 10;

_progressView.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",0.0 * 100];
_progressView.progress = 0;
}

- (void)setItem:(XMGThemeItem *)item
{
_item = item;

// 設(shè)置圖片
UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:item.image0];
if (image) {   如果有圖片直接設(shè)置,并把進度設(shè)為100%
    _imageView.image = image;
    _progressView.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",1.0 * 100];
    _progressView.progress = 1;
} else {    如果沒有圖片,就先把進度設(shè)置為0 ,再去下載圖片
    _progressView.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",0.0 * 100];
    _progressView.progress = 0;
    // 下載網(wǎng)絡(luò)圖片
    [_imageView sd_setImageWithURL:[NSURL URLWithString:item.image0]  placeholderImage:nil options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        進度就為已下載的文件大小 / 總文件大小
        CGFloat progress = 1.0 * receivedSize / expectedSize;
        運行發(fā)現(xiàn),進度有時候為-0,打印發(fā)現(xiàn)總文件大小該開始為-0       當為-0 的時候就返回
      注意:該block會頻換調(diào)用,所以  returen一次沒關(guān)系
        if (expectedSize < 0) return ;
        _progressView.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",progress * 100];
        _progressView.progress = progress;

    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

        if (!item.is_bigPicture) return ;

        // 生成一個新拉伸好圖片
        CGFloat w = XMGScreenW - 20;
        CGFloat h = w / item.width * item.height;

        // 開啟圖形上下文
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), NO, 0);
        // 繪圖
        [image drawInRect:CGRectMake(0, 0, w, h)];
        // 獲取上下文圖片
        image = UIGraphicsGetImageFromCurrentImageContext();
        // 保存圖片到沙盒
        [[SDImageCache sharedImageCache] storeImage:image forKey:item.image0];
        // 關(guān)閉上下文
        UIGraphicsEndImageContext();

        _imageView.image = image;
    }];
}
根據(jù)服務(wù)器數(shù)據(jù),決定gif圖片是否顯示
_gifView.hidden = !item.is_gif;
 根據(jù)自己判斷保存的屬性,來決定顯示大圖按鈕是否顯示
_seeBigButton.hidden = !item.is_bigPicture;

if (item.is_bigPicture) {
    _imageView.contentMode = UIViewContentModeTop;
    _imageView.clipsToBounds = YES;
} else {
    _imageView.contentMode = UIViewContentModeScaleToFill;
    _imageView.clipsToBounds = NO;
}
}

3.videoView樣式 和 voiceView樣式

Paste_Image.png

3.1 由于這兩個模塊基本相同,處理方法也差不多

3.2 根據(jù)類型,只需要設(shè)置中間按鈕的圖片就可以了

3.3 xib搭建界面,并把界面添加到cell里面

3.4 請求數(shù)據(jù)

3.5 在視圖模型中計算cell子控件的frame和高度

3.6 展示數(shù)據(jù)

3.6.1 在videoView或voiceView的模型里設(shè)置數(shù)據(jù)的時候,要對數(shù)據(jù)進行處理

3.6.2 為什么要處理?
服務(wù)器返回的時間數(shù)據(jù)是以秒為單位的,需求以 00:00 來顯示

3.6.3 怎么處理?

 NSInteger minute = item.voicetime / 60;
NSInteger second = item.voicetime % 60;
self.timeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld",minute,second];

4 在cell模型屬性的set方法里面統(tǒng)一設(shè)置middleView各個模塊的frame的是否隱藏

// middleView
if (vm.item.type == XMGThemeItemTypePicture) { // 圖片
    _pictureView.hidden = NO;
    _videoView.hidden = YES;
    _voiceView.hidden = YES;

    _pictureView.item = vm.item;
    _pictureView.frame = vm.middleViewFrame;

} else if (vm.item.type == XMGThemeItemTypeVideo) { // 視頻
    _pictureView.hidden = YES;
    _videoView.hidden = NO;
    _voiceView.hidden = YES;

    _videoView.item = vm.item;
    _videoView.frame = vm.middleViewFrame;
} else if (vm.item.type == XMGThemeItemTypeVoice) { // 音頻
    _pictureView.hidden = YES;
    _videoView.hidden = YES;
    _voiceView.hidden = NO;

    _voiceView.item = vm.item;
    _voiceView.frame = vm.middleViewFrame;

} else {
    _voiceView.hidden = YES;
    _pictureView.hidden = YES;
    _videoView.hidden = YES;
}

未完待續(xù)......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容