Programlı olarak düzen kısıtlamaları oluşturma


84

Pek çok insanın bu konuda zaten tonlarca soru sorduğunu biliyorum, ancak cevaplarla bile işe yaramıyorum.

Film şeridindeki kısıtlamalarla uğraşırken, bu kolay ama kodda zor zamanlar geçiriyorum. Örneğin sağ tarafta kalan ve ekran yönüne göre ekran yüksekliği olan bir görünüme sahip olmaya çalışıyorum. Bu benim kodum:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

Bazı kısıtlamaları karşılamıyor. Neyin yanlış olduğunu görmüyorum. Ayrıca, neden self.myViewyerel değişken yerine gibi bir özelliği kullanamıyorum myView?


Yukarıdaki kodda vivi nedir?
iDev

14
Lütfen başlığı "IOS" yerine "iOS" olarak değiştirin - İkincisi, Cisco'nun anahtar / yönlendirici işletim sistemini ifade eder. Kafam karıştı. Teşekkürler.
armani

1
Bununla ilgili birkaç soru: (1) "Bazı kısıtlamaları karşılamadığında" hangi hatayı alıyorsunuz? (2) Otomatik yeniden boyutlandırmayı kısıtlamalara çeviriyor musunuz myView? (3) Ne vivi(ACB'nin sorduğu gibi)? (4) myViewBeyan edilen bir malınız var selfmı?
Tim

1
ih Tim, vivi için çok üzgünüm, çok hızlı dokundum ... bu myView. Çeviri derken neyi kastediyorsunuz? Tek yaptığım şey yukarıdaki kodda. Mülk hakkında, mülk olarak bildirilen başka görünümlerim var ama aynı kodu bu mülke uyguladığımda çöküyor ... "hata" mesajı gerçekten büyük, buraya yapıştıramıyorum
pierre23

Belirli bir görünümden kısıtlamaları geçici olarak kaldırmak için, bu stackoverflow.com/questions/13388104/…
Sam B

Yanıtlar:


106

Kodda Otomatik Yerleşim kullanılırken çerçevenin ayarlanması hiçbir şey yapmaz. Dolayısıyla, yukarıdaki görünümde 200'lük bir genişlik belirlemiş olmanız, üzerinde kısıtlamalar koyduğunuzda hiçbir şey ifade etmez. Bir görünümün kısıtlama kümesinin belirsiz olmaması için dört şeye ihtiyacı vardır: herhangi bir durum için bir x konumu, bir y konumu, bir genişlik ve bir yükseklik.

Şu anda yukarıdaki kodda, yalnızca iki tane var (süpervizöre göre yükseklik, denetime göre ve y konumu). Buna ek olarak, görünümün denetleme kısıtlamalarının nasıl ayarlandığına bağlı olarak çakışabilecek iki gerekli kısıtlamaya sahipsiniz. Eğer Superview belirtir 's yükseklik 748 den bazı değer daha az olması gerekli bir kısıtlamasını olması idi, bir "edilemezdir kısıtlamalar" istisna alacak.

Kısıtlamalar belirlemeden önce görünümün genişliğini ayarlamış olmanız hiçbir şey ifade etmez. Hatta eski çerçeveyi hesaba katmayacak ve bu görünümler için belirlediği tüm kısıtlamalara dayalı olarak yeni bir çerçeve hesaplayacaktır. Kodda otomatik düzen ile uğraşırken, genellikle kullanarak initWithFrame:CGRectZeroveya basitçe kullanarak yeni bir görünüm oluştururum init.

Sorunuzda sözlü olarak tanımladığınız düzen için gerekli olan kısıtlama kümesini oluşturmak için, tam olarak belirlenmiş bir düzen vermek üzere genişliği ve x konumunu sınırlandırmak için bazı yatay sınırlamalar eklemeniz gerekir:

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:[myView(==200)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

Bu düzeni sözlü olarak açıklamak, dikey kısıtlamadan başlayarak aşağıdaki gibidir:

myView, süpervizörün yüksekliğini standart alana eşit bir üst ve alt dolgu ile doldurur. myView'ın süpervizör görüntülemesinin minimum yüksekliği 748 puntodur. myView'ın genişliği 200 puntodur ve denetime göre standart alana eşit bir sağ dolgusu vardır.

Sadece görünümün, süpervizörün yüksekliğini sınırlamadan tüm süpervizyon yüksekliğini doldurmasını istiyorsanız, o zaman sadece (>=748)görsel format metnindeki parametreyi çıkarırsınız . (>=748)Parametrenin ona bir yükseklik vermek için gerekli olduğunu düşünüyorsanız - bu durumda yapmazsınız: görünümü |, boşluk ( |-, -|) sözdizimi içeren çubuğu ( ) veya çubuğu kullanarak süpervizörün kenarlarına sabitlemek, görünümünüze bir y vermiş olursunuz. -konum (görünümü tek kenara sabitleme) ve yüksekliği olan bir y-konumu (görünümü her iki kenara sabitleme), böylece görünüm için kısıtlama kümenizi karşılar.

İkinci sorunuzla ilgili olarak:

Kullanarak NSDictionaryOfVariableBindings(self.myView)(myView için bir özellik kurulumunuz varsa) ve bunu self.myViewVFL metninizde kullanmak üzere VFL'nize besleyin, otomatik düzen VFL metninizi ayrıştırmaya çalıştığında muhtemelen bir istisna alırsınız. Bunun sözlük tuşlarındaki nokta notasyonu ve kullanmaya çalıştığı sistemle ilgisi vardır valueForKeyPath:. Benzer bir soru ve cevap için buraya bakın .


UILabel gibi bazı nesnelerin kendine özgü bir boyuta sahip olduğunu ve bu nesnenin genişliğini veya yüksekliğini ayarlamanıza gerek olmadığını, sadece konumunu unutmayın. Bununla birlikte, yüksekliği veya genişliği ayarlarsanız, her ikisini de kaldıracağına inanıyorum ve sonra ikisini de sağlamanız gerekir.
Nick Turner

Bu cevap sorumu cevaplamasa da bir şeyi fark etmeme yardımcı oldu. Olduğunuz için teşekkürler! :)
Matej

1
Şimdiye kadar internetteki tek kısa ve okunabilir otomatik düzen tanıtımı.
Joey Carson

plz bana yardım et sorum şu ... programlı olarak kısıtlamaları nasıl kullanacağımı bilmiyorum stackoverflow.com/questions/36326288/…

61

Merhaba Bu sayfayı kısıtlamalar ve "nasıl yapılır" için çok kullanıyorum. İhtiyaç duyduğumu fark etme noktasına gelmem sonsuza kadar sürdü:

myView.translatesAutoresizingMaskIntoConstraints = NO;

bu örneğin işe yaraması için. Teşekkürler Userxxx, Rob M. ve özellikle buradaki açıklama ve kod için larsacus, paha biçilmezdi.

Çalıştırmak için yukarıdaki örnekleri almak için kodun tamamı:

UIView *myView = [[UIView alloc] init];
myView.backgroundColor = [UIColor redColor];
myView.translatesAutoresizingMaskIntoConstraints = NO;  //This part hung me up 
[self.view addSubview:myView];
//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:[myView(==200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

11

Swift versiyonu

Swift 3 için güncellendi

Bu örnek, Arayüz Oluşturucu'da yaptığınız gibi aşağıdaki kısıtlamaları programlı olarak eklemek için iki yöntem gösterecektir:

Genişlik ve yükseklik

görüntü açıklamasını buraya girin

Konteynerde Merkez

görüntü açıklamasını buraya girin

Genelge kodu

override func viewDidLoad() {
    super.viewDidLoad()

    // set up the view
    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add constraints code here (choose one of the methods below)
    // ...
}

Yöntem 1: Çapa Stili

// width and height
myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

// center in container
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Yöntem 2: NSLayoutConstraint Stili

// width and height
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true

// center in container
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true

Notlar

  • Bağlantı stili, NSLayoutConstraintStil yerine tercih edilen yöntemdir , ancak yalnızca iOS 9'dan kullanılabilir, bu nedenle iOS 8'i destekliyorsanız, yine de NSLayoutConstraintStil'i kullanmalısınız .
  • Ayrıca Programlı Olarak Kısıtlama Oluşturma belgelerine bakın.
  • Bir sabitleme kısıtlaması eklemenin benzer bir örneği için bu yanıta bakın .

5

Özellikler hakkındaki ikinci sorunuzla ilgili olarak, self.myViewyalnızca bunu sınıfta bir özellik olarak bildirdiyseniz kullanabilirsiniz . Yana myViewyerel bir değişkendir, bunu böyle kullanamaz. Bu konuda daha fazla ayrıntı için, ben elma belgelerine geçmesi tavsiye ederim Beyan Özellikleri ,


5

self.myViewmyView gibi yerel bir değişken yerine neden bir özellik kullanamıyorum?

kullanmayı deneyin:

NSDictionaryOfVariableBindings(_view)

onun yerine self.view


Bu, uygulamamın çökmesine neden oldu, şu mesajı veriyor: 'Kısıtlama formatı ayrıştırılamıyor: polylineImageView, görünümler sözlüğünde bir anahtar değil.'
Tai Le

4

Ayrıca, iOS9'dan yeni yardımcı sınıf NSLayoutAnchor alt sınıflarını kullanarak kısıtlamaları programlı olarak "daha kısa ve okunması daha kolay" tanımlayabileceğimizi lütfen unutmayın .

Dokümandan bir örnek:

[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.