IOS UITableView中行的操作

這篇文章主要講的表格的操作包括:標記行、移動行、刪除行、插入行。

這次就不從頭建立工程了,在http://www.oschina.net/code/snippet_164134_9876下載工程。這個工程就是最簡單的產生一個表格並向其中寫入數據。用Xcode 4.2打開它,在這個工程基礎上實現以上操作。

1、標記行

這裏講的標記行指的是單擊此行,可以實現在此行右邊出現一個勾,如下圖所示:

爲了實現標記功能,在ViewController.m中@end之前添加代碼:

#pragma mark -
#pragma mark Table Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *oneCell = [tableView cellForRowAtIndexPath: indexPath];
    if (oneCell.accessoryType == UITableViewCellAccessoryNone) {
        oneCell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else 
        oneCell.accessoryType = UITableViewCellAccessoryNone;
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 
}

該代碼實現:單擊某行時,若此行未被標記,則標記此行;若此行已經被標記,則取消標記。

運行效果如上圖。

上面的代碼實際上就是修改某行的accessoryType屬性,這個屬性可以設爲四個常量:

UITableViewCellAccessoryCheckmark
UITableViewCellAccessoryDetailDisclosureButton
UITableViewCellAccessoryDisclosureIndicator
UITableViewCellAccessoryNone

效果依次如下圖所示:

            

   UITableViewCellAccessoryCheckmark            UITableViewCellAccessoryDetailDisclosureButton

                

UITableViewCellAccessoryDisclosureIndicator                   UITableViewCellAccessoryNone

注意,上面第二張圖片中的藍色圓圈不僅僅是一個圖標,還是一個控件,點擊它可以觸發事件,在上一篇博客《iOS開發16:使用Navigation Controller切換視圖》使用過。

2、移動行

想要實現移動或者刪除行這樣的操作,需要啓動表格的編輯模式。使用的是setEditing:animated:方法。

2.1 打開ViewController.xib,將其中的表格控件映射成Outlet到ViewController.h,名稱爲myTableView。

2.2 打開ViewController.m,在viewDidLoad方法最後添加代碼:

//啓動表格的編輯模式
[self.myTableView setEditing:YES animated:YES];

2.3 在@end之前添加代碼:

//打開編輯模式後,默認情況下每行左邊會出現紅的刪除按鈕,這個方法就是關閉這些按鈕的
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
           editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 
    return UITableViewCellEditingStyleNone; 
} 

//這個方法用來告訴表格 這一行是否可以移動
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 
    return YES; 
}

//這個方法就是執行移動操作的
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)
        sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    NSUInteger fromRow = [sourceIndexPath row]; 
    NSUInteger toRow = [destinationIndexPath row]; 
    
    id object = [list objectAtIndex:fromRow]; 
    [list removeObjectAtIndex:fromRow]; 
    [list insertObject:object atIndex:toRow]; 
}

editingStyleForRowAtIndexPath這個方法中用到了常量UITableViewCellEditingStyleNone,它表示不可編輯,這裏的編輯指的是刪除和插入。表示表格行的編輯模式的常量有:

UITableViewCellEditingStyleDelete
UITableViewCellEditingStyleInsert
UITableViewCellEditingStyleNone

顧名思義,第一個表示刪除,第二個表示插入,第三個表示不可編輯。

若將editingStyleForRowAtIndexPath方法中的UITableViewCellEditingStyleNone依次換成上面三個值,則它們運行的效果依次如下圖所示:

    

2.4 運行,從下圖可以看到實現了行的移動:

但是也會發現,現在無法對每行進行標記了。這說明,在編輯模式下,無法選擇行,從而didSelectRowAtIndexPath這個方法不會執行。

3、刪除行

從第2步過來,實現刪除某行,其實比較簡單了。

3.1將editingStyleForRowAtIndexPath方法中的UITableViewCellEditingStyleNone修改成UITableViewCellEditingStyleDelete。

3.2 在@end之前添加代碼:

//這個方法根據參數editingStyle是UITableViewCellEditingStyleDelete
//還是UITableViewCellEditingStyleDelete執行刪除或者插入
- (void)tableView:(UITableView *)tableView commitEditingStyle:
    (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.list removeObjectAtIndex:row]; 
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationAutomatic]; 
    }
}

在這個方法中又出現了一個常量:UITableViewRowAnimationAutomatic,它表示刪除時的效果,類似的常量還有:

UITableViewRowAnimationAutomatic
UITableViewRowAnimationTop
UITableViewRowAnimationBottom
UITableViewRowAnimationLeft
UITableViewRowAnimationRight
UITableViewRowAnimationMiddle
UITableViewRowAnimationFade
UITableViewRowAnimationNone

它們的效果就不一一介紹了,可以在實際使用時試試。

3.3 運行,看看效果:

    

剛運行時顯示如左邊的圖片,點擊某一行左邊的圓圈圖標,會顯示如中間圖片所示。然後點擊Delegate按鈕,那一行就會被刪除掉,如右邊的那張圖片所示,它顯示的是刪除時的效果。

4、插入行

這個與刪除行類似。

4.1 首先將editingStyleForRowAtIndexPath方法中的UITableViewCellEditingStyleDelete修改成UITableViewCellEditingStyleInsert。

4.2在3.2添加的方法中添加代碼:

else {
    //我們實現的是在所選行的位置插入一行,因此直接使用了參數indexPath
    NSArray *insertIndexPaths = [NSArray arrayWithObjects:indexPath,nil];
    //同樣,將數據加到list中,用的row
    [self.list insertObject:@"新添加的行" atIndex:row];
    [tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
}

上面的代碼中也可以不用insertRowsAtIndexPaths方法,而直接使用[tableView reloadData];語句,但是這樣就沒有添加的效果了。

4.3 好了,運行一下:

    

剛運行時如上面左圖所示,單擊了某個加號後,新的一行就從右邊飛進來了,因爲在insertRowsAtIndexPaths中用了參數UITableViewRowAnimationRight。

UITableView每個cell之間的默認分割線如何去掉

很簡單,只需要

tableView.separatorStyle = NO;


UITableView

-、建立 UITableView

 DataTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 420)];
 [DataTable setDelegate:self];
 [DataTable setDataSource:self];
 [self.view addSubview:DataTable];
 [DataTable release];


二、UITableView各Method說明

 


//Section總數
- (NSArray *)sectionIndexTitlesForTableView:(UITableView*)tableView{
 return TitleData;
}


// Section Titles
//每個section顯示的標題
- (NSString *)tableView:(UITableView *)tableViewtitleForHeaderInSection:(NSInteger)section{
 return @"";
}


//指定有多少個分區(Section),默認爲1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
 return 4;
}


//指定每個分區中有多少行,默認爲1
- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section{
}


//繪製Cell
-(UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier =@"SimpleTableIdentifier";
  
   UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:
                            SimpleTableIdentifier];
    if (cell ==nil) {  
       cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier: SimpleTableIdentifier] autorelease];
 }
 cell.imageView.image=image;//未選cell時的圖片
 cell.imageView.highlightedImage=highlightImage;//選中cell後的圖片
 cell.text=//.....
 return cell;
}


//行縮進
-(NSInteger)tableView:(UITableView *)tableViewindentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{
 NSUInteger row = [indexPath row];
 return row;
}


//改變行的高度
- (CGFloat)tableView:(UITableView *)tableViewheightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return40;
}


//定位
[TopicsTable setContentOffset:CGPointMake(0, promiseNum * 44 +Chapter * 20)];


//返回當前所選cell
NSIndexPath *ip = [NSIndexPath indexPathForRow:rowinSection:section];
[TopicsTable selectRowAtIndexPath:ip animated:YESscrollPosition:UITableViewScrollPositionNone];


[tableViewsetSeparatorStyle:UITableViewCellSelectionStyleNone];


//選中Cell響應事件
- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath{

 [tableView deselectRowAtIndexPath:indexPathanimated:YES];//選中後的反顯顏色即刻消失
}


//判斷選中的行(阻止選中第一行)
-(NSIndexPath *)tableView:(UITableView *)tableViewwillSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUIntegerrow = [indexPath row];
    if (row ==0)
       return nil;
   
    returnindexPath;
}


//划動cell是否出現del按鈕
- (BOOL)tableView:(UITableView *)tableViewcanEditRowAtIndexPath:(NSIndexPath *)indexPath {
}


//編輯狀態
- (void)tableView:(UITableView *)tableViewcommitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{


[topicsTable setContentSize:CGSizeMake(0,controller.promiseNum *44)];
//右側添加一個索引表
- (NSArray *)sectionIndexTitlesForTableView:(UITableView*)tableView{
}

//返回Section標題內容
- (NSString *)tableView:(UITableView *)tableViewtitleForHeaderInSection:(NSInteger)section{
}

//自定義划動時del按鈕內容
- (NSString *)tableView:(UITableView *)tableView
titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath*)indexPath


//跳到指的row or section
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0inSection:0] atScrollPosition:UITableViewScrollPositionBottomanimated:NO];

 

三、在UITableViewCell上建立UILable多行顯示

- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {
    staticNSString *CellIdentifier =@"Cell";   
   UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell ==nil) {
       cell = [[[UITableViewCell alloc] initWithFrame:CGRectZeroreuseIdentifier:CellIdentifier] autorelease];
  UILabel *Datalabel = [[UILabelalloc] initWithFrame:CGRectMake(10, 0, 320, 44)];
  [Datalabel setTag:100];
  Datalabel.autoresizingMask =UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
  [cell.contentViewaddSubview:Datalabel];
  [Datalabel release];
 } 
 UILabel *Datalabel = (UILabel *)[cell.contentViewviewWithTag:100];
 [Datalabel setFont:[UIFontboldSystemFontOfSize:18]];
 Datalabel.text = [data.DataArrayobjectAtIndex:indexPath.row];
 cell.accessoryType =UITableViewCellAccessoryDisclosureIndicator;
    returncell;
}

 

 

//選中cell時的顏色

typedef enum {
   UITableViewCellSelectionStyleNone,
   UITableViewCellSelectionStyleBlue,
   UITableViewCellSelectionStyleGray
} UITableViewCellSelectionStyle

 

//cell右邊按鈕格式

typedef enum {
 
  UITableViewCellAccessoryNone,                  // don't show any accessory view
   UITableViewCellAccessoryDisclosureIndicator,   // regular chevron. doesn't track
   UITableViewCellAccessoryDetailDisclosureButton, // blue button w/chevron. tracks
   UITableViewCellAccessoryCheckmark              // checkmark. doesn't track
} UITableViewCellAccessoryType

 

//是否加換行線

typedef enum {
   UITableViewCellSeparatorStyleNone,
   UITableViewCellSeparatorStyleSingleLine
} UITableViewCellSeparatorStyle

 

//改變換行線顏色

tableView.separatorColor =[UIColor blueColor];


解決自定義UITableViewCell在瀏覽中出現數據行重複的問題

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://ddkangfu.blog.51cto.com/311989/

       我在寫一個App的時候自定義了一個UITableViewCell,但是這個UITableView在運行的時候出現了每6行數據就循環重複顯示的問題,而直接使用cell.textLabel.text顯示是沒有這個問題,以下是我實現的代碼。

[plain] view plaincopy
  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath    
  2. {   
  3.     NSInteger section = [indexPath section];   
  4.     NSInteger row = [indexPath row];   
  5.     UITableViewCell *cell;   
  6.    
  7.     switch (section)   
  8.     {   
  9.         case 0:   
  10.       //do something.   
  11.         case 1:   
  12.             cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];   
  13.             if (cell == nil)   
  14.             {   
  15.                 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease];   
  16.    
  17.                 //Image   
  18.                 UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 14.0f, 45.0f, 50.0f)];   
  19.                 image.backgroundColor = [UIColor clearColor];   
  20.                 image.image = [UIImage imageNamed:@"folder.png"];   
  21.                 [cell.contentView addSubview:image];   
  22.                 [image release];   
  23.                 //Label   
  24.                 UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(45.0f, 6.0f, 214.0f, 50.0f)];   
  25.                 titleLabel.text = (NSString *)[(NSArray *)[self.categoryArray objectAtIndex:1] objectAtIndex:row];   
  26.                 NSLog(@"%@ -- %d", titleLabel.text, row);   
  27.                 titleLabel.textAlignment = UITextAlignmentLeft;   
  28.                 titleLabel.numberOfLines = 3;   
  29.                 titleLabel.tag = 201;   
  30.                 titleLabel.font = [UIFont boldSystemFontOfSize:14];   
  31.                 [cell.contentView addSubview:titleLabel];   
  32.                 [titleLabel release];   
  33.             }   
  34.             cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;   
  35.             break;   
  36.     }   
  37.    
  38.     cell.selectionStyle = UITableViewCellSelectionStyleNone;   
  39.     return cell;   
  40. }   

google了一下,目前已有的解決方案是將

[plain] view plaincopy
  1. cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];   

替換成

[plain] view plaincopy
  1. cell = [tableView cellForRowAtIndexPath:indexPath];   

或者

[plain] view plaincopy
  1. cell = nil;   

這們做的目的去掉Cell的重用機制,但是這種方法都會在後臺隨着表格滾動一直在創建cell,通過上面源代碼中Label定義裏那句NSLog在控制檯輸出就可以看到,雖然會自動回收內存,但肯定也會給系統帶來不小開銷,所以不到萬一得以還是不會用的。

還有一種解決方案是自己定義Cell數組,在tableView:tableView cellForRowAtIndexPath:中進設置要顯示的cell,這是手工維護cell的一種方式,對大數據量的情況肯定是不適用的,不過也能算得上是一種思路吧,可以參考一下。其代碼如下:

[plain] view plaincopy
  1. //在構造函數裏定義cell數組   
  2. for(int i = 0; i < 31; i ++)                                                                                        
  3. {                                                                                                                   
  4.     static NSString *MyBookMarkIdentifier = @"CityMangerCell";                                                          
  5.     cityCell[i] = [[CityMangerCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyBookMarkIdentifier initIndex:i];   
  6. }                                                                                                                   
  7.    
  8. //使用它   
  9. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   
  10. {                                                                                                        
  11.     if((0 <= indexPath.row) && (indexPath.row < 31))                                                         
  12.      return cityCell[indexPath.row];                                                                       
  13.     return nil;                                                                                              
  14. }   

後來我仔細分析了一下程序,找到了問題所在:

原因是在if (cell == nil)判斷內部不應該對其label進行賦值,即不使用這句:

[plain] view plaincopy
  1. titleLabel.text = (NSString *)[(NSArray *)[self.categoryArray objectAtIndex:1] objectAtIndex:row];   

正確的做法應該是在if (cell == nil){}判斷後面進行賦值。即

[plain] view plaincopy
  1. if (cell == nil)                                                                             
  2. {                                                                                            
  3.     ....                                                                                     
  4. }                                                                                            
  5. UILabel *l1 = (UILabel *)[cell.contentView viewWithTag: 201];                                
  6. l1.text = (NSString *)[(NSArray *)[self.categoryArray objectAtIndex:1] objectAtIndex:row];   

分析原因如下:
UITableView中被實例化的cell個數由屏高和每個cell的高度決定,因爲我的cell高度設置爲80,一屏只能 顯示6個Cell(只有6個cell被實例化),也就是隻有這6個cell纔會執行if (cell == nil){}中的代碼,從第6行往後的cell都是重用的這6個cell,也就是說從第7行開始將不會執行if (cell = nil){}中的代碼,當UITableView需要繪製第7行cell的時候,會取得第1個cell進行重用,如果我們不把原來第1行cell中的 Label內容進行修改,那麼第7行將完全顯示第1行中的內容,所以纔會在第6行之後開始出現數據重複的情況。
現在我將Label內容設置的代碼放到if (cell == nil){}之後,它將會對每一個被重用的cell的Label進行設定,也就不會再出現cell內容重複的現象。
希望這個問題的解決過程會對大家有所幫助。這個問題解決出自 “一葉障目” 博客,請務必保留此出處http://ddkangfu.blog.51cto.com/311989/465557

  1. 1.系統默認的顏色設置  
  1. //無色  
  2. cell.selectionStyle = UITableViewCellSelectionStyleNone;  
  3.   
  4. //藍色  
  5. cell.selectionStyle = UITableViewCellSelectionStyleBlue;  
  6.   
  7. //灰色  
  8. cell.selectionStyle = UITableViewCellSelectionStyleGray;  


2.自定義顏色和背景設置

 改變UITableViewCell選中時背景色:

UIColor *color = [[UIColoralloc]initWithRed:0.0green:0.0blue:0.0alpha:1];//通過RGB來定義自己的顏色

[html] view plaincopy
  1. cell.selectedBackgroundView = [[[UIView alloc] initWithFrame:cell.frame] autorelease];  
  2. cell.selectedBackgroundView.backgroundColor = [UIColor xxxxxx];  

3自定義UITableViewCell選中時背景

[html] view plaincopy
  1. cell.selectedBackgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cellart.png"]] autorelease];   
  2. 還有字體顏色   
  3. cell.textLabel.highlightedTextColor = [UIColor xxxcolor];  [cell.textLabel setTextColor:color];//設置cell的字體的顏色  

4.設置tableViewCell間的分割線的顏色


[theTableView setSeparatorColor:[UIColor xxxx ]];


5、設置cell中字體的顏色

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  if(0 == indexPath.row)
  {
    cell.textLabel.textColor = ...;
    cell.textLabel.highlightedTextColor = ...;
  }
  ...
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章