31 October 2012

iOS 6 UICollectionView – Bölüm 1/2

Learn how to use UICollectionView in iOS 6!Ray’in Notu: Bu iOS6 hakkındaki 4. makalemiz. Bu makale iOS 6 By Tutorials kitabımızda yer alan konulardan derlenmiştir. Brandon Trebitowski hem arkadaşım hemde ekibimizin yeni üyesidir.
Bu yazı iOS Tutorial Team member Brandon Trebitowski tarafından yazıldı. Internet istesi adresi brandontreb.com.

Apple 2010 yılında ilk iPad’i çıkardığında belki fark ettmişsinizdir. Photos uygulaması cihazla birlikte geldi. Fotoğrafları göstermek için kendine has bir arayüzü vardı.

Güzel bir grid view şeklinde fotoğrafları gösteriyor:

Albümlerin görünümüde aşağıdaki gibi:

2 görünüm arasında ufak bir parmak hareketiyle geçiş yapabiliyoruz. “Bunu kendi uygulamamda da istiyorum!” diye düşünmüş olabilirsiniz.

Grid view’i veya benzer arayüzleri uygulamalarımıza ekleme şansımız var. Ancak biraz kurnazlık gerekiyor! Doğru görünümü elde edebilmek için epey kod yazmak gerekiyor. Bunun kolay bir yolu yok mu?

İyi haber iOS 6 ile geldi. Apple bu sürüm ile birlikte UICollectionView isimli yeni bir sınıf duyurdu. Bu sınıf Photos uygulaması gibi arayüzleri ve geçişleri kolaylıkla yapmamızı sağlıyor. Aryıca UICollectionView’i istediğimiz gibi özelleştirebiliriz. Buna imkan tanıyor. Dilediğimizi yapma şansımız var.
Son olarak kullanıcılara verileri göstermek için oldukça güçlü bir yöntem. Bu class neredeyse UITableView class’ı kadar önemli ve yardımcıdır. UITableView ile aşınaysanız öğrenmekte zorluk çekmekeceksiniz. Ayrıca datayı kullanmak veya pattern eklemede neredeyse aynı mantıkta çalışır.

Bu makalede kendi oluşturacağımız Grid yapılı fotoğraf uygulaması ile UICollectionView’e değinmeye çalışacağız. Sona geldiğimizde ise UICollectionView hakkında temel bilgileri almış olacağız. Okumaya devam edin!

Etiketler: , , , ,

iOS 6 UICollectionView – Bölüm 2/2

Learn how to use UICollectionView in iOS 6!Ray’in Notu: Bu iOS6 hakkındaki 4. makalemiz. Bu makale iOS 6 By Tutorials kitabımızda yer alan konulardan derlenmiştir. Brandon Trebitowski hem arkadaşım hemde ekibimizin yeni üyesi. Yazımızın 2. bölümünde biraz daha detaylara ineceğiz.
Bu yazı iOS Tutorial Team member Brandon Trebitowski tarafından yazıldı. Internet istesi adresi brandontreb.com.

Header Eklemek

1. yazımızda oluşturduğumuz uygulamamızı dahada geliştirelim. Her bir aramadan sonra bir header olması veya fotoğraf hakkında kullanıcıya biraz daha detay vermek gibi.

Header oluştururken UICollectionReusableView adında yeni bir class kullanacağız. Bunu bir collection view cell gibi de düşünebiliriz. Bu view’i storyboard üzerinde ve kendi class’ına bağlantılı olarak oluşturabiliriz.  Yeni bir class ekleyerek başlayalım:
Menuden FileNewFile…iOSCocoa TouchObjective-C class template‘i seçelim. Adını FlickrPhotoHeaderView koyalım ve UICollectionReusableView’in subclass’ı olarak atayalım. Yeni class’ı oluşturmuş olduk.

Öncelikle oluşturmamız gereken 2 tane outlet var. FlickrPhotoHeaderView.m’i açıp aşağıdaki kodu ekleyelim:

@interface FlickrPhotoHeaderView ()
@property(weak) IBOutlet UIImageView *backgroundImageView; 
@property(weak) IBOutlet UILabel *searchLabel;
@end

Böylece class için 2 tane tanımlama yaptık. UILabel arama kriterini gösterirken, image view’da arkaplanı oluşturacak. Image view’in bir outlet üzerinden bağlantısının olması gerekiyor çünkü boyutu dinamik olarak UILabel’a göre uyarlanacak.

MainStoryboard’ı açıp içindeki collection view’a tıklayalım. Attributes Inspector’i açıp Accessories altındaki Section Header’a tıklayın.

Eğer scene inspector’a bakarsanız, otomatik olarak UICollectionReusableView’in Collection View altına eklendiğini göreceksiniz. UICollectionReusableView’i seçelim ve subview eklemeye başlayalım. Daha rahat çalışmak için view’i 90 pixel genişletelim.
Object Library’den bir image view’i UICollectionReusableView’e sürükleyip bırakalım. Image view’in boyutları çok önemli değil. Ancak merkezde konumlandırılması önemli. Bunu ister guide çizgileri ile ister Editor menusundan yapabilirsiniz. ImageView’in mode ayarını da center yapalım.

Şimdi bir imageView’in üstünde olacak şekilde bir label sürükleyip bırakalım. Font’u 32 birim, merkeze hizalı ve font rengini  mavi seçelim. Görünüm aşağıdaki gibi olmalı:

UICollectionReusableView’in FlickrPhotoHeaderView’in subclass’ı olduğunu belirtip, daha önce oluşturduğumu outlet’leri bağlayacağız.

Scene Inspector’dan Collection Reusable View’a tıklayıp ve Identity Inspector’ü açalım. Class’ı FlickrPhotoHeaderView olarak belirleyelim. Attributes Inspector’ü açıp Identifier değerini FlickrPhotoHeaderView olarak değiştirelim. Bu identifier, view’leri kullanırken işimize yarayacak. Buna ek olarak Attributes Inspector’daki Reuse Identifier değerini de FlickrPhotoHeaderView olarak atayalım. Bu kod tarafında header’ı tanıtmamızı sağlayacak. Şimdi Outlet Inspector’u açıp teker teker backgroundImageView ve searchLabel için uygun outletlere sürükleyip bırakalım.
Uygulamayı çalıştırırsanız header’ı göremeyeceksiniz. Çünkü kod tarafında header için yazdığımız kodu yorum satırı yapmıştık. Bunu düzeltelim:
ViewController.m’i açıp aşağıdaki kodu ekleyelim.

#import "FlickrPhotoHeaderView.h"

Yorum satırlarını kaldıralım ve  collectionView:viewForSupplementaryElementOfKind:atIndexPath: metodunu aşağıdaki gibi değiştirelim.

- (UICollectionReusableView *)collectionView: (UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
    FlickrPhotoHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:
UICollectionElementKindSectionHeader withReuseIdentifier:@"FlickrPhotoHeaderView" forIndexPath:indexPath];
    NSString *searchTerm = self.searches[indexPath.section]; [headerView setSearchText:searchTerm];
    return headerView;
}

Yukarıdaki kod ile her bir arama için bir header oluşmasını sağladık. Aynı zamanda header’in text’i de arama sözcüklerimiz olacak. setSearchText metodunu oluşturmadığımızdan hata alacağız.
In the above code, you dequeue the header view for each section and set the search text for that cell. This tells the collection view which header to display for each section. The setSearchText method is obviously one that you haven’t written yet, so you will see an error. Time to implement it!
FlickrPhotoHeaderView.h ‘i açıp aşağıdaki kodu ekleyerek sorunu giderelim:

-(void)setSearchText:(NSString *)text;

FlickrPhotoHeaderView.m:

-(void)setSearchText:(NSString *)text { 
    self.searchLabel.text = text;
    UIImage *shareButtonImage = [[UIImage imageNamed:@"header_bg.png"] resizableImageWithCapInsets:
    UIEdgeInsetsMake(68, 68, 68, 68)];
    self.backgroundImageView.image = shareButtonImage;
    self.backgroundImageView.center = self.center; 
}

setSearchText metodu arkaplan için UIImage oluştururken label’in text’ini de belirleyecek. Uygulamamızı çalıştıralım.

Cell ile Etkileşim

Makalemizin son bölümünde cell’in parmak hareketlerimize nasıl yanıt verdiğine değineceğiz. Bu noktada 2 türlü sonuç oluşturabiliriz. İlki tıklanan resmin daha büyük bir halini gösteren bir popup açılması, ikincisi ise çoklu seçim ile resimleri email üzerinden paylaşmak.

Tek Seçim

İlk olarak tıklanan resmin daha büyük bir halini gösteren bir popup yapacağız. Bunun için File/New/file menusundan iOS/Cocoa touch/ Objective-c class’ı seçerek yeni bir dosya ekleyelim. Adını FlickrPhotoViewControlker koyalım ve UIViewController’ın subclass’ı olarak atayalım. Cihaz tipi iPad olsun. Bu arada dosyayla birlikte xib’i ekleyen checkbox’u boş bırakalım. Class’ı oluşturup açalım ve içine aşağıdaki kodu ekleyelim (FlickrPhotoViewController.h):

@class FlickrPhoto;
@interface FlickrPhotoViewController : UIViewController @property(nonatomic, strong) 
FlickrPhoto *flickrPhoto; 
@end

Bu property’i popup için kullanacağız. FlickrPhotoViewController.m’i açıp en üste ilgili dosyaları import edelim:

#import "Flickr.h" 
#import "FlickrPhoto.h"

@Interface’de deklarasyonumuzu yapalım:

@property (weak) IBOutlet UIImageView *imageView; 
-(IBAction)done:(id) sender;

Bu outlet image’i görüntüleyecek ve kullanıcı “Done” buttonuna bastığında kapatacak.
Ayrıca kapama işlemi için aşağıdaki metodu ekleyelim:

- (IBAction)done:(id)sender {
    // TODO
}

Şimdi MainStoryboard.storyboard’ı açalım ve Object Library’den bir view controller ekleyelim. Yeni controller’i seçip Identity Inspector’den ilgili class adını FlickrPhotoViewController olarak atayalım. Segue’yi oluşturabilmemiz için main view ile yeni view controller’i bağlamamız gerekiyor. Bunun için main view’i ctrl’ye basılı tutup FlickrPhotoViewController’e bırakın. Açılan popup’tan modal’ı seçip segue işlemini tamamlıyoruz.

bundan sonraki adım ise Segue’yi ayarlamamız gerekiyor. 2 view arasınaki segue’ye tıklayıp Attributes Inspector’ü açalım. Identifier değerini ShowFlickrPhoto, Presentation değerini de Form Sheet olarak atayalım.

Şimdi bir toolbar ve image view’i Flickr Photo view controller’a sürükleyip bırakalım. Toolbar’da yer alan buttonun text’ini “Done” olarak  değiştirelim. Ctrl ile sürükleyip Scene Inspector’daki Flickr Photo View Controller’a bırakalım. Açılan popup’tan from the popup’ı seçelim. Aynı işlemi image view için yapalım ve açılan popup’tan imageView’i seçip daha önce oluşturduğumuz outlet ile bağlantımızı tamamlayalım.

ViewController.m’i açıp aşağıdaki gibi bir property tanımlayalım:

@property (nonatomic) BOOL sharing;

Bu bool değeri ile paylaşım veya büyük görüntüden hangisini istediğimizi ayarlayacağız. true değeri paylaşım, false değeri diğer işlemi sağlayacak. Hangi satıra tıklandığını anlamak için aşağıdaki kodu  collectionView:didSelectItemAtIndexPath: metoduna ekleyelim:

if (!self.sharing) {
    NSString *searchTerm = self.searches[indexPath.section]; 
    FlickrPhoto *photo = self.searchResults[searchTerm][indexPath.row]; 
    [self performSegueWithIdentifier:@"ShowFlickrPhoto"
sender:photo]; 
    [self.collectionView
deselectItemAtIndexPath:indexPath animated:YES]; 
} else {
    // Todo: Multi-Selection
}

Eğer paylaşım (yani koddaki sharing) modu aktif değilse, ShowFlickrPhoto metodu çalışıp ayarlardığımız segue üzerinden resmin büyük halini görüntüleyecek. Ayrıca tıklanan fotoğrafıda sender üzerinden gönderiğimizi de belirtmeliyim. Bu hangi fotoğrafı istediğimizi görüntüleyecek view’e söyleyecek.
Kodun sonunda ise cell seçili olmaktan çıktığında belirginliği kaybolacak (yani highlighted olmayacak).

Son olarak oluşturmamız gereken bir class daha var. Hatırlarsanız segue’nin oluşabilmesi için prepareForSegue metodunun çağırılması gerek. ViewController.m’e aşağıdaki kodu ekleyelim.

#import "FlickrPhotoViewController.h"

Segue’yi oluşturmak için aşağıdaki kodu eklemek yeterli olacak.

#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"ShowFlickrPhoto"]) { 
        FlickrPhotoViewController *flickrPhotoViewController = segue.destinationViewController;         
        flickrPhotoViewController.flickrPhoto = sender;
    } 
}

Özetlersek bu metod FlickrPhotoViewController’in bir instance’ını oluşturup, içinde tanımladığımız FlickrPhoto property’sine gelen fotoğrafı atayacak (sender üzerinden). Bağlantılarımız tamm. Uygulamayı çalıştırıp arama yapalım ve bir resime tıklayalım. Popup açıldı ama resim görüntülenmedi.

FlickrPhotoViewController’e açılan popup’taki image view’e seçilen fotoğrafla ilgili ne yapacağını söylemedik. Bunu gerçekleştirmek için FlickrPhotoViewController.m’i açıp aşağıdaki kodu ekliyoruz.

-(void)viewDidAppear:(BOOL)animated { 
    // 1
    if(self.flickrPhoto.largeImage) {
        self.imageView.image = self.flickrPhoto.largeImage; 
    } else {
        // 2
        self.imageView.image = self.flickrPhoto.thumbnail;
        // 3
        [Flickr loadImageForPhoto:self.flickrPhoto thumbnail:NO completionBlock:^(UIImage *photoImage, NSError *error) {
            if(!error) { // 4
                dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image =
                    self.flickrPhoto.largeImage;
                }); 
            }
        }]; 
    }
}


Koda bakarsak:

  1. Eğer fotoğraf geldiyse bunu imageView’e ata ve göster.
  2. Eğer fotoğraf gelmediyse ufak halini imageView’e ata ve boyutunu ona uyarla (Facebook uygulamasıda bunu yapıyor).
  3. Flickra seçilen fotoğrafın büyük halini almasını söyle.
  4. Eğer bir sorun çıkmadıysa image view’i güncelle.

Uygulamayı tekrar çalıştıralım. Arama yapıp sonuçlara tıkladığınızda bu sefer resimimiz görüntüleniyor.

Not: Eğer resimin görüntülenmesiyle ilgili sorun yaşıyorsanız UIImageView’in şu özelliklerine örneğin 1 gibi ufak bir değer verin: Content Hugging Priority ve Content Compression Resistance Priority.

Bu noktaya kadar herşey tamam. Sadece bir şey popup’taki button hiçbir işe yaramıyor : ) Done: metodunu değiştirmemiz gerek.
FlickrPhotoViewController.m‘i açıp daha önce boş bıraktığımız metodu değiştirelim:

-(void)done:(id)sender { 
    [self.presentingViewController dismissViewControllerAnimated:YES completion:^{}];
}

Böylece button’ımız işlerlik kazanmış oldu.

Çoklu Seçim

Son olarak kullanıcıya birden fazla fotoğraf seçtirip, seçtiklerini mail ile paylaşmasını sağlayacağız. Süreç UITableView’dakine çok benzer. Tek fark aslında collection view’a çoklu seçime izin vermesini söyleyeceğiz.
İşlemi özetlersek:

  1. Kullanıcı Paylaş (örnekte Share) buttonuna bastığında UICollectionView’a çoklu seçimi açmasını söyle ve belirlediğimiz sharing property’sini (BOOL değeri) YES olarak değiştir.
  2. Seçilen fotoğrafları bir diziye at.
  3. Done button’una basıldığında mail gönderme arayüzünü aç.
  4. Seçilen fotoğrafları HTML olarak gösteren email oluştur..
  5. Kullanıcı göndere veya iptal’e bastığında fotoğrafların seçimi kaldır ve collection view’i tek seçim moduna döndür.

Uygulamamızın hafızasını oluşturacak  diziyi oluşturarak başlayalım. ViewController.m’i açıp property’imizi tanımlayalım:

@property(nonatomic, strong) NSMutableArray *selectedPhotos;

ViewDidLoad metodunun altına bu kodu ekleyelim:

self.selectedPhotos = [@[] mutableCopy];

Diziyi oluşturmuş olduk. Şimdi çoklu seçimi aktive edelim. collectionView:didSelectItemAtIndexPath: metodundaki “Todo: Multi-Selection”  yorum satırını silip aşağıdaki kodu ekleyelim:

NSString *searchTerm = self.searches[indexPath.section]; 
FlickrPhoto *photo = self.searchResults[searchTerm][indexPath.row]; 
[self.selectedPhotos addObject:photo];

Bu kod seçilen kodu belirleyip oluşturduğumuz diziye atayacak. collectionView:didDeselectItemAtIndexPath: daki yorum satırının yerine şu kodları ekleyelim:

if (self.sharing) {
    NSString *searchTerm = self.searches[indexPath.section]; 
    FlickrPhoto *photo = self.searchResults[searchTerm][indexPath.row];
    [self.selectedPhotos removeObject:photo]; 
}

bu arada kullanıcı kazara bir fotoğraf seçebileceğinden bunu değiştirmesini yukarıdaki kod ile sağladık.

Şimdi paylaş buttonu (ShareButton) tıklandığında ne olacağını belirtelim. Button’un metodunu aşağıdaki gibi değiştirelim:

-(IBAction)shareButtonTapped:(id)sender {
    UIBarButtonItem *shareButton = (UIBarButtonItem *)sender; 
    // 1
    if (!self.sharing) {
        self.sharing = YES;
        [shareButton setStyle:UIBarButtonItemStyleDone]; 
        [shareButton setTitle:@"Done"];
        [self.collectionView setAllowsMultipleSelection:YES];
    } else { 
        // 2
        self.sharing = NO;
        [shareButton setStyle:UIBarButtonItemStyleBordered]; 
        [shareButton setTitle:@"Share"];     
        [self.collectionView setAllowsMultipleSelection:NO];
        // 3
        if ([self.selectedPhotos count] > 0) { 
            [self showMailComposerAndSend];
        }
        // 4
        for(NSIndexPath *indexPath in self.collectionView.indexPathsForSelectedItems) { 
            [self.collectionView deselectItemAtIndexPath:indexPath animated:NO]; 
        }
        [self.selectedPhotos removeAllObjects]; 
    }
}

Yukarıdaki kodlara bakalım:

  1. Kullanıcı paylaşım modunu açmadıysa (yani bool değeri false iken) bu kod ile UICollectionView’a çoklu seçimi açmasını ve ilk örnekteki done buttonunu share buttonu olarak değiştirmesini söyledik.
  2. Paylaşım modu zaten açılmışsa done buttonunu share olarak değiştir ve çoklu seçimi kapa (if-else döngüsü nedeniyle 1. veya 2. aşamaya geliyoruz).
  3. Kullanıcı herhangi bir fotoğraf seçmişmi diye bak. Seçtiyse showMailComposerAndSend metodunu çağır.
  4. Seçili tüm fotoğrafların seçimini kaldır ve diziyi temizle.

Mail gönderimi için MFMailComposeViewController’ı yani MessageUIFramework’u projeye eklememiz gerekiyor. Bunu yapmadan uygulamamızı çalıştıramayız. Bunu yapmak için projeye  tıklayıp Project Navigator’u açalım. Flickr Search’ü seçelim Build Phases tabına geçelim. Binary With Libraries’i genişletip (+) buttonuna basalım ve MessageUI framework’ü aratıp ekleyelim. (add)

Projemize eklediğimiz MessageUI framework’ü kullanmak için ViewController.m’e gerekli dosyayyı import edelim.

#import <MessageUI/MessageUI.h>

ViewController’i MFMailComposeViewControllerDelegate protokolünü destekleyecek şekilde değiştirelim.

@interface ViewController ()<UITextFieldDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, MFMailComposeViewControllerDelegate>

En alta aşağıdaki metodu ekleyelim:

-(void)showMailComposerAndSend {
    if ([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
        mailer.mailComposeDelegate = self;
        [mailer setSubject:@"Check out these Flickr Photos"];
        NSMutableString *emailBody = [NSMutableString string]; 
        for(FlickrPhoto *flickrPhoto in self.selectedPhotos)
        {
            NSString *url = [Flickr flickrPhotoURLForFlickrPhoto: flickrPhoto size:@"m"];
            [emailBody appendFormat:@"<div><img src='%@'></div><br>",url];
        }
        [mailer setMessageBody:emailBody isHTML:YES];
        [self presentViewController:mailer animated:YES completion:^{}];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Mail Failure" message:@"Your device doesn't support in-app email" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show]; 
    }
}

bu metodda ilk kod bloğu kullanıcının mail atabilirliğini kontrol edecek. Eğer kullanıcı cihazında bir mail hesabı oluşturmadıysa hata verip kullanıcıyı uyaracak. Mail’in içeriği temel html kodları ile görüntülenecek. Mail içeriği ve başlığı oluşunca kullanıcıya mail gönderme ekranı açılır. Burada kullanıcının maili göndermesi veya iptal etmesinde ne olacağını yönetmemiz gerekiyor. Delegate metodu ViewController.m’de mail gönderimi için oluşturalım.

- (void)mailComposeController: (MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    [controller dismissViewControllerAnimated:YES completion:^{}];
}

Artık mail gönderim ekranı işlem bittiğinde kendini kapatacak. Artık uygulamayı çalıştırabiliriz.

Geriye bir tek şey kaldı. Kullanıcı fotoğrafı seçtiğini nasıl anlayacak? Görsel herhangi bir şey olmadığından anlaması imkansız. Bunu da selectedBackgroundView özelliğini değiştirerek sağlayabiliriz.
FlickrPhotoCell.m‘i açalım ve initWithFrame: metodunu silip aşağıdakini ekleyelim:

-(id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 
    if (self) {
        UIView *bgView = [[UIView alloc] initWithFrame:self.backgroundView.frame]; 
        bgView.backgroundColor = [UIColor blueColor]; 
        bgView.layer.borderColor = [[UIColor whiteColor] CGColor]; 
        bgView.layer.borderWidth = 4;
        self.selectedBackgroundView = bgView; 
    }
    return self; 
}

Bu kod ile arkaplanı mavi ve beyaz kenarlığı olan bir view oluşup bunu selectedBackgroundView olarak atayacağız. Ne zaman bir cell seçili hale gelse bu metod tetiklenip arkaplanı değiştirecek.
Uygulamayı çalıştıralım. tüm özellikleri deneyelim. Seçili fotoğraflar aşağıdaki gibi olmalı:

Kusursuz çalışıyor!

Buradan Sonrası ?

Örnek projeyi burayadan indirebilirsiniz.

Tebrikler Flickr Fotoğraf tarayıcınızı UICollectionView ile oluşturmuş oldunuz. UITableView gibi oldukça basit bir kullanıma sahip. 

Eğer daha fazlasını öğrenmek istiyorsanız yeni kitabımız olan iOS 6 by Tutorials a bakabilirsiniz. Uygulamayı kendiniz daha da geliştirebilirsiniz. Bu konuyla ilgili detaylı incelemeleri bulabilirsiniz (örneğin kendi UICollectionView’ımızı oluşturmak).

Sorularınızla ilgili olarak forumumuza katılın!

 Bu yazı iOS Tutorial Team member Brandon Trebitowski tarafından yazıldı. Internet istesi adresi brandontreb.com.

Etiketler: , , , ,

16 October 2012

iOS 6 Auto Layout – Bölüm 2/2

Learn Auto Layout in the iOS 6 SDK!Ray’in notu:  Tebrikler! Başardınız! iOS 6 hakkındaki ikinci makaleye hoşgeldiniz!
Bu makale iOS 6 By Tutorials kitabının bir bölümünü içermektedir. iOS Apprentice Series i yazan Matthijs Hollemans tarafından hazırlanmıştır. Keyfini çıkarın!
Bu yazı iOS geliştiricisi ve tasarımcısı olan Matthijs Hollemans tarafından yazılmıştır.

İlk yazımızda eski Struts ve Springs ile arayüz problemlerini nasıl çözebileceğimizi gördük.iOS 6 ile gelen Auto Layout pek çok soruna daha kolay çözümler getiriyor.

İkinci ve son yazımızda constraintler hakkında daha çok şey öğreneceğiz.

Kalın Constraint’ler

Fark ettiyseniz ekranda görünen bazı T-bar’lar diğerlerine göre daha kalın şekilde gösteriliyor. Böyle görünen contraint’lere User Constraint denir. Diğerlerinin aksine bunları silme şansımız var. Ancak bir user constraint sildiğimizde Interface Builder onun yerine silemeyeceğimiz bir constraint ekler. Nedenini birazdan göreceğiz.

User contraintler Document Outline’da mavi ikonludur:

User constraints document outline

Listeden Vertical Space (40) constraintini seçip silelim. 2 button arasındaki T-Bar artık kayboldu ve yerine ekranın aşağısına kadar uzanan yeni bir tane eklendi:
After deleting user constraint

Bu yeni constraintin ikonu mavi yerine pembe ve yazı tipi de normal tiptedir. Anlamı onu silemeyeceğimizdir. Artık 2 button birbiriyle düşeyde bağlantılı değil. Ancak sol taraftan olan bağlantıları devam ediyor.

Buna neden olay şey nedir? Sistem neden yeni bir constraint ekledi? Yanıtı şu:
Her view için, her zaman, kendisini posizyonunu ve ebatlarını belirleyen yeterli sayıda constraint’i mutlaka olmalıdır.

Konu Auto Layout olunca bu kural herzaman hatırlanması gerekir. Yeterli constraint olmadığında Auto Layout hesap yapamaz. Bu çeşit layoutlar uygunsuzdur. Bunların örneklerine sonra bakacağız.

Interface Builder arayüzün doğru görünebilmesi için epey uğraşır. Buttonlarımızın boyutları, içindeki textler ve genişlikleri bilindiğinden – intrinsic content size (önceki yazımızdan hatırlarsınız – hesaplama yapmak oldukça kolay. Üstteki buttonun x koordinatını biliyoruz ve alttaki button ile sol taraftan hizalı, ayrıca alttaki button her zaman yatay olarak merkeze hizalı. Yani tek bilmediğimiz Y koordinatı.

Her iki buttonda dikey alanda birbiri ile bağlantılı olduğundan Y koordinatını bulabiliriz. Ancak bunu tanımlayan constraint i silerseniz Auto Layout için doğru hesaplama yapmak çok kolay olmayacaktır.

Bunu çözmek için Interface Builder’in bir “pin” e ihtiyacı var.

Pin all the buttons

Neyseki uygulamamızı çalıştırdığımızda bir sorun görünmüyor. Ekran önceki gibi karşımızda olsada tasarım mantığımız burada farklılık gösteriyor: 2 buttonda ekranın altına bağlı. Bunun anlamı eğer alttaki button hareket ederse, üstteki onunla birlikte hareket etmeyecek. (belirtmem gerekirki her 2 çözümde uygun. karar tamamen size ve tasarımınıza kalmış)

Bunu denemek için alt buttonla ekranın altı arasındaki yatay constraint i seçelim. Attributes inspector’dan constraintin değerini autodan 40′a çevirelim

buttonlar bağlı olmadığından sadece alttaki button hareket etti. Üsteki duruyor:
Only bottom button moves up

Fark ettiyseniz değeri değiştirdiğimiz constraint artık User Constraint oldu.

Needle ve pin

Buttonları tekrar bağlayalım. Şuana kadar constraintleri buttonları sürüklememiz sırasında elde ettik. Daha sonrasında da bunları oluşturabiliriz.   Cmd tuşuna basarken 2 buttonu seçelim. Sonra Editor menusundan Pin/Vertical Spacing’i seçelim.

Ayrıca alttaki menuden de bunu yapabiliriz:
Shortcut menu pin

Tıkladığınızda açılan menu:
Pin menu

Hangi yöntemi uygularsak uygulayalım artık yeni constraintimiz var.
Pin vertical spacing

Bu yeni constraint yatay düzlemde ve değeride 20 birim. bunun nedeni buttonlar arası mesafenin 20 birim olması. Eski 104 birimlik constraint hala duruyor. Artık ona ihtiyacımız olmadığından silebilirz. Hatırlarsanız daha önce mavi bir constraint sildiğimizde yerine silinemez pembe constraint atanıyordu. Şuanda böyle bir atama yapılmadı. Çünkü onun yerini doldurabilecek başka bir constraintimiz var. özetle interface builder sadece gerekli olduğunda bu işlemi yapar.

Constraint tablomuz aşağıdaki gibi olmalı:
Restored constraints

Yatay alan constraintini seçelim ve değerini 40 yerine standart olarak değiştirelim. böylece 2 button birden harekete edecek. Çünkü artık birbirlerine bağlılar.

Runtime’da bir gezinti

Şuana kadar temel şeyleri gördük. ancak kontrolleri guide’ları kullanarak hizalamayı, aralarına mesafe belirlemeyi biliyoruz. Daha sonra Align ve Pin menulerini nasıl kullanacağımıza değineceğiz.

Interface builder ile oynamak eğlenceli ama bu işin runtime da nasıl çalıştığına bakalım. Aşağıdaki metodu ViewController.m’e ekleyelim:

- (IBAction)buttonTapped:(UIButton *)sender
{
    if ([[sender titleForState:UIControlStateNormal] isEqualToString:@"X"])
        [sender setTitle:@"A very long title for this button" 
                forState:UIControlStateNormal];
    else
        [sender setTitle:@"X" forState:UIControlStateNormal];
}

Bu metod basit olarak buttonlarımız bir event aracılığı ile konumlarını değiştirecek. Interface builder üzerinden bu metodu buttonlar ile bağlayalım: Ctrl’ye basılı tutup ekrana sürükleyim ve açılan menuden buttonTapped: i seçelim.
Uygulamayı çalıştıralım ve buttonlara bastığımızda nasıl davrandıklarını görelim.
Long and short titles

Hangi buttona basıldığı farketmeksizin constraintlerimiz sayesinde ekranda doğru bir görünüm elde edeceğiz:

  • Alttaki button herzaman yatay olarak ekranın merkezine hizalıdır.
  • Alttaki button her zaman ekranın altından 20 birim yukarıda yer alır.
  • Üstteki button her zaman alttaki buttonun soluna hizalıdır.

Bunlar arayüzümüzün temel bilgileri. Farklı bir şey deneyelim. buttonları seçin Align menusundan Right Edges’i seçip uygulamayı çalıştırın.

Genişliği ayarlamak

Pin menusunde genişliği ayarlayan bir seçenek var. 2 view için bunu seçtiğinizde Auto Layout 2 view’e hemen aynı genişliği verecektir. Deneyelim.

Buttonlarımızı seçelim ve Pin/widths equally’a basalım. Bu işlem her iki buttona bir constraint ekler:
Buttons widths equally

Not: Eğer bu işlem sonucunda fazladan constraint eklenirse, buttonları seçip AlignHorizontal Centers ‘ı seçin.

Bu tipte constraintleri 1. makalemizde görmüştük. Her zamanki T-Bar yerini aldı.

Document Outline’da bu işlem için constraintimiz yerini aldı:
Equal widths in document outline

Bu buttonun içeriğini değiştirmek boyuta etki edecektir.

İçeriği x olarak değiştirdiğinizde 2 buttonun genişliği oldukça kısaldı. Yukarıdaki buttonun text’i artık sığmıyor:
Top button text no longer fits

Peki interface builder hangi buttonun boyutu esas alacağını nereden biliyor? Dikkatli bakarsak hangi buttona atandığını görebiliriz:
Width constraint on truncated button in document outline
Width constraint on truncated button
Interface Builder boyutları aynı tutmak için buttonu boyutunu olması gerekenden kısa olacak şekilde zorlar.

tabiki istediğimiz bu değil. üstteki buttonu seçelim ve Size to Fit Content from the Editor i işaretleyeim. Button şimdi normal halini aldı ve genişliği belirten constraint kayboldu.
Uygulamayı çalıştıralım. içerdikleri textleri ne olursa olsun buttonların boyutları hep aynı:
Buttons equal widths in app

Aslında text boyutu kısa olduğunda buttonlar kendiliğinden ebatlarını ufaltacaktır hem de tam olmaları gerektiği boyuta. Buna ne diyorduk? “Intrinsic content size

Intrinsic Content Size (varsaylan içerik boyutu)

Auto Layout’tan önce kontrollere ne kadar büyük olmaları gerektiği, sınırları vb. özelliklerini söylemek zorunda kalıyorduk. Ancak şuanda çoğu kontrol için mükemmel şekilde çalışıyor.

Bir label kontrolü, ne kadar geniş ve uzun olacağını içerdiği text uzunluğu, font büyüklüğü vb. nedenlerden dolayı bilir. Aynen buttonda olduğu gibi.

Progress Bar gibi kontrollerde ise yüksekliği bilmek mümkün ancak genişliği bilemeyiz. “Intrinsic content size” bunu bilir. Aslında bu konsept Auto Layout için oldukça önemlidir. Buttonlarla ilgli örneklerimizde görmüştük. Auto Layout ekranı doğru şekillendirebilmek için kontrollerimize ne kadar büyük olmaları gerektiğini sorar. Bu bilgilere görede ekranı oluşturur.

Kendimizin yükseklik ve genişlik bilgilerini girdiğimiz durumlarda Auto Layout bu bilgiyi sormaz. Elle boyutu değiştirdiğimizde Interface Builder değerler için constraint atar. Size to Fit Content komutu ile bizim belirlediğmiz değerler ve buna bağlı constraintler kaybolur.

Genellikle intrinsic content size kullanılır. ancak bazı durumlarda bunu kullanmak uygun olmayacaktır. Ekran boyutundan büyük bir boyuta sahip bir resimi UIImageView’e atadığımızı düşünün. Bu durumda resmin boyutunu kendimiz belirleriz.

Peki buttonlardan birinin girilmiş bir genişlik değeri olduğunu düşünün. Buttonlar kendi boyutlarını hesaplar  ancak elle kendimi değer atayabiliriz.   Üstteki buttonu seçelim ve PinWidth tıklayalım. Bu bir T-bar ekler:
Button fixed width constraint

Böylece sadece o button için bir constraint ekledik. Document Outline’dan da görebiliriz. Bu sırada button genişliğini 73 birim olarak belirledik.

Uygulamayı çalıştıralım ve buttonlara basalım. Ne oldu? Buttonun boyutu değişti ancak texti daha uzun olduğundan yeni boyuta sığmadı:

Button text clipped

Çünkü üstteki buttonun belirlenmiş bir genişlik değeri var ve aynı 2 buttonda aynı boyda olma zorunluluğu var.

Note: Muhtemelen tasarım aşamasında genişlik için bir constraint atamayız. En iyisi kendisinin belirlemesi. Ancak arayüzle ilgili bir sorun yaşandığında bunu değiştirebiliriz. Değiştirememiz durumunda constraintlere bakmakta fayda var.

Unutmamamız gereken Auto Layout’un doğru hesaplama yapabilmesi için yeterli sayıda constraint olması gerekiyor.

Got enough constraints

Galeri Örneği

Constraintler hakkında yeterince bilgimiz artık var ve arayüz oluştururken nasıl çalıştıklarını biliyoruz. Buradan sonra örneklerle devam edeceğiz.
Favori programcılarımızı gösteren bir galeri uygulaması yapalım. ekran görünümüde aşağıdaki gibi olsun:
The Gallery app

Ekranı 4 eşit parçadan oluşacak. Her bir çeyreğin bir image view i ve label ı olsun. Bunu nasıl yaparız?

Uygulamamızı yapmaya başlayalım. Eski view ve constraintleri silerek veya yeni bir uygulama açarak başlayalım. Yeni projemizin adı “Galeri” olsun. storyboard’u kapatalım.

ViewController.xib ‘i açalım. Object Library’den bir boş bir view atalım ve boyutunu 160×230 olarak değiştirelim. Arkaplan rengi yeşil olsun:

View with auto layout
Bu view’in 4 tane constrainti var. View, button veya label gibi olmadığından intrinsic content size’ı olmaz. Her bir view için pozisyonu ve ebatları gösteren constraintlerin olması gerekiyor.  Merak edenler için 2 tane yatay 2 tane de düşey constraintimizi document outline’dan görebiliriz:
Constraints for UIView in document outline

Yeşil ekranın genişliği superview’in genişliği eksi constraintler olarak hesaplanır. Ekran boyutu değiştiğinde formule göre yeniden hesaplama yapılır. Ekran genişliği 320×460’tan 480×300 olarak değişir. Uygulamayı çalıştırıp ekranı döndürdüğünüzde değişikliği kendinizde görebilirsiniz.

Üstteki view’i seçip Attribute inspector’a gelin. Simulated Metrics’den Orientation değerini Landscape olarak değiştirin:

Simulated metrics landscape

Bu bize ekran döndürüldüğünde view’in nasıl görüneceğini göstermiş olacak. Yeşil view kendi boyutlarını uygun şekilde ayarladı. Orientation değerini portrait’e çevirelim.

Not: Boş viewleri neden oluşturacağımızın 2 temel nedeni var.
a) Diğer viewlerin içeriğini düzenlememize imkan verecekler.
b) Yertutucu olduklarından kendi yazdığımız class, UIView veya UIControl class’larını atayabiliriz.

Ekran döndürüldüğünde view’in değişmesini istemediğimiz durumlarda constraintlere kendimiz değer atamamız yeterli olacaktır. Bunu deneyelim. View’i seçin sırayla Pin menusunden height ve width’i tıklayın.
Böylece 2 tane yeni constraint eklemiş olduk. Width yani genişlik değeri 160 birim, height yani yükseklik değeri ise 230 birim:

Width and height constraints on UIView

Document outline’dan view’e atanmış bu değerleri görebiliriz. Genellikle constraintler 2 farklı view arasındaki ilişkiyi açıklar. örneğin yeşil view ile onu taşıyan gri superview arasındaki düşey ve yatay constraintler – bu değerleri view ve superview arasındaki boy ve genişlik bağlantısı olarak kabul edebilirsiniz.

Uygulamayı çalıştıralım. Portrait modda doğru görünüm var. Ancak ekranı döndürdüğümüzde istediğimizi elde edemedik. View boyutunu yine değiştirdi ve Xcode’dan bir hata aldık:

Gallery[68932:11303] Unable to simultaneously satisfy constraints.
	Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "",
    "",
    "",
    "",
    ""
)
Will attempt to recover by breaking constraint 
 
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in &lt;UIKit/UIView.h&gt; may also be helpful.

Hatırlarsanız Auto Layout’un hesaplamayı yapabilmesi için yeterli constraint olmalıydı. Bizim örneğimizde ise gereğinden fazla constrainte sahibiz! “Unable to simultaneously satisfy constraints” uyarısının anlamı constraintler arasında bir çakışma var demektir.

Constraintlere bir daha bakalım:
Conflicting constraints

Yeşil view için 6 tane constraint var. 4 tane boşluklar için önceden verdiğimiz ve 2 tane az önce eklediğimiz boy ve genişlik için olan constraintler. Peki karışıklık nerden çıkıyor?

Portrait modda herhangi bir problem yok çünkü işlem doğru hesaplanıyor. Superview (gri) in genişliği 320 birim. yatay alan ve genişlik değerlerini topladığımızda 320′yi (51 + 160 + 109 = 320 ) elde ediyoruz.   Ayrıca düşey değerler ise benzer şekilde en fazla 460 birim olmalı.

Ancak ekranı döndürdüğümüzde Auto Layout hangi değeri alacağını bilemiyor. Karşılaştığımız sorun bizim geniş değerini veya margin değerlerinden biri kendimizin belirlemesi. Sorunu çözmek için bazılarını silmeliyiz. Örneğimizden devam edersek uygulamanın doğru görünebilmesi için (her iki modda) yapacağımız değişiklik: yatay boşluk değeri gitmeli: Tasarım ekranından önce yatay boşluğu sonra da view’in altında yer alan  yatay alan’ı silelim. Ekran aşağıdaki gibi olmalı:

Conflicting constraints fixed

Şimdi view doğru sayıda constrainte sahip. Ne eksik ne fazla. Uygulamayı çalıştıralım ve hata mesajı alıp almadığımızı görelim. Hata mesajı kayboldu ve görünüm 2 modda da doğru.

Note: Interface Builder gerçekten doğru görünümü elde edebilmemiz için yoğun uğraş verir.  ancak mucize yaratmasını beklemeyin. En azından Auto Layout detaylı hata mesajları vererek sorun olduğunu gösterir. Bu hatalarla ilgili detayları sonraki yazılarımızda inceleyeceğiz.

Görünümü Boyamak

Yeşil view içerisine bir label atalım. Guide’lar bize yerleştirme için yardım oluyor. Çünkü view’imiz label için superview’dir.
Drag label into green view

Label’i ekrandaki gibi konumlandırdığınızda label’i ekranın sol-üst bölümüne bağlayan bir 2 constraint eklenir:

Label constraints

Bu constraintlerin yeşil view’imizin altında gösterildiğini (document outline’da) unutmayalım.

Şimdi yeşil view’in yerini değiştirip görüntüdeki gibi yerleştirelim. View’e ait constraintlerin değiştiğini görebilirsiniz. ancak label için birşey değişmedi. Label aynı yerde durmaya devam ediyor.

Lebel’ı da görüntüdeki gibi alt bölüme hizalayıp konumlandıralım. Yeni bir image view’i sürükleyip bırakalım:
Image view in gallery
Image view, ekranın sağ sol ve üst bölümüne pinlendi. Ancak alt bölümü standart boşluk nedeniyle label’a bağlı.

Bu örnek için gereken ek dosyaları buradan indirebilirsiniz. Zip’i açıp açılan klasörü projenin içine dahil edelim. Ray.png dosyasını image view’imiz için seçelim. Aspet Fit’i seçip ve arkaplan rengini beyaz yapalım. Label’in text’ “Ray” olsun.

Arayüz aşağıdaki gibi olmalı:
Gallery with Ray

Bu arada Interface Builder label’a bir yükseklik constraint’i ekledi. Bu image olarak bir resim verdiğimiz anda gerçekleşti.

Label fixed height

Interface Builder layouttaki belirsizlikleri önlemeye çalışır. Image view’de ve label’da bir yükseklik değeri belirlememiş olsak Auto Layout hesaplamayı yapamaz. (Interface builder şuan için bu durum dikkate almadı   çünkü yeterli sayıda constraint’imiz var)

Diyelimki bir noktada yeşil view’imiz 100 birim daha uzun oldu. Auto Layout bu yeni birim genişliği nasıl dağıtacak? Label aynı kalırken image view’mi 100 birim genişleyecek? veya label genişlerken image view aynı mı kalacak? 100 birim ikisine eşit oranmı paylaştırılacak? veya farklı bir orandamı dağıtılacak?

Auto Layout bu soruların cevabını vermez ama Interface Builder bu problemi label ve image view’e sabit bir boy değeri vererek çözer.
Not:
Bu sorunun aslında çözümü label’ın “Content Compression Resistance Priority” değerini değiştirmek. Bunun detaylarına sonra bakacağız. Şimdi Size inspector’a gelip label için vertical Content Compression Resistance Priority değerini 751 yapalım. boy için verilen constraint kaybolur.

Diğer resimleri ekleyelim

Yeşil view’i ekranın sol üst köşesine taşıyalım. Ekranın kenarına yerleştiğinden constraint hala var. ancak değeri 0 – bu değer ekranda gördüğünüz gibi çizgilerle gösterilir:
View in top-left corner

Gördüğünüz gibi view kenara yaslıda olsa hala onu bağlayan bir constraint değerine ihtiyacı var. Değeri sıfır bile olsa.

yeşil view’i seçip Cmd-D ile çoğaltalım. yeni view’i sağa yaslayalım.

Green view in top-right corner

2 yeni daha view açıp alt köşelere hizalayalım. Arkaplanlarını da değiştirelim:

Gallery design

Gayet yakışıklı programcılar değilmi =)

Uygulamayı çalıştıralım. Portrait görünümde gayet iyi. ancak landscape modda iyi görünmüyor:
Gallery looks bad in landscape

Sorunun nedeni belli. Boy ve genişlik için elle değer girdiğimizden view’lar her zaman aynı boy ve genişlikte kalmak istiyor. Document Outline’dan genişlik(160) ve boy(230) değerlerini içeren constraintleri tüm view’ler için silelim. Uygulamayı çalıştıralım:
Still looks bad in landscape

Oldukça kötü. Problemi çözdüğümüzü sandık ancak yapmamız gereken başka şey daha var. 4 view’ide seçip Pin menusundan sırasıyla Widths Equally ve Heights equally’i seçin. Uygulamayı çalıştırdığımızda ekranı döndürün. Hiçbir değişiklik olmadı değilmi ?

Ekran görüntüsüne bakarsanız 4 view’inde aynı boyu oldupunu ve aynı genişlikte olduğunu göreceksiniz (yeşil ve kahverengi view’ler altta kalmış). Yine constraintlerle ilgili bir sorun var. Sadece boy ve genişlik değil. Başka bir tane.
Neyseki view’lerdeki constraintlere bakarsanız yatay ve dikey alanlar için olan constraintlerin görünümü zorladıklarını görebilirsiniz:
Bad H-space

Daha kötüsü bu constraintleri silemiyoruz. T-bar kalın ve mavi değil. Interface Builder problem olmasın diye yerleştirmiş.  Neden bunu yaptığının yanıtı ise 4 view’de eşit ölçülerde olmalı ancak hesaplama için yeterli constraint bulunmuyor. Bu nedenle Auto Layout hesaplamayı, view’lar arasındaki bağlantıyı (örneğin “Ray” ve “Matthijs”) çözemediğinden tam olarak yapamıyor. Auto Layout bunu çözemiyorsa bizim ona yardımcı olmamız gerek:

To be related ,

Ray ve Matthijs viewlerini seçelim ve Pin menusunden Horizonal Spacing i seçelim. Çünkü yanyanalar ve aralarına yatay bir constraint Auto Layout’un hesaplamasına ve aralarında bağlantı olduğunu bilmesi içi yeterli olacaktır.

Önemli: Interface Builder constraintleri eklediğimiz zaman kendi oluşturduklarını silmez. Ancak onu User Constraint’e çevrirsek yapılabilir. Çevirmeden silmeyi denersek “Unable to simultaneously satisfy constraints” hatası alırız.
Uygulamayı çalıştıralım:
Landscape a bit better

Biraz daha düzgün. 4 view’de eşit genişlikte. ancak boyları hala eşit değil. Çözüm neredeyse aynı. Ray ve Dennis Ritchie viewleri arasında düşey constraint ekleyerek birbirine bağlayalım. Uygulamayı çalıştırdığımızda bu kez istediğimizi elde ettik:

Gallery landscape OK

Fark ettiyseniz “Dennis Ritchie” label’i image view’in ortasına denk gelmiyor. Aslında bu durum text’i girdiğimizden bu yana var. Label her nekadar ortalanmış olsada Interface Builder bunu değiştirmeyi uygun gördü. Bunu düzeltmek için Align menusunden Horizonal Center’i seçin.

image view hakkında ufak bir not: Kendimiz değer girmediğimiz için boyutları otomatik olarak değişti. image view bu durumda landscape moda sığmaz. Eğer image view’in aspect ratio’da kalmasını istiyorsanız hiç şansınız yok. Interface builder ile bunu yapamayız:
Aspect ratio on images

Maalesef Interface Builder aspect ratio’yu korumak için bir çalışma yapmaz. Bunu yapabilmek için kod yazmamız gerekiyor. Bunu Auto Layout hakkındaki sonraki yazılarımızda işleyeceğiz.

İpucu: Daha önce arayüzün nasıl görüneceği ile ilgili önizleme yapmak için Simulated Metrics altındaki Orientation setting’i kullanmıştık.

Ekranın tamamını seçelim. Simulated Metrics, atındaki Size değerini Freeform olarak atayalım. Bu ana ekranı istediğimiz gibi şekillendirmemizi sağlayacak. Auto Layout arayüz için tekrar hesap yapar:
Freeform

Bunu kullanırken dikkatli olmamız gerekiyor. Bazen Interface Builder boyutları ayarlamak için yeni constraintler ekleyebilir. Bu nedenle bazen ekran sınırlarına taşmalar yaşanabilir.

Bundan sonrası?

Buraya kadar geldiyseniz – tebrikler! – Auto Layout hakknda epey şey öğrendik. Ancak öğrenecek daha çok şey var.
Bu makale ile iOS 6 by Tutorials kitabındaki Auto Layout hakkındaki bilgilerin bir bölümünü inceledik. 2. bölüm daha gerçekçi örnekleri ve bilmemiz gereken şeyleri içeriyor olacak. Ancak tüm tasarım araçları gibi Interface Builder’inde belirli sınırları var ve bu sınırlar NSLayoutConstraints objeleriyle kod tarafından uğraşmayı gerektiriyor. Eğer daha derine inmek istiyorsanız kitabımızı alabilirsiniz!
 

Bu yazı iOS geliştiricisi ve tasarımcısı olan Matthijs Hollemans tarafından yazılmıştır.

Etiketler: , , , , , ,

12 October 2012

iOS 6 Auto Layout – Bölüm 1/2

Learn Auto Layout in the iOS 6 SDK!Ray’in notu:  Tebrikler! Başardınız! iOS 6 hakkındaki ilk makaleye hoşgeldiniz!
Bu makale iOS 6 By Tutorials kitabının bir bölümünü içermektedir. iOS Apprentice Series i yazan Matthijs Hollemans tarafından hazırlanmıştır. Keyfini çıkarın!
Bu yazı iOS geliştiricisi ve tasarımcısı olan Matthijs Hollemans tarafından yazılmıştır.
—-

Uygulamanızın güzel görünmesi için çabalamaktan hiç yoruldunuz mu? Hem iPhone hemde iPad için arayüz hazırlamak sizi deliye çeviriyor mu? Eğer öyleyse sizin için iyi haberlerimiz var!!

Aynı boyuta sahip ekranlar için arayüz tasarlamak büyük bir problem değil. Ancak bazı durumlarda arayüzümüz kendini yeni boyutlara da uyarlamak zorunda kalabilir. Bugüne kadar eğer arayüzünüz
mantıklı bir nedenden ötürü karmaşık bir yapı taşıyorsa, ciddi miktarda kod yazmak zorunda kalıyorduk. Bu makalemizi okuyunca mutlu olacaksınız. iOS 6 iPhone ve iPad için yeni bir özellik taşıyor: Auto Layout.

Auto Layout sadece farklı ebatlardaki ekranlara destek vermekle kalmıyor ayrıca belli durumlar içinde globalleştirmeyide kendisi yapabiliyor.
Artık desteklenen her dil için farklı bir storyboard yapmak gerekmiyor ve ibranice ve Arapça gibi sağdan yazmalı diller içinde kolaylık sağlıyor.

Bu makale ile size Interface Builder ile Auto Layout hazırlanmasını göstereceğiz. Auto Layout ile ustalaşmaya hazır olun. Okumaya devam edin!

Etiketler: , , , , , ,