1.給tableView設(shè)置背景view
UIImageView *backImageView=[[UIImageViewalloc]initWithFrame:self.view.bounds];
[backImageView setImage:[UIImageimageNamed:@"liaotianbeijing"]];
self.tableView.backgroundView=backImageView;
2.讓cell透明
-(UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"METext"forIndexPath:indexPath];
cell.backgroundColor=[UIColor clearColor];//關(guān)鍵語句
[cell setCellInfo:dic];//自定義類目方法
return cell;
}
UITableView 總結(jié)
UITableView是UIScrollView的子類,因此它可以自動響應(yīng)滾動事件(一般為上下滾動)。
它內(nèi)部包含0到多個UITableViewCell對象,每個table cell展示各自的內(nèi)容。當(dāng)新cell需要被顯示時,就會調(diào)用tableView:cellForRowAtIndexPath:方法來獲取或創(chuàng)建一個cell;而不可視時,它又會被釋放。由此可見,同一時間其實只需要存在一屏幕的cell對象即可,不需要為每一行創(chuàng)建一個cell。
1.協(xié)議介紹
UITableViewDataSource(11)
//每個section下cell的個數(shù)(必須實現(xiàn))
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//通過indexpath返回具體的cell(必須實現(xiàn)) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
//返回有多少個section(默認(rèn)是1)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
//每個section上面的標(biāo)語內(nèi)容 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
//每個section下面的標(biāo)語內(nèi)容 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// Editing
//是否可編輯
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
// Moving/reordering
// 是否可拖拽
-tableView:moveRowAtIndexPath:toIndexPath:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
// Index
//右側(cè)索引條需要的數(shù)組內(nèi)容
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// return list of section titles to display in section index view (e.g. "ABCD...Z#")
//索引值對應(yīng)的section-index
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - insert and delete support
// 對Cell編輯后的回調(diào)
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// 對Cell拖拽后的回調(diào)
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
UITableViewDelegate(常用)
//將要展示Cell/header/Footer視圖回調(diào)
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
//完成展示Cell/header/Footer視圖回調(diào) - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell )cell forRowAtIndexPath:(NSIndexPath)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// Variable height support
// 每個cell高度的返回(這里高度通過協(xié)議返回,是為了table能準(zhǔn)確的定位出要顯示的Cell-index,從而滿足UITableView的重用機(jī)制)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 每個section-header高度的返回 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
// 每個section-footer高度的返回 - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
// Section header & footer information. Views are preferred over title should you decide to provide both
//可返回每個section-header的自定義視圖
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; // custom view for header. will be adjusted to default or specified header height
//可返回每個section-footer的自定義視圖 - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; // custom view for footer. will be adjusted to default or specified footer height
// Selection
// Cell高亮的回調(diào),一般式在選擇的時候才高亮
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
// Cell選中和取消選擇的回調(diào)
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// Called after the user changes the selection. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
UITableViewDelegate中的協(xié)議還有很多,我只列出了比較常用的,想知道更多的可以查看官方頭文件或官方文檔
分割線:separator 復(fù)制粘貼:Copy/Paste 拖拽:move 索引:index 編輯:editing
2.刷新
下拉刷新:
第三方:EGORefreshTableHeaderView
官方提供(ios6以上系統(tǒng)):UIRefreshControl
UIRefreshControl使用方法非常簡單:
UIRefreshControl * _refresh;
/******內(nèi)置刷新的常用屬性設(shè)置******/
_refresh = [[UIRefreshControl alloc] init];
_refresh.tintColor = [UIColor grayColor];
[_refresh addTarget:self action:@selector(pullToRefresh) forControlEvents:UIControlEventValueChanged];
[_tableView addSubview:_refresh];
另外UITableViewController中已經(jīng)自帶了UIRefreshControl 為成員變量,只需要增加猝發(fā)時間就可以了
上拉刷新
1.第三方:EGORefreshTableFooterView
2.自加按鈕:
-
(void) initTableFooterView
{
/******自定義查看更多屬性設(shè)置******/
if(_bottomRefresh==nil){
_bottomRefresh = [UIButton buttonWithType:UIButtonTypeCustom];
[_bottomRefresh setTitle:LocalizedString(@"c_loading") forState:UIControlStateNormal];
[_bottomRefresh setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[_bottomRefresh setContentEdgeInsets:UIEdgeInsetsMake(0, 0, 5, 0)];
[_bottomRefresh.titleLabel setFont:[UIFont systemFontOfSize:15]];
[_bottomRefresh addTarget:self action:@selector(upToRefresh) forControlEvents:UIControlEventTouchUpInside];
_bottomRefresh.frame = CGRectMake(0, 0, 320, 44);
_activityView= [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(90 , 3, 30, 30)];
[_activityView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[_activityView stopAnimating];
[_bottomRefresh addSubview:_activityView];
[_bottomRefresh setHidden:YES];
[_tableView setTableFooterView:_bottomRefresh];
}
3.視圖滾到最后直接加載更多:-
(void)scrollViewDidScroll:(UIScrollView *)scrollView {
int contentHeight=scrollView.contentSize.height;
int offsetY=scrollView.contentOffset.y;
if(contentHeight>0 && offsetY>0 && offsetY > (contentHeight - scrollView.frame.size.height)){
if(!_isGetMore && !_isNoMore &&!_isUpdate){ //判斷是否在加載中或者加載為空,不然或多次加載過多
[self upToRefresh];
}
}
3.搜索在xib中拖入search Bar and Search Display控件,實現(xiàn)UISearchBarDelegate協(xié)議
-
pragma mark SearchDisplayController DelegateMethod
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self CONTAINS %@", searchString];
if (_searchList)
{
_searchList = nil;
}
_searchList = [NSMutableArray arrayWithArray:[_dataList filteredArrayUsingPredicate:predicate]];
return YES;
}
pragma mark TableView DataSource and Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return _searchList.count;
}
else
{
return _rowCount;
}
}
不用xib的話,可以直接添加代碼
_bSearchBar = [[UISearchBar alloc] init];
_bSearchBar.delegate = self;
[_bSearchBar setPlaceholder:@"搜索"];
CGSize size = [_bSearchBar sizeThatFits:_tableView.bounds.size];
_bSearchBar.frame = CGRectMake(0, 0, size.width, size.height);
_tableView.tableHeaderView = _byxSearchBar;
_bSearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:_bSearchBar contentsController:self];
_bSearchDisplayController.searchResultsDataSource = self;
_bSearchDisplayController.searchResultsDelegate = self;
_bSearchDisplayController.delegate = self;
_bSearchDisplayController.searchResultsTitle = @"";
_bSearchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
demo: https://github.com/Jonear/iosDemo/tree/master/TableViewFresh
4.重用
UItableView對Cell有一套重用機(jī)制,他會將滾出屏幕外的cell放到一個隊列中,滾入屏幕的會從這個隊列中獲取cell,如果沒有再去創(chuàng)建。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @" cellIdentifier ";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:windowReuseIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:windowReuseIdentifier];
}
return cell;
}
自定義cell
新建cell文件,繼承UITableViewCell
如果你沒使用xib或者storyboard的話可以在直接new一個cell,跟普通寫法一樣
1. 新建cell文件,繼承UITableViewCell
2. 如果你沒使用xib或者storyboard的話可以在直接new一個cell,跟普通寫法一樣
static NSString *cellid = @"cellIdentifier";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid];
if (!cell) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid];
}
3. 如果有xib
static NSString *CellIdentifier = @"FriendCell";
FriendCell *cell= [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
[tableView registerNib:[UINib nibWithNibName:@"FriendCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
4.還有個未必好的辦法(這個辦法也用于在xib多個view中獲取到想要的一個)
static NSString *reuseId = @"headCell";
NADHeadArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
if (!cell) {
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:@"NADHeadArticleCell" owner:self options:nil];
for(id oneObject in nib){
if([oneObject isKindOfClass:[NADHeadArticleCell class]]){
cell = (NADHeadArticleCell *)oneObject;
break;
}
}
}
不使用重用方法
方法1 將獲得cell的方法從- (UITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier 換為-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
重用機(jī)制調(diào)用的就是dequeueReusableCellWithIdentifier這個方法,方法的意思就是“出列可重用的cell”,因而只要將它換為cellForRowAtIndexPath(只從要更新的cell的那一行取出cell),就可以不使用重用機(jī)制,因而問題就可以得到解決,雖然可能會浪費(fèi)一些空間。
第一個方法如果使用下面插入多次可能會有問題:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
方法2 通過為每個cell指定不同的重用標(biāo)識符(reuseIdentifier)來解決。
重用機(jī)制是根據(jù)相同的標(biāo)識符來重用cell的,標(biāo)識符不同的cell不能彼此重用。于是我們將每個cell的標(biāo)識符都設(shè)置為不同(@"CMainCell%d", indexPath.row)
方法3 刪除重用cell的所有子視圖
這個方法是通過刪除重用的cell的所有子視圖,從而得到一個沒有特殊格式的cell。
方法4:為不重用的單元格單獨生成單獨的cell,而不是重用隊列中的單元格。
注冊Cell
// Beginning in iOS 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
- (void)registerNib:(UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
- (void)registerClass:(Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
簡單講就是注冊完cell后,使用
dequeueReusableCellWithIdentifier:forIndexPath:
一定會有返回cell,系統(tǒng)在默認(rèn)沒有cell可復(fù)用的時候自動new一個cell出來。
5.編輯
//是否可編輯
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
//返回編輯的類型1.沒有2.刪除3.插入
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
//刪除提示文本
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
//編輯完成
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
滑動更多
繼承UITableViewCell,重新初始化方法
- (void)initializer {
int height=self.bounds.size.height;
UIScrollView *cellScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), height)];
cellScrollView.contentSize = CGSizeMake(self.bounds.size.width+BTN_WIDTH, height);
cellScrollView.delegate = self;
cellScrollView.showsHorizontalScrollIndicator = NO;
[cellScrollView setBounces:NO];
[cellScrollView setPagingEnabled:YES];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewPressed:)];
[cellScrollView addGestureRecognizer:tapGestureRecognizer];
self.cellScrollView = cellScrollView;
UIButton * deleteButton=[[UIButton alloc] initWithFrame:CGRectMake(320, 0, BTN_WIDTH, height-3)];
[deleteButton setTitle:LocalizedString(@"c_delete") forState:UIControlStateNormal];
[deleteButton setImage:[UIImage imageNamed:@"trash"] forState:UIControlStateNormal];
[deleteButton setImage:[UIImage imageNamed:@"trash"] forState:UIControlStateHighlighted];
[deleteButton.titleLabel setFont:[UIFont systemFontOfSize:12]];
[deleteButton setBackgroundColor:color_with_rgb(211, 49, 49)];
[deleteButton setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 15)];
[deleteButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
[deleteButton addTarget:self action:@selector(onDeleteCell) forControlEvents:UIControlEventTouchUpInside];
[self.cellScrollView addSubview:deleteButton];
UIView *scrollViewContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), height)];
scrollViewContentView.backgroundColor = [UIColor whiteColor];
self.scrollViewContentView = scrollViewContentView;
[self.cellScrollView addSubview:scrollViewContentView];
UIView *contentViewParent = self;
if (![NSStringFromClass([[self.subviews objectAtIndex:0] class]) isEqualToString:@"UITableViewCellContentView"]) {
// iOS 7
contentViewParent = [self.subviews objectAtIndex:0];
}
NSArray *cellSubviews = [contentViewParent subviews];
[self insertSubview:cellScrollView atIndex:0];
for (UIView *subview in cellSubviews) {
[self.scrollViewContentView addSubview:subview];
}
[self insertSubview:self.cellScrollView atIndex:0];
}
demo:http://code4app.com/ios/SWTableViewCell/5269d9376803fa5367000001
6.優(yōu)化
1.最好改造原生的tableViewCell,盡量不要用xib自定制cell,可以盡量在drawRect中繪制
2.盡量使用重用機(jī)制,不要創(chuàng)建太多cell
3.盡量不要使用透明視圖,和layer改造
4.重載共同部分可以放在生成Cell部分
5.盡量不要老調(diào)用reloaddata,可能的情況下可以考慮使用
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0);
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
-(void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath NS_AVAILABLE_IOS(5_0);