iPhone/iPad uygulamalarında, her bir hücresi derin bir menü sistemi ve onlarca bileşen içeren tablolar görebileceğiniz gibi, 2-3 bileşen içeren hücrelerden oluşan basit tablolar da görebilirsiniz. Aslında uygulamaların geneline bakarsanız, bahsettiğim ikinci türden tabloların çok daha sık kullanıldığını görürsünüz. Kompleks hücre tasarımlarını genellikle Interface Builder ile ayrı bir .xib dosyasında yapmak mantıklıyken, basit hücreler için ayrı dosya oluşturup projei karıştırmaya gerek yoktur. Bu yazıda tablo hücrelerinin içeriğinin isteğe göre nasıl değiştirilebileceğini göstereceğim. Örnek olarak ise her satırında bir tuş ve tuşa basıldığında görünür halden görünmez hale geçen bir tik ikonu içeren bir tablo oluşturacağım.
İlk olarak XCode'u açıp yeni bir proje yaratın. Yaratırken önceki örneklerde olduğu gibi View-based application taslağını kullanın. Ben projenin adını her zamanki gibi "Ornek" verdim. Dosya isimlendirmelerim de ona göre olacak.
Öncelikle "OrnekViewController.h" adlı dosyayı açıp arayüze koyacağınız tablo için bir Outlet tanımlamanız gerekiyor. Ayrıca tablonun göstereceği verileri (bu örnekte meyve isimlerini) tutacak olan NSMutableArray* türünden bir özelliği, tik resmini içerecek olan UIImage* türünden bir özelliği de tanımlanamız gerekiyor. Yapmanız gereken diğer bir şey de tablo hücrelerinin içerisine koyacağınız tuşlara basıldığında çağrılacak olan bir method tanımlamak. Tüm bu dediklerimi yaptıktan sonra dosyanın içeriği şöyle bir şey olmalı.
#import <UIKit/UIKit.h>
@interface OrnekViewController : UIViewController {}
@property (nonatomic, retain) IBOutlet UITableView* tablo;
@property (nonatomic, retain) NSMutableArray* dizi;
@property (nonatomic, retain) UIImage* resim;
-(void)tusaBasildi:(id)sender;
@end
Burası hakkında açıklama yapmama gerek yok çünkü önceki yazılarımı okuduysanız zaten objective-c konusunda en azından bunları anlayabilecek kadar şey biliyorsunuzdur. Sonraki adım ise "OrnekViewController.xib" adlı dosyayı Interface Builder ile açıp arayüze bir tablo koymak ve bu tabloyu tanımlamış olduğunuz Outlet'e bağlamak. Outlet'in Interface Builder içerisinden görülebilmesi için .m dosyasına geçip aşağıdaki satırı
@implementation sözcüğünün olduğu satırdan sonrasına eklemeniz gerekiyor. Tabloyu Outlet'e bağladıktan sonra önceki yazımda anlattığım şekilde dataSource ve delegate bağlantılarını da File's Owner'a bağlayın. Çünkü bu örnekte de tabloya verileri verecek olan nesne, bu .xib dosyasının sahibini, yani OrnekViewController'ı temsil eden File's Owner.
@synthesize tablo,dizi,resim;
Outlet'i tabloya bağladıktan sonra Interface Builder'ı kapatabilirsiniz çünkü bu örnekte onunla daha fazla işiniz yok. Aynı şey .h dosyası için de geçerli.
Uygulamanın her satırda bir tik resmi göstereceğini söylemiştim. Bunu yapabilmek için öncelikle projeye bir tik resmi eklemeniz gerekli. Benim kullandığım tik resmini buradan indirebilirsiniz. Resmi projeye eklemek için ise tek yapmanız gereken XCode'un sol kısmındaki panelde istediğiniz klasör içine sürüklemek. Resmi hangi klasöre yerleştirdiğinizin bir önemi yok ancak mantıklı olan aşağıdaki resimde gösterdiğim gibi "Resources" klasörü altına yerleştirmek.
Çok sayıda resim kullanacağınız durumlarda resimlerle dolu bir klasörü de aynı şekilde projeye ekleyebilirsiniz. Bu yönteme alternatif olarak klasörün üzerinde sağ tuşa tıklayıp Add Existing Files seçeneğini de kullanabilirsiniz. Her iki yöntemde de karşınıza gelen pencereyi aşağıdaki hale getirip Add tuşuna basarsanız resmi projeye eklemiş olursunuz. Eğer resmi zaten proje klasörünüze koymuşsanız en üstteki seçeneği işaretlemenize gerek yok.
Bundan sonra yapmamız gereken her şey .m dosyası içerisinde. O dosyayı tekrar açıp içerdiği gereksiz metodları temizleyin ve aşağıdaki hale getirin.
#import "OrnekViewController.h"
@implementation OrnekViewController
@synthesize tablo,dizi,resim;
- (void)viewDidLoad
{
[super viewDidLoad];
self.dizi = [NSMutableArray arrayWithObjects:@"elma",@"armut",@"portakal",@"çilek",@"kiraz",@"muz",@"karpuz",@"kavun",nil];
self.resim = [UIImage imageNamed:@"tick.png"];
tablo.rowHeight = resim.size.height;
}
- (void)viewDidUnload
{
self.tablo = nil;
}
- (void)dealloc
{
[tablo release];
[dizi release];
[resim release];
[super dealloc];
}
@end
Burada viewDidLoad metodu içerisinde tablonun göstereceği verileri içeren diziyi içeriğini vererek yarattık ve kullanacağımız tik resmini açıp "resim" adlı değişkene attık. Diğer iki metod içerisinde de memory leak yapmamak için gerekli bellek iade etme işlemlerini yaptık. Şimdi sıra geldi tabloya veri kaynağı olabilmek için gereken delegate metodlarını yazmaya.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return dizi.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Hucre";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// Hücrenin içerisine eklenecek resim kutusu ve tuşu yarat
UIImageView* resimKutusu = [[UIImageView alloc] init];
UIButton* tus = [UIButton buttonWithType: UIButtonTypeRoundedRect];
// Resim kutusuna resmi koy
resimKutusu.image = resim;
// Resim kutusu ve tuşu hücreye ekle
[cell.contentView addSubview:resimKutusu];
[cell.contentView addSubview:tus];
// Ekleme işleminden sonra her resim kutusunun 1 azalt
[resimKutusu release];
// Resim kutusu ve tuşun hücre içerisindeki yerini boyutunu ayarla
resimKutusu.frame = CGRectMake(10, 0, resim.size.width, resim.size.height);
tus.frame = CGRectMake((tablo.frame.size.width-100)/2, tablo.rowHeight/4, 100, tablo.rowHeight/2);
}
// Kaçıncı satır için içerik hazırlayacağını öğren
int satirNo = [indexPath indexAtPosition:1];
// Hücredeki tuşa işaretçi yarat
UIButton* satirdakiTus = [cell.contentView.subviews objectAtIndex:1];
// Tuşun üzerindeki yazıyı değiştir
[satirdakiTus setTitle:[dizi objectAtIndex:satirNo] forState:UIControlStateNormal];
return cell;
}
Burada her yeni hücre yaratışımızda (CellIdentifier'e bakarak eskiden yaratılmış olan bir hücreyi kullanırken değil) basabilmek için bir adet tuş (UIButton) ve resim gösterebilmek için de bir adet resim kutusu (UIImageView) türünden 2 obje yarattık. Tüm resim kutuları aynı resmi göstereceği için, resim kutusuna da image özelliği aracılığı ile göstereceği tik resmini verme işlemini bu if bloğunun içerisinde yaptık. Daha sonra her iki objeyi de hücrenin içeriğini belirleyen contentView aldı view'in içine ekledik ve hücre içerisindeki pozisyon ve boyutlarını ayarladık. Hücre yaratma işi bittikten sonra da (if bloğunun dışında) hücreye önceden eklemiş olduğumuz tuşun üzerindeki yazıyı satır numarasına göre değiştirdik.
Önceki yazımdaki örnekte hücrelerin içlerinde varsayılan olarak bulunan textLabel adlı bileşeni kullanarak her satırda bir meyve ismi yazdırmıştık. Bu örnekte ise benzer bir işi kendi eklediğimiz bileşenler ile yapmış olduk. Uygulamayı bu haliyle çalıştırırsanız aşağıdaki gibi bir görüntü ile karşılaşmanız gerekiyor.
Uygulamanın bu halinde tuşlar herhangi bir işe yaramamakta. Şimdi tuşlara basıldığında ilgili satırdaki tikin görünmez olmasını, tekrar basıldığında ise tekrar görünür olmasını sağlayalım. Bunun için hücreyi yarattığınız delegate metodunu, koyu renkle göstermiş olduğum değişiklikleri yaparak şu hale getirin.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Hucre";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// Hücrenin içerisine eklenecek resim kutusu ve tuşu yarat
UIImageView* resimKutusu = [[UIImageView alloc] init];
UIButton* tus = [UIButton buttonWithType: UIButtonTypeRoundedRect];
// Tuşa basıldığında çağrılacak olan fonksiyonu ayarla
[tus addTarget:self action:@selector(tusaBasildi:) forControlEvents:UIControlEventTouchUpInside];
// Resim kutusuna resmi koy
resimKutusu.image = resim;
// Resim kutusu ve tuşu hücreye ekle
[cell.contentView addSubview:resimKutusu];
[cell.contentView addSubview:tus];
// Ekleme işleminden sonra her resim kutusunun 1 azalt
[resimKutusu release];
// Resim kutusu ve tuşun hücre içerisindeki yerini boyutunu ayarla
resimKutusu.frame = CGRectMake(10, 0, resim.size.width, resim.size.height);
tus.frame = CGRectMake((tablo.frame.size.width-100)/2, tablo.rowHeight/4, 100, tablo.rowHeight/2);
}
// Kaçıncı satır için içerik hazırlayacağını öğren
int satirNo = [indexPath indexAtPosition:1];
// Hücredeki tuşa işaretçi yarat
UIButton* satirdakiTus = [cell.contentView.subviews objectAtIndex:1];
// Tuşun üzerindeki yazıyı değiştir
[satirdakiTus setTitle:[dizi objectAtIndex:satirNo] forState:UIControlStateNormal];
satirdakiTus.tag = satirNo;
return cell;
}
Burada yaptığımız değişikliklerden ilki tuşlara
addTarget:forControlEvents: metodu yardımıyla üzerinde basıldığında hangi metodu çağıracağını göstermek oldu. Diğeri ise tuş basıldığında çağrılacak olan metod içerisinden hangi satıra ait tuşa basıldığını anlayabilmek için tuşların
tag (etiket) özelliklerine hangi satırda olduklarını yazmak. Şimdi eksik olan tek şey metodun kendisini aşağıdaki şekilde yazmak.
-(void)tusaBasildi:(id)sender
{
UIButton* basilanTus = sender;
UIImageView* resimKutusu = [basilanTus.superview.subviews objectAtIndex:0];
if (resimKutusu.hidden == YES)
resimKutusu.hidden = NO;
else
resimKutusu.hidden = YES;
}
Buradaki sender parametresi, bu metodu çağırmış olan nesneye işaret etmekte. Bu parametreden yararlanarak basılan tuşu, onun superview özelliği aracılığıyla hücrenin contentView'ini, onun subviews özelliği aracılığı ile de hücre içerisindeki tüm bileşenlerin listesini aldık. Bu liste üzerinde objectAtIndex: metodunu tuşun etiket numarasını parametre olarak verip çağırarak o hücredeki resim kutusuna işaret eden bir işaretçi elde ettik. Bu işaretçiyi kullanarak eğer resim kutusu görünmüyorsa gösterip, görünüyorsa gizledik.
Programı son haliyle çalıştırırsanız artık satırlardaki tik ikonlarının görünürlüklerini, sağ taraflarındaki tuşlara basarak kontrol edebileceğiniz göreceksiniz.