en

hi, it seems you are using microsoft internet explorer. it doesn't match web standard and causes problems browsing this site. please please please use mozilla firefox or google chrome instead. thank you!

zh

哦哦!您正在使用Internet Explorer 瀏覽器,它與我們的網頁標準並不相容,可能會導致畫面顯示不正常。
請改用 Mozilla Firefox 或者 Google Chrome 才能正常瀏覽本網站,謝謝!

2.17.2012

改變 UITableView 外觀的方法

  

UITableView 所製作出來的應用程式在使用上多半大同小異,它們之間最大的不同還是在表格的呈現方面,如何設計出具有獨特外觀的 UITableView,才是令人頭痛的問題,通常是選擇製作一個全新的 UITableViewCell 來使用,但是你也可以採用比較簡單的做法,使用內建的方法函式來做些微的改變,方式如下。


Table View
整個 Table View 能改變的東西實在不多,多半都是更改背景,但是當你更改背景顏色之後就會發現 Cell 與 Cell 之間會多出一條白線 Separator,你可以參考下列程式碼改變它的顏色或是移除不顯示。
//改變Separator顏色
[self.tableView setSeparatorColor:[UIColor orangeColor]];

//移除Separator
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];


Table View Cell
Table View Cell 本身就提供一些不同的類型可供選擇,如下圖,你可以藉由選擇不同的類型來改變文字在 Cell 中編排的方式。

Attributes 中的 Style 屬性

另外如果想要在 Cell 中增加其它元件時,可以使用 addSubview 的方法函式來添加新的元件,例如在下列程式碼中,除了設定左右的圖像之外,還自行新增了一個 UILabel 放在其中。
//設定文字背景為透明
[cell.textLabel setBackgroundColor:[UIColor clearColor]];

//設定Cell中左邊的圖片
cell.imageView.image = [UIImage imageNamed:[[heroicaArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row + 1]];

//設定Cell中右邊的連結圖片
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dice.png"]];

//增加UILabel
UILabel *subtitle = [[UILabel alloc] initWithFrame:CGRectMake(95.0, 45.0, 200.0, 20.0)];
[subtitle setTextColor:[UIColor colorWithHue:1.0 saturation:1.0 brightness:1.0 alpha:0.5]];
[subtitle setBackgroundColor:[UIColor clearColor]];
[subtitle setFont:[UIFont systemFontOfSize:12.0]];
[subtitle setText:@"還可以放注解唷"];

[cell addSubview:subtitle];

//設定背景
[cell setBackgroundView:[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellBG.png"]]];


Section
透過下列內建的方法函式,可以自行更改 Section 的標題內容。
//設定開頭的分類樣式
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *sectionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 30)];
    [sectionView setBackgroundColor:[UIColor brownColor]];

    //增加UILabel
    UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 18)];
    [text setTextColor:[UIColor blackColor]];
    [text setBackgroundColor:[UIColor clearColor]];
    [text setText:[[heroicaArray objectAtIndex:section] objectAtIndex:0]];
    [text setFont:[UIFont boldSystemFontOfSize:16.0]];

    [sectionView addSubview:text];
    return sectionView;
}

//設定結尾的分類樣式
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
}


Section Index
表格分類的快速索引雖然沒有內建的方法函式可供設定外觀使用,但是你仍然可以透過自製的索引介面並配合下列程式碼,將表格切換到所想要的分類上。
CGRect sectionRect = [self.tableView rectForSection:1];
[self.tableView scrollRectToVisible:sectionRect animated:YES];


備註
如果表格個對應的資料結構有任何問題,可以在「索引式搜索」中的「元件設定」分類裡找到所有有關 UITableView 的文章,查閱其他有關表格的設定方式。






11 則留言:

  1. hi 牛奶
    請問個問題
    我資料庫是用sqlite 我用tableview 顯示出 資料庫內資料及照片網址!並秀出照片在cellimage 現在遇到run 時候會卡卡的~書上寫用NSURLConnection 非同步下載
    有人建議用AFNetwork 是否可以給個方向!因為照片url 都在資料庫 所以是不是用NSURLConnection就行~感覺AFNetwork 對我初學者有點難@@以下是我程式碼
    我不太曉得加入NSURLConnection 後怎把網址導向 CellImage感謝//設定圖片的url位址
    NSURL *url = [NSURL URLWithString:[[custs objectAtIndex:indexPath.row] objectForKey:@"photo1"]];

    //使用NSData的方法將影像指定給UIImage
    UIImage *urlImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:url]];

    // 從url產生Http request物件
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    // 準備建立連線
    NSURLConnection* connection =
    [[NSURLConnection alloc]
    initWithRequest:request delegate:self startImmediately:YES];
    // 檢視連線是否順利生成
    if (connection) {
    // 生成則初始化m_data準備接收
    m_data = [NSMutableData data];
    } else {
    // 沒有辦法生成則產生警告訊息
    UIAlertView* alertView =
    [[UIAlertView alloc] initWithTitle:@"連線失敗"
    message:@"無法建立連線"
    delegate:nil
    cancelButtonTitle:@"OK"
    otherButtonTitles:nil, nil];
    [alertView show];

    UIImageView* cellAccessoryView = [[UIImageView alloc]initWithImage:urlImage];
    // 設定這個View的大小和使用者行為
    cellAccessoryView.userInteractionEnabled = YES;
    [cellAccessoryView setFrame:CGRectMake(0, 0, 100, 80)];
    // 設定這個View為cell的accessoryView
    cell.accessoryView = cellAccessoryView;
    return cell;
    }
    -(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // m_status.text = @"下載中";
    [m_data appendData:data];

    }

    回覆刪除
    回覆
    1. Bryan Chen 您好

      我覺得你原來這樣就很好了,不太需要使用到 NSURLConnection,NSURLConnection 是適用在http 協定下的東西,既然你已經決定使用 SQLite,就是按照您程式碼所寫的這樣做。

      你的問題應該是在「秀出照片在cellimage 現在遇到run 時候會卡卡的」,沒錯吧。

      解決這個問題,你可以考慮使用較小的縮圖讓傳給你的device,或是採用非同步的方式,像是只顯示(抓取)目前所顯示範圍的縮圖預覽等等來減少傳輸量,
      如果採用同步的方式來實作,最好是製作一個loading畫面來做緩衝,讓device取得所有圖片放置在陣列中再一次顯示。

      另外,AFNetwork 的層級比起 NSURLConnection要高的許多,如果你只是要做基本的取值動作,不是很建議使用這麼龐大的 framework,還是建議針對你device的動作自己寫一個對應的 class ,比較恰當。

      刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. 所以我應該針對下載動作 做非同步 方式 另外做一個 class 然後再把下載完資料倒入 tableview Cell Image 內 加上個loading 圖示緩衝 這樣我進到tableview畫面 既使還沒下載完成 我上下拉畫面 就會順暢不會卡 這樣沒錯吧~~另外確認一下 「非同步下載」是寫到另一個class 不要寫在 tableview 裡面 對嗎

    感謝您指導

    回覆刪除
  4. 今天早上 看另一方式 // 需要等下载完才顯示圖片 但可以進入畫面
    NSString *url2=[[custs objectAtIndex:indexPath.row] objectForKey:@"photo1"];


    UIImageFromURL( [NSURL URLWithString:url2], ^( UIImage * image )
    {
    cell.ImageView.image=image;
    NSLog(@"%@",image);
    }, ^(void){
    NSLog(@"error!");
    });

    畫面跑起來比以前順多了~
    可是有些小圖在更新時會重複出現別的cell圖示 ~等於是我只有指定一張圖網址沒下載前跑出別的網址圖 ~ 我想是不是要加個下載中顯示預設圖 就可以搞定><晚點試試

    回覆刪除
    回覆
    1. 感覺好像沒什麼太大的改變,「需要等下载完才顯示圖片」這本身就是使用url載入圖片的機制之一喔。

      刪除
  5. 拍謝~牛大在跟您請教一下~關於上次卡卡的問題~我用NSURLConnection執行
    程式碼如下跑起來不會卡卡了~可是關於這句NSURL* url = [NSURL URLWithString:[[custs objectAtIndex:0] objectForKey: @"photo1"]];
    因為我只有objectAtIndex:0 所以只下載 0 欄位 photo1的網址圖~所以目前模擬器跑出來都是同一張圖~
    我因該怎改才能把所有欄位圖下載並分配到cell裡面~之前在tableView裡面可以用 //NSURL *url = [NSURL URLWithString:[[custs objectAtIndex:indexPath.row] objectForKey:@"photo1"]]; 就會抓取所有圖到指定cell 可是現在輸入NSURL* url = [NSURL URLWithString:[[custs objectAtIndex:indexPath.row] objectForKey: @"photo1"]];
    是不行的因為不在tableView裡面@@
    ~~感謝麻煩指導一下


    -(void) beginDownload {
    // 取得圖檔的URL

    NSURL* url = [NSURL URLWithString:[[custs objectAtIndex:0] objectForKey: @"photo1"]];


    // 從url產生Http request物件
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    // 準備建立連線
    NSURLConnection* connection =
    [[NSURLConnection alloc]
    initWithRequest:request delegate:self startImmediately:YES];
    // 檢視連線是否順利生成
    if (connection) {
    // 生成則初始化m_data準備接收
    m_data = [NSMutableData data];
    } else {
    // 沒有辦法生成則產生警告訊息
    UIAlertView* alertView =
    [[UIAlertView alloc] initWithTitle:@"連線失敗"
    message:@"無法建立連線"
    delegate:nil
    cancelButtonTitle:@"OK"
    otherButtonTitles:nil, nil];
    [alertView show];

    }

    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    //顯示影像
    cell.mainImage.image = [UIImage imageWithData:m_data];
    return cell;
    }

    回覆刪除
    回覆
    1. 您好:

      你的邏輯有點怪怪的,你不寫在 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 這個函式裡,又想分別設定每個 cell,會有點麻煩,你可以回去看看這一篇「UITableView 的資料設定方式」一文:
      http://furnacedigital.blogspot.tw/2012/01/uitableview.html

      在設定表格裡面的每個項目時,系統會根據你表格項目的多寡來決定要執行多少次上述的函式,所以你必須在此函式中分別設定你的 cell。

      你可以選擇程式一直行就先抓圖,將影像存放到陣列,在上述式中分別設定這陣列中的片到 cell 中。
      另一中方式,是直接在上述函式中呼叫下載影像的function,逐一下載每張圖片,分別設定。

      刪除
  6. 您好~

    感謝您的文章,很實用!

    不過遇到一點小問題,我有一個NSMutableArray要分兩段

    照步驟都沒問題,直到要自訂Section的時候

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {
    }
    開頭時會多出一個Section,可是我只要兩個
    像是如下圖:
    ----
    Section1
    ----
    | Row1 |
    | Row2 |
    ----
    Section2
    ----
    |Row11|
    ----
    Section3
    ----
    |Row21|
    |Row22|

    如何才能把Section1拿掉又能自訂Section?

    感謝您~

    回覆刪除
    回覆
    1. chen-en Wu 您好:

      定義 Section的外觀參考本篇實作應該是沒有太大的問題,你的問題應該是出現在最上頭又多出一個 Section tag,解決方法你可以參考「UITableView 的分類顯示 Sections」一文。
      http://furnacedigital.blogspot.tw/2012/02/uitableview-sections.html

      在文中將 case 0: 的部分,也就是第一個遇到的 Section tag 拿掉即可(此方法只是不設定文字,但是padding依然存在)。

      另一個方式就是分兩個table繪製了!

      刪除
    2. 了解!
      有試過您說的拿掉case 0: 不過還是會有padding :(

      來試試看說的繪製兩個table
      感謝您的解答!

      刪除