Daha önceki bir yazımda ScrollView bileşeninin nasıl kullanıldığını anlatmış ve gelecekteki bir yazımda bu bileşen yardımıyla iOS ana ekranındaki (home screen) sayfalama işlevseliğinin aynısının nasıl yapılacağını anlatacağımı söylemiştim. Bu yazımda ele alacağım konu tam olarak bu. Her zamanki gibi örnek bir iphone uygulaması yazacağım ancak daha önceki yazımda yazılan şeylerin artık bilindiğini varsayıp orada anlatmış olduğum şeyleri tekrar etmeyeceğim. Örnek uygulamanın her biri basit bir UILabel bileşeni içeren toplam 3 sayfası olacak. Ancak bu sayfalar farklı ViewController'lar tarafından kontrol edilen farklı ekranlarda olmayacak. Tek bir ViewController tarafından kontrol edilen, tek bir ekranda olacak. ScrollView yardımıyla bu tek ekran sanki 3 sayfaymış gibi gösterilecek. Kullanıcıya kaçıncı sayfada olduğu, UIPageControl nesnesinin arayüze koyduğu dairelerle (aynı Home screen'de olduğu gibi) gösterilecek.
Öncelikle View-Based Application taslağını kullanarak yeni bir proje yaratın. Ben projenin adını "Sayfalama" koydum ve dosya isimlerim de ona göre olacak. Bu projede arayüze editörü kullanarak sadece bir UIScrollView ve bir de UIPageControl nesnesi koymak yeterli. Bunu yapmadan önce "SayfalamaViewController.h" adlı Objective-C header dosyasında bu iki nesne için birer Outlet tanımlayın. Sonra bu ViewController ScrollView'ın delegate'i olacağından, UIScrollViewDelegate protokülünü desteklemesi için gereken satırı ekleyin. Bunlara ek olarak ne için kullanacağınızı az sonra söyleyeceğim "sayfaDegistir:" adlı bir metod ve "pageControlKullanildi" adında ve BOOL tipinde bir özellik tanımlayın de. Tüm bu işlemlerden sonra .h dosyasının içi şu hale gelmiş olmalı.
#import <UIKit/UIKit.h>
@interface SayfalamaViewController : UIViewController
<UIScrollViewDelegate>
{
BOOL pageControlKullanildi;
}
@property (nonatomic,retain) IBOutlet UIScrollView *scroller;
@property (nonatomic,retain) IBOutlet UIPageControl *pageControl;
- (IBAction)sayfaDegistir:(id)sender;
@end
Sonra "SayfalamaViewController.m" adlı Objective-C kod dosyasına gerekli @synthesize direktiflerini ve bellek iade satırlarını ekleyerek şu hale getirin.
#import "SayfalamaViewController.h"
#define SAYFA_SAYISI 3
@implementation SayfalamaViewController
@synthesize scroller, pageControl;
- (void)viewDidUnload
{
[super viewDidUnload];
self.scroller = nil;
self.pageControl = nil;
}
- (void)dealloc
{
[scroller release];
[pageControl release];
[super dealloc];
}
Burada söylediklerime ek olarak, bir de SAYFA_SAYISI adında bir tanımlama yaptım. Bu uygulamanın kaç sayfa içereceğini gösteren bir tanımlama. Az sonra sayfalama işlevini yazarken bu tanımlamayı bir kaç kez kullanacaksınız. Böyle ayrı bir tanımlama yapmış olmamın sebebi uygulamanın sayfa sayısını deneme yapabilmek amacıyla kolayca değiştirebilmenizi sağlamaktan öte bir şey değil.
Şimdi "SayfalamaViewController.xib" adlı arayüz dosyasını açıp içerisine bir adet UIScrollView ve bir adet de UIPageControl nesnesi yerleştirerek aşağıdaki hale getirin.
Şimdi her iki bileşen için de Outlet bağlantılarını yapın ve ScrollView'in delegate'i olarak da SayfalamaViewController sınıfını ayarlayın. Sonra ScrollView'in Paging Enabled özelliğini açıp, yatay ve dikey kaydırma çubuklarını gösterme ayarlarını kapatın. Paging Enabled özelliği, ScrollView kendi genişliğinin tam katı olan miktarlarda, yani yeni bir sayfaya geçilecek kadar kaydırıldığında, kaydırma işleminin sonlanmasını sağlıyor. Kaydırma çubuklarını ise gereksiz oldukları için kapattık. Son olarak pageControl nesnesinin Value Changed event'ini, daha önce tanımlamış olduğunuz sayfaDegistir: metoduna bağlayın. Bunu yaptıktan sonra pageControl nesnesinin sol veya sağ tarafına tıkladığınızda bu metod çağrılacak ve sayfa düzgün bir şekilde değişecek.
Sıradaki işiniz, ScrollView içerisinde gösterilecek sayfaları hazırlamak. Bunun için viewDidLoad: metodu en uygun yer. Bu metodu aşağıdaki hale getirin:
- (void)viewDidLoad
{
[super viewDidLoad];
// Kayar panelin içerik boyutunu SAYFA_SAYISI kadar sayfayı alabilecek boyuta getir
scroller.contentSize = CGSizeMake(scroller.frame.size.width * SAYFA_SAYISI, scroller.frame.size.height);
// Her sayfanın içerisine, sayfa numarasını gösteren bir UILabel koy
for (int i=0; i<sayfa_sayisi; i++)
{
UILabel* label = [[[UILabel alloc] init] autorelease];
label.text = [NSString stringWithFormat:@"%d. Sayfa",i+1];
label.font = [UIFont fontWithName:@"Helvetica" size:30];
label.backgroundColor = [UIColor clearColor];
// Label'ı ilgili sayfaya koy
label.frame = CGRectMake(scroller.frame.size.width * i + 100, 200, 200, 50);
// Label'ı kayar panele ekle
[scroller addSubview:label];
}
// pageControl nesnesinin özelliklerini ayarla ve ilk sayfada başladığımızdan emin ol
pageControl.numberOfPages = SAYFA_SAYISI;
pageControl.currentPage = 0;
[self sayfaDegistir:nil];
}
Burada ScrollView'in içerisine sayfa sayısı kadar UILabel nesnesi koyduk. Burada dikkat edilmesi gereken noktalar; ScrollView'in içerik boyutunun tam SAYFA_SAYISI tane ScrollView genişliği kadar yapılması, her Label'ın x koordinatının ilgili sayfanın başladığı x koordinatına göre verilmesi ve pageControl nesnesine sayfalama işlemini düzgün yapabilmesi için ihtiyacı olan değerlerin atanması. Şimdi sıra geldi asıl işi yapan metod olan sayfaDegistir: metoduna.
- (IBAction)sayfaDegistir:(id)sender
{
int sayfa = pageControl.currentPage;
// Kayar paneli ilgili sayfaya kaydır
CGRect frame = scroller.frame;
frame.origin.x = frame.size.width * sayfa;
frame.origin.y = 0;
[scroller scrollRectToVisible:frame animated:YES];
// Kaydırma işleminin UIPageControl nesnesi tarafından başlatıldığını belirten bayrağı 1 yap
pageControlKullanildi = YES;
}
Bu metod pageControl nesnesinin sol veya sağ kısmına basılarak sayfa değiştirilmeye kalkıldığında çağrıldığını biliyoruz. Öncelikle hangi sayfaya gidileceğini pageControl nesnesinden öğrendik. Sonra ScrollView'in içeriğini ilgili sayfayı tam olarak görünür yapacak şekilde yatay eksende kaydırdık. Son satırdaki bayrağı YES yapmamızın sebebi, kaydırma işleminin pageControl nesnesi tarafından başlatıldığı bilgisini kaydetmek. Bu bilgiye neden ihtiyaç duyduğumuzu az sonra göreceksiniz.
Uygulamayı bu haliyle çalıştırırsanız ekranın alt kısmındaki pageControl bileşenini kullanarak sayfalar arasında geçiş yapabildiğinizi görürsünüz. Ancak eğer sayfa çevirme işleminin aynı iOS Home Screen'de olduğu gibi yukarıdaki ScrollView'i kaydırarak da yapılabilmesiniz isterseniz, UIScrollViewDelegate protokolünde bulunan bazı metodların aşağıdaki şekilde implementasyonunu yapmanız gerekli.
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
// Eğer sayfa çevirme işlemi kullanıcının paneli kaydırması ile değil, pageControl nesnesi ile yapılmışsa hiçbir şey yapma
if (pageControlKullanildi) return;
// Önceki yada sonraki sayfanın yarısından fazlası görünür hale gelmişse pageControl nesnesinin sayfa göstergesini güncelle
float pageWidth = scroller.frame.size.width;
int page = floor((scroller.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
pageControlKullanildi = NO;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
pageControlKullanildi = NO;
}
İşte burada pageControlKullanildi bayrağının ne işe yaradığını görüyorsunuz. Eğer kaydırma işlemini pageControl nesnesi başlatmışsa, scollViewDidScroll: metodunda hiçbir şey yapmıyoruz. Çünkü bu metodun içerisinde pageControl nesnesinin sayfa göstergesini güncellenmekte. Eğer pageControl nesnesinin başlatmış olduğu bir kaydırma işlemi sırasında tekrar pageControl nesnesinin değerini güncellersek, tekrar sayfaDegistir: metodu çağrılacak, dolayısıyla tekrar bir kayma işlemi başlatılacak ve bunun üzerine çağrılacak olan scollViewDidScroll: metodunda da tekrar pageControl nesnesinin değeri değişecek. Yani uygulama anlamsız bir kısır döngü içerisine girmiş olacak. İşte o bayrağı bunu engellemek için kullanıyoruz. Kullanıcının kaydırma işlemini kendisi başlattığı ve bıraktığı zamanlarda çağrılacak olan diğer iki delegate metodunda da bayrağı sıfırlıyoruz çünkü artık kaydırma işlemi kullanıcı tarafından yapılmış oluyor, pageControl nesnesi tarafından değil.
Uygulamayı bu son değişiklikle birlikte tamamlamış olduğunuz. Şimdi çalıştırırasanız hem scrollView'i parmağınızla kaydırarak, hem de pageControl nesnesinin sol veya sağ kısmına dokunarak sayfa değiştirebildiğinizi göreceksiniz. Aşağıda uygulamanın son halinden 2 ekran görüntüsü veriyorum. İlki uygulama ilk açıldığındaki halini, diğeri ise sayfa çevrilirkenki halini gösteriyor.