1. 程式人生 > >iOS`UITableView`使用系統多選 全選自定義選中背景色 cell多選

iOS`UITableView`使用系統多選 全選自定義選中背景色 cell多選

    最近做一個專案,要用到UITableView中cell的多選和全選。 

上網簡單一搜索,發現很多小夥伴對於這塊是自己自定義cell且通過程式碼判斷,再去改變UI來實現。很多方法的理論基礎基本上都是自己給cell寫一個屬性來記錄其是否未被選中的狀態,然後單獨用一個字典來裝這些狀態和對應cell所在的indexPath  每次載入cell再去做判斷 如何顯示選中與非選中狀態UI不同。 就突然記起Apple對這塊功能貌似是已經實現了的,並且留了簡單易懂的介面給我們。

於是首先建立一個簡單的TableView如下圖:


 接下來簡單為tableView新增倆行程式碼就可以實現選中後那個藍色的勾。

   
     table.editing = YES;
     table.allowsMultipleSelectionDuringEditing = YES;
程式碼中第一行意思為table進入編輯狀態,第二行是允許table在編輯的時候多選。當然關於table的編輯在<UITableViewDelegate>中有關於table編輯的插入 刪除等等不在此贅述。 然後接下來是實現cell的全選的實現。此處我是將點選全選和取消全選都寫在左邊的NavigationItem上:
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.title = @"多選cellDemo";
    
    [self customTableView];
    
    //為左邊的item設定標題和動作
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"全選" style:UIBarButtonItemStylePlain target:self action:@selector(selecteAllCells:)];
    
}


#pragma mark Actions
- (void)selecteAllCells:(UIBarButtonItem *)sender {
    if (_isAllSelected == NO) {
        
        _isAllSelected = YES;
        [sender setTitle:@"取消"];
        
        for (int i = 0; i < self.dataArray.count; i++) {

            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
        }
    } else {
        
        _isAllSelected = NO;
        [sender setTitle:@"全選"];
        
        for (int i = 0; i < self.dataArray.count; i++) {
            
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
        }
    }
    
}

程式碼實現邏輯主要是講所有cell的indexPath找出來用table的方法選擇和取消選擇cell.效果圖如下:


選中之後呼叫[tableViewindexPathsForSelectedRows]獲得所有indexPath.

此時有新的需求 選中之後背景的灰色不太好看 客戶只想要保留藍色的勾,不要這個背景灰色。那麼可在<UITableViewDataSource>的返回和自定義cell的函式中設定 

   cell.selectedBackgroundView = [[UIViewalloc]init]; 另外一個小tip 可設定tableView的tableFooterView = [[UIView alloc] init]可以消除tableView下面那些多出來的線條。效果圖如下:


此時客戶需求又有變化,客戶覺得那個選中圖片圓圈的背景圖片藍色太深 不好看,讓改淡些。心裡一萬匹草泥馬呼嘯而過 但咱作為有素質有技術的工程師不能表現出來對吧。於是又接著改。直到此時 仍不願去自定義cell裡面的控制元件寫邏輯 忒麻煩了有木有。

於是想,該圖片在介面上已經顯示出來了,那肯定是存在的於是在呼叫 [cell subviews]方法尋找,發現在<UITableViewDataSource>的自定義cell那個方法裡沒什麼線索。


換個地方,於是在<UITableViewDelegate>裡面選擇回撥的地方用類似的方法找,果然皇天不負有心人。

由下圖可見,此時選中的cell中有四個子檢視 類名分別為:UIView,UITableViewCellContentView,UITableViewSeparatorView,UITableViewCellEditControl.猜也能猜到我們的藍色勾勾在第四個裡面,正好裡面還有一個imageView屬性。然後問題又來了,這個UITableViewCellEditControl是何方神聖?翻遍了dash裡面iOS9.0文件和UITableViewCell標頭檔案並沒有找到這麼一個類。想來可能是一個匿名類,不過還好其基類是UIControl類,於是可以用面向物件三大特性之一的多型,迴圈判斷找出該物件。沒有標頭檔案的類,屬性自然也沒有setter和getter方法,不能通過點語法讀取到。於是我們還有一個強大的工具,叫做KVC(key-value-coding)鍵值編碼,對OC這門動態語言量身定製,利用runtime執行時原理動態為物件設定屬性。於是通過以下程式碼設定

#pragma mark <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    NSArray *subviews = [[tableView cellForRowAtIndexPath:indexPath] subviews];
    
    for (id obj in subviews) {
        if ([obj isKindOfClass:[UIControl class]]) {

            for (id subview in [obj subviews]) {
                if ([subview isKindOfClass:[UIImageView class]]) {
                    
                    [subview setValue:blueBackground forKey:@"tintColor"];
                    break;
                }
                
            }
        }
    }
}

至此,終於達到目的,且重要的是沒用多少程式碼有木有。效果圖如下


最後,還有一個小小Bug,因為我們的全選的做法是迴圈所有cell的indexPath 然後掉方法

[self.tableViewselectRowAtIndexPath:indexPathanimated:YESscrollPosition:UITableViewScrollPositionTop];這樣,全選的cell顏色又回到了原來那麼深 於是將改變cell選中圖片背景色的程式碼封裝成方法 在這倆處呼叫整理程式碼如圖


************更改補充說明

用KVC思想做執行時物件屬性設定是一種很好的辦法。但發現其實勾選的顏色的更改只需要一句簡單的程式碼設定 

cell.tintColor = [UIColor redColor];

簡單看一下tintColor這個屬性


   如上圖文件中介紹,tintColor自iOS 5.0之後可用,自iOS7.0之後會影響以設定該屬性的檢視為根檢視的整個檢視層次架構,即如果指定了一個檢視的tintColor,這個值會自動賦值到以該檢視為根檢視的所有子檢視上面,如果該子檢視沒有另外設定tintColor的話。想了解更深的同學可以看看這篇文章:http://www.cocoachina.com/ios/20150703/12363.html

(歡迎隨手給一顆星星哦~)本篇部落格Demo地址https://github.com/xmy0010/DemoForCSDN

本人郵箱[email protected]歡迎小夥伴一起討論,學習,進步。

相關推薦

iOS`UITableView`使用系統 定義選中景色 cell

    最近做一個專案,要用到UITableView中cell的多選和全選。  上網簡單一搜索,發現很多小夥伴對於這塊是自己自定義cell且通過程式碼判斷,再去改變UI來實現。很多方法的理論基礎基本上都是自己給cell寫一個屬性來記錄其是否未被選中的狀態,然後單獨用一個字典

Swift:定義UITableViewCell景色

效果 前言 前段時間在整理課件 《UITableView》 章節的時候,看著單元格選中時的背景顏色覺得特別扭,系統給的顏色太過單調,當時想整理一篇修改單元格選中樣式的文章,但一直沒有時間,現在閒下來,終於可以完成了。在實際開發中,系統提供的樣式不能滿足需

iOS手勢識別的詳細使用(拖動,縮放,旋轉,點,手勢依賴,定義手勢)

1、UIGestureRecognizer介紹手勢識別在iOS上非常重要,手勢操作移動裝置的重要特徵,極大的增加了移動裝置使用便捷性。iOS系統在3.2以後,為方便開發這使用一些常用的手勢,提供了UIGestureRecognizer類。手勢識別UIGestureRecogn

IOS控制元件系列二---優雅的UITableView的MVC模式設計,支援定義下拉重新整理/上提載入更檢視(含swift)

demo效果如下: 本小框架設計原則依舊按照之前的慣例: 1.擴充套件性好,程式碼不冗餘(整個重新整理的頭部與底部程式碼不超過300行)。 2.邏輯清晰。 3.回撥介面清晰。 4.移植性好。 對於擴充套件性本框架擴充套件點如下: 1.框架中的

iOS定義可拖動帶點效果的懸浮按鈕

   實現方法是自定義一個UIView,在UIView上新增拖動手勢(UIPanGestureRecognizer)和點選手勢(UITapGestureRecognizer). - (instancetype) initWithFrame:(CGRect)frame

ZABBIX最MYSQL定義監控實例mysql與主從復制狀態沒有之一

等待 獲取 oca 含義 cli ges type con sha 我們首先要提取你服務器上有多少mysql實例提取方法如下: #!/usr/bin/env pythonimport osimport jsont=os.popen("""su

Echarts 定義legend圖片,修改點之後的顏色圖解

第一個問題:echarts 可以自定義圖例的圖示,百度上很多回答都是引用的相對路徑,但是不知道為啥,我的vue專案就是引用不顯示,在network裡面找不到相應圖片 後來我想了個法子,就是先獲取到這個圖片,然後複製它的dataURL 也就是在網頁上解析之後的圖片路徑,就能正常顯示了——————至於原因,em

java簡單部落格系統(二)導航標籤頁點後頁面內容改變及景色改變

一、同一個Servlet處理多個請求,顯示不同的頁面內容 導航標籤頁 bootStrap模板: <ul class="nav nav-tabs"> <li role="presentation" class="active"><a href="#">Home

flutter - 點事件(一) - 定義一個方便的點控制元件

android中,所有View都可以直接setOnClickListener, RN中也有TouchableHightlight這樣的控制元件可以直接套在外面,ios中也可以有UIControl 這樣的控制元件可以直接新增點選事件. 那麼flutter中有嗎? 答案自然是有. Ges

Flutter定義折線圖並新增點事件

前言 最近用Flutter做了一個天氣類的app,我也是新手,對flutter理解還不是很深入,但是開發過程中的程式設計思想給了我很大的啟發。Dart語言特性很優秀,單執行緒模型,非同步io,初始化列表,函式也是物件,鏈式呼叫等等,flutter的設計思想很前衛。好了,馬屁只拍到這裡,下面講一下在開發過程中

C#定義窗體style中 button點事件通過Command傳遞

資源字典中 < Button x:Name="BtnClose" Margin="0,-1.5,-1,0" Style="{DynamicResource ButtonClose}" HorizontalAlignment="Right" Vertic

利用原生js實現定義滾動條(可點到達,拖動到達)

1.HTML檔案 div1是滾動條,div2是滾動小球,div3是文字區域容器,div4是文字區域。 <div id="div"> <div id="div1"> <div id="div2"> </div> </div&

AndroidStudio定義註釋 Edit variables不可點灰色

1,自定義註釋  1.1,Androidstudio 選單欄點選FIle —> Settings —> Editor找到Live Templates             1.2,點選上圖中的右邊的 + 號選擇Template Group,建立一個Templ

js定義右鍵選單,點定義選單隱藏、顯示指定div

       首先寫好自己想要的右鍵選單的樣子,然後設定該選單div為預設隱藏,滑鼠右擊後設置css顯示該選單(display:block;),並禁用瀏覽器右鍵預設選單。 接下來就可以寫選單中具體項的

定義通知欄,並註冊點事件

描述 如題 效果圖 程式碼 /** * function: 自定義通知欄 * Created by wiky on 2016/6/27. */ public class MyNotification { private static f

定義BaseAdapter完成ListView列表單功能

今天在公司寫專案的時候自定義了一個baseAdapter實現listview的單選功能。本人也一直想著寫技術部落格,就以此開頭吧。所以一回到家就開始寫Demo分享給大家。 這裡有幾個需要解決的問題,一是要保留對listview的優化,二是隻能有一個打鉤,沒選擇

定義Drawable(文字按鈕點效果設定)

一些在開發UI時經常需要用到的自定義Drawable的程式碼,整理起來,方便今後高效的開發。 1,單選按鈕、複選框 <?xml version="1.0" encoding="utf-8"?

iOS 深入瞭解定義物件 深拷貝,層次深拷貝

關於iOS的深拷貝,淺拷貝已經有很多文章,不必在過多贅述。有關係統常見可變物件和不可變物件的copy 和 mutableCopy網上有很多文章,一張圖基本上可以說明那麼本文著重要研究的是自定義物件的拷貝問題,特別比如說自定義物件裡面有屬性可以一、物件持有另一個本類的例項物件,

Andriod中定義Dialog樣式的Activity點空白處隱藏軟體盤(Dialog不消失)

一、需求觸發場景: 專案中需要出發帶有EditText的Dialog顯示,要求在編輯完EditText時,點選Dilog的空白處隱藏軟鍵盤。但是Dialog不會消失。示例如下: 二、實現方法: 釋出需求時,我個人曾想過直接通過new的方式直接建立Dialog,經過多次嘗試

jQuery點元素獲取定義屬性的值,利用冒泡原理~

知識鋪墊: attr(“屬性名”); //獲取屬性的值(取得第一個匹配元素的屬性。通過這個方法可以方便的從第一個匹配元素中獲取一個屬性的值。如果元素沒有相應屬性,則返回undefined)