【iOS】實現評論區展開效果

文章目錄

  • 前言
  • 實現行高自適應
  • 實現評論展開效果
  • 解決cell中的buttom的復用問題


前言

在知乎日報的評論區中,用到了Masonry行高自適應來實現評論的展開,這里設計許多控件的約束問題,當時困擾了筆者許久,特此撰寫博客記錄

實現行高自適應

步驟1:
設置tableView.rowHeight = UITableViewAutomaticDimension

步驟2:
設置tableView.estimatedRowHeight = 100

解釋:設置一個預估的行高,為了代碼的易讀性,還是盡量要設置一個跟cell的高差不多的值。

步驟3:
到了此步,就涉及到了我們行高自適應的核心思想:根據內容長短將我們的控件撐開從而實現tableviewcell撐開

方法便是對控件設置上下約束但是不設置其高度,這里需要注意我們的bottom的約束一定要與contentviewbottom有關,否則無法撐開我們的contentview

我們以一段小demo為例來講解

    [_name mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(@30);make.top.equalTo(@30);make.height.equalTo(@40);make.width.equalTo(@100);}];//    [_time mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.left.equalTo(@30);
//            make.height.equalTo(@40);
//            make.width.equalTo(@100);
//        make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);
//    }];[_content mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(@30);make.top.equalTo(self->_name.mas_bottom).offset(10);
//            make.bottom.equalTo(self->_reply.mas_top).offset(-20);make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);make.right.equalTo(self.contentView.mas_right).offset(-20);}];

當我們沒有給_content的文本進行賦值時,視圖層級是這樣的
在這里插入圖片描述
同時我們的_content控件甚至沒有在層級圖上出現,但是一旦我們對其進行賦值,就會自動撐開cell的高度

    cell.content.text = @"FMDB中有三個常用的類FMDatabase 表示一個SQLite數據庫,用來執行SQL語句。";

在這里插入圖片描述

實現評論展開效果

現在我們已經實現用Masonry實現行高自適應,接下來我們講講我們知乎日報評論區中評論的展開。
思路:
1.首先我們可以得到回復的一段文本,我們需要根據文本的長短來判斷我們的評論是否需要展開,也就是說我們的展開效果是否需要實現是與我們評論的長短有關的。

-(CGSize)textHeightFromTextString:(NSString *)text width:(CGFloat)textWidth fontSize:(CGFloat)size {// 計算 label 需要的寬度和高度NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:size]};CGRect rect = [text boundingRectWithSize:CGSizeMake(textWidth, MAXFLOAT) options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];CGSize size1 = [text sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:size]}];return CGSizeMake(size1.width, rect.size.height);
}NSInteger count = [self textHeightFromTextString:reply width:303.667 fontSize:15.5].height /cell.replyLabel.font.lineHeight;if (count <= 2) {cell.foldButton.hidden = YES;} else {cell.foldButton.hidden = NO;}

這里需要注意,我們的回復label也需要實現行高自適應的效果,與content的代碼結合起來便是

    [_name mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(@30);make.top.equalTo(@30);make.height.equalTo(@40);make.width.equalTo(@100);}];[_time mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(@30);make.height.equalTo(@40);make.width.equalTo(@100);make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);}];[_content mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(@30);make.top.equalTo(self->_name.mas_bottom).offset(10);make.bottom.equalTo(self->_reply.mas_top).offset(-20);make.right.equalTo(self.contentView.mas_right).offset(-20);}];[_reply mas_makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(self->_content.mas_bottom).offset(20);make.bottom.equalTo(self.time.mas_top).offset(-10);make.right.equalTo(self.contentView.mas_right).offset(-20);make.left.equalTo(@30);}];[_foldButton mas_makeConstraints:^(MASConstraintMaker *make) {make.left.equalTo(@140);make.height.equalTo(@40);make.bottom.equalTo(self.contentView.mas_bottom).offset(-20);make.width.equalTo(@100);}];

這樣我們的contentreply就都與我們的contentView的底部又了約束關系,從而實現了行高自適應
在這里插入圖片描述

解決cell中的buttom的復用問題

我們可以通過上面的動畫看到,我們的評論區確實實現了評論展開,但是出現了buttom的復用問題,這里筆者將一下解決方案

  • 首先為每一個buttom設置一個tag值,并且我們需要通過我們的buttom得到我們的cell

筆者使用的方法是- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;

通過buttom的tag來確定我們的row,從而定位到我們選擇的cell
replyTableViewCell *cell = (replyTableViewCell *)[_commentTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:buttom.tag inSection:0]];

當然還有另外的辦法,就是通過查找父視圖的方法來得到對應的cell

 1.button.superView = cell.contentView; 2.button.superView.superView = cell; 3.button.superView.superView.superView = UITableviewWrapperView; 4.button.superView.superView.superView.superView = UITableView; 

這樣一來就實現了得到對應buttom的cell

replyTableViewCell *cell = (replyTableViewCell *)[_commentTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:buttom.tag inSection:0]];
replyTableViewCell *cell = (replyTableViewCell *)buttom.superview.superview;
  • 然后我們對對應的cellreply.numberOfLines進行修改
    if (cell.reply.numberOfLines == 0) {NSLog(@"1");cell.reply.numberOfLines = 2;[buttom setTitle:@" · 展示更多" forState:UIControlStateNormal];} else {NSLog(@"2");cell.reply.numberOfLines = 0;[buttom setTitle:@" · 收起" forState:UIControlStateNormal];}
  • 最后使用[_commentTableView beginUpdates]; [_commentTableView endUpdates];這兩個方式刷新我們的tabelView

注意這里必須使用[_commentTableView beginUpdates];[_commentTableView endUpdates];,否則仍然會發生按鈕的復用,原因是:

[_commentTableView reloadData]:

重新加載整個表格視圖的數據。 此方法會重新調用數據源和代理方法,并刷新所有的行和部分。

[_commentTableView beginUpdates][_commentTableView endUpdates]:

用于執行一系列的插入、刪除、選擇和重新加載的動畫,而不需要調用 reloadData。 通常與
insertRowsAtIndexPaths:withRowAnimation:、deleteRowsAtIndexPaths:withRowAnimation:、reloadRowsAtIndexPaths:withRowAnimation:
等方法一起使用。

UITableView 的 reloadData 方法會重新加載整個表格視圖的數據,包括所有的行和部分。這會導致表格的重繪,所有的可見單元格都會被重新加載,也就是會調用 cellForRowAtIndexPath: 方法獲取新的單元格。
如果在 cellForRowAtIndexPath: 方法中沒有正確處理單元格的重用標識符和狀態,就會導致按鈕等子視圖的狀態混亂,因為這些子視圖的狀態沒有被正確更新。
而使用 beginUpdates 和 endUpdates 方法執行一系列的插入、刪除、選擇和重新加載的操作時,系統會盡量保持現有單元格的狀態,而不是重新加載整個單元格。這樣,單元格的復用機制仍然有效,減少了對整個表格的重繪,從而減小了混亂的可能性。

同時使用[_commentTableView beginUpdates];[_commentTableView endUpdates];還優化了tableviewcell加載與刷新的性能開銷

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/160415.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160415.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160415.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何構建更簡潔的前端架構?

目錄 為什么需要前端架構&#xff1f; 那么&#xff0c;前端架構是什么樣的呢&#xff1f; 使用了哪些層&#xff1f; 那么&#xff0c;這種架構會出什么問題呢&#xff1f; 我們應該如何避免這些錯誤&#xff1f; 哪些原則應適用于組件&#xff1f; Anti-Patterns 反模…

小程序存在優惠卷遍歷,但是歪了

進入小程序&#xff0c;因為是一個小商城&#xff0c;所以照例先查看收貨地址是否存在越權&#xff0c;以及能否未授權訪問&#xff0c;但是發現不存在這些問題&#xff0c;所以去查看優惠卷 進入領券中心&#xff0c;點擊領取優惠券時抓包 發現數據包&#xff0c;存在敏感參數…

數據庫的級聯刪除

級聯刪除是指在數據庫中刪除一個對象時&#xff0c;與該對象有關的其他對象也被自動刪除。在 Django 中&#xff0c;級聯刪除通常通過在模型中定義外鍵時使用 on_delete 參數來實現。以下是一些常見的 on_delete 選項&#xff1a; 1.models.CASCADE: 當關聯的對象被刪除時&…

CentOS 7 使用Fmt庫

安裝 fmt Git下載地址&#xff1a;https://github.com/fmtlib/fmt 步驟1&#xff1a;首先&#xff0c;你需要下載fmt的源代碼。你可以從https://github.com/fmtlib/fmt或者源代碼官方網站下載。并上傳至/usr/local/source_code/ ? 步驟2&#xff1a;下載完成后&#xff…

【Docker】Docker安裝Nginx配置靜態資源

1.下載鏡像 2.創建nginx配置文件 3.創建nginx容器運行 4.配置nginx靜態資源 1.下載鏡像 Dockerhub官網&#xff1a;Docker docker pull nginx docker pull nginx下載最新版本 默認latest 下載指定版本docker pull nginx:xxx 2.創建nginx配置文件 啟動容器之前要創建nginx…

怎么使用sentinel,以及所有的知識點

Sentinel是一個開源的流量控制和實時監控系統&#xff0c;主要用于保護企業級應用程序免受不良的請求。下面是使用Sentinel需要了解的知識點&#xff1a; 1. 什么是流量控制&#xff1f; 流量控制指的是限制應用程序的請求流量&#xff0c;防止過多的請求超出系統的承受范圍。…

基于單片機停車場環境監測系統仿真設計

**單片機設計介紹&#xff0c; 基于單片機停車場環境監測系統仿真設計 文章目錄 一 概要二、功能設計設計思路 三、 軟件設計原理圖 五、 程序六、 文章目錄 一 概要 基于單片機的停車場環境監測系統是一種利用單片機技術實現環境監測和數據處理的系統。它可以感知停車場的溫濕…

Python (十一) 迭代器與生成器

迭代器 迭代器是訪問集合元素的一種方式&#xff0c;可以記住遍歷的位置的對象 迭代器有兩個基本的方法&#xff1a;iter() 和 next() 字符串&#xff0c;列表或元組對象都可用于創建迭代器 字符串迭代 str1 Python str_iter iter(str1) print(next(str_iter)) print(next(st…

zip4j壓縮使用總結

一、引入依賴 <dependency><groupId>net.lingala.zip4j</groupId><artifactId>zip4j</artifactId><version>1.3.1</version></dependency>二、使用添加文件&#xff08;addFiles&#xff09;的方式生成壓縮包 /*** Author wan…

藍橋杯物聯網_STM32L071_2_繼電器控制

CubeMX配置&#xff1a; Function.c及Function.h&#xff1a; #include "Function.h" #include "gpio.h" void Function_LD5_ON(void){HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET); }void Function_LD5_OFF(void){HAL_GPIO_WritePin(LD5_…

HarmonyOS應用開發者認證題目滿分指南

為了幫助大家快速的上手HarmonyOS應用程序開發&#xff0c;官方制作了一些免費的課程&#xff1a;HarmonyOS第一課。每個課程后面都有一些練習題&#xff0c;下面就是這些題目的滿分答案。 【習題】運行Hello World工程 判斷題 1.DevEco Studio是開發HarmonyOS應用的一站式集…

定時器如何計算觸發頻率?

定時器觸發頻率的計算公式為&#xff1a;定時器時鐘頻率/&#xff08;預分頻系數*計數周期1&#xff09;。其中&#xff0c;定時器時鐘頻率是指定時器所連接的總線頻率&#xff0c;預分頻系數和計數周期需要根據具體的需求進行設置。預分頻系數用于將總線頻率分頻&#xff0c;計…

Power Apps-下拉列表控件

插入一個下拉列表控件 設置值的兩種方式 1.通過屬性items寫數組設置 2.通過連接數據表&#xff0c;先在右側操作面板中選擇項目中的數據表 再從Value中選擇其中一列&#xff0c;下拉就可以選擇該列全部行的值 但是這樣會導致有很多重復的字段&#xff0c;所以可以在items屬性里…

好用的博客評論系統 Valine 使用及避坑指南

評論系統&#xff0c;即網站的一個小功能&#xff0c;展示評論內容和用戶輸入框。開源免費的評論系統可不多&#xff0c;原來很火的"多說"評論系統都關閉了&#xff0c;而Disqus又是國外的訪問受限。無意間發現了Valine&#xff0c;挺不錯的&#xff0c;分享給大家。…

如何用cmd命令快速搭建FTP服務

環境&#xff1a; Win10專業版 問題描述&#xff1a; 如何用cmd命令快速搭建FTP服務 解決方案&#xff1a; 1.輸入以下命令來安裝IIS&#xff08;Internet Information Services&#xff09;&#xff1a; dism /online /enable-feature /featurename:IIS-FTPServer /all …

IDEA集成Git

一、配置Git忽略文件 例如&#xff1a;用eclipse創建的項目有其特定的文件&#xff0c;例如&#xff1a;.classpath,.project文件&#xff0c;而用IDEA創建的項目也有其特定的文件&#xff1a;.xml,.iml,.target,我們需要最好忽略他們。 為什么要忽略他們&#xff1f; 與項目…

從Github登錄的雙因子驗證到基于時間戳的一次性密碼:2FA、OTP與TOTP

Github于2023-03-09推出一項提高軟件安全標準的措施&#xff0c;所有在Github上貢獻過代碼的開發人員在年底前必須完成 2FA&#xff08;Two-factory authentication&#xff0c;雙因子認證&#xff09;。初聽此事之時&#xff0c;不以為意&#xff0c;因為自己之前就知道雙因子…

關于2023年的裸辭對話

2023: 為什么要裸辭&#xff1f; 小蘇&#xff1a;因為我瘋了 2023&#xff1a;裸辭后悔嗎&#xff1f; 小蘇&#xff1a; 如果很快找到工作就不后悔&#xff0c;但是今年沒有工作&#xff0c;后悔裸&#xff0c;不后悔辭。 2023&#xff1a;關于市場環境的敏感度&#xff…

操作系統(三)| 進程管理下 經典進程問題分析 線程 死鎖

文章目錄 6.經典進程同步問題6.1 生產者-消費者問題 (既有同步又有互斥)6.2 讀者-寫者問題6.3 哲學家進餐問題6.4理發師問題 7. 進程之間通信7.1 共享存儲區7.2 消息傳遞7.3 管道 8.線程8.1 線程的實現機制 9 進程調度9.1 調度方式9.2 常見算法先來先服務 FCFS短進程優先 SPN最…

C++之常用的排序算法

C之常用的排序算法 sort #include<iostream> using namespace std; #include<vector> #include<algorithm> #include<functional> void Myptint(int val) {cout << val << " "; }void test() {vector<int> v;v.push_back(…