OS X Kakao Otomatik Düzen gizli öğeler

Yeni Otomatik Düzenlemeyi in Aslan çünkü oldukça güzel görünüyor. Ancak, nasıl yapılacağı hakkında iyi bir bilgi bulamıyorum. Örneğin:

İki etiketim var:

+----------------+
| +------------+ |
| + label 1    | |
| +------------+ |
|                |
| +------------+ |
| | label 2    | |
| +------------+ |
+----------------+

Ancak ilk etiket her zaman içerikle doldurulmuyor, bazen de bunun için hiçbir içerik yok. Yapmak istediğim, etiketin (1) içerik olduğunda, etiketin (1) otomatik olarak gösterilmesidir.

+----------------+
| +------------+ |
| + label 2    | |
| +------------+ |
|                |
|                |
|                |
|                |
+----------------+

Hangi kısıtlamaları eklemem gerekiyor ki otomatik olarak otomatik olarak çalışır? Sadece her şeyi kodlayabildiğimi anlıyorum, ama 30 kadar etiket ve resim ve düğmelerin hepsi isteğe bağlı olan farklı stiller ve şekiller var. Ayrıca otomatik olarak çok güzel çalışabiliyorken kod satırlarının hundretslerini eklemek istemiyorum. .

Eğer işe yaramazsa, sadece bir WebView kullanacağım ve bunu HTML ve CSS ile yapacağım.

29
Bir tablo sadece yukarıdan aşağıya doğru olsaydı yardımcı olurdu, ancak bazı şeyler soldan sağa çok doğru ve başkalarının ve eşyaların yerini almalı. Ama fikir kötü değil itiraf ediyorum.
katma yazar Jeena, kaynak
Otomatik düzende bunun mümkün olup olmadığından emin değilim, ancak gerçekten istediğiniz şey tablo gibi görünüyor.
katma yazar user557219, kaynak

8 cevap

Bu otomatik düzende mümkündür, ancak tam olarak ölçeklendirilmez.

Örnek vermek gerekirse, A etiketini ve B etiketini (veya düğmeyi veya başka bir şeyi gerçekten) varsayalım. İlk önce A için süper görüntüye bir üst sınırlama ekleyerek başlayın. Sonra A ve B arasındaki dikey boşluk kısıtlaması. Bu, şu ana kadar normaldir. Bu noktada A'yı çıkarırsanız, B belirsiz bir yerleşime sahip olur. Eğer onu saklayacak olsaydın, yine de etiketler arasındaki boşluk da dahil olmak üzere alanı kaplardı.

Ardından, B'den başka bir kısıtlama eklemeniz gerekir. Bu önceliği diğerlerinden daha düşük olarak değiştirin (900 deyin) ve daha sonra standart (veya başka bir küçük değer) olarak sabit olmasını ayarlayın. Artık A, süper görüntüden kaldırıldığında, düşük öncelikli kısıtlama B'ye girecek ve en üste doğru çekecektir. Kısıtlamalar böyle bir şeye benziyor:

Interface Builder screenshot

Sorun, uzun bir etiket listesiyle yapmaya çalıştığınızda ortaya çıkıyor.

24
katma
Bu, sunulan dava için temiz bir çözümdür. Daha fazla etiket olması durumunda, muhtemelen bu kodu kopyalamak en kolay olurdu. IB, "En yakın komşuya" atıfta bulunulduğunda açılan "Yeni kısıtlama ekle" editöründe bir çözüm önermektedir. Aslında bunu yapsaydı, kutudan çalışırdı. Problemin onların çok erken bağlandıkları ("neigbhor") ve bunu storyboard dosya formatında görebilmeleri olduğunu düşünüyorum.
katma yazar Chris Conover, kaynak
Bu çalışmanın ikinci kısmı nasıl? B'den süper ekrana başka bir kısıtlama eklerseniz, öncelikten bağımsız olarak her zaman tetiklenmez mi?
katma yazar kevinl, kaynak
Nevermind, bu özel mantığı benim çalışmamın sonundaki senaryoda kullanmaya çalışıyorum: Düğme A, B, C var. B'yi kaldıracağım ve C'nin B'nin yerini almasını istiyorum.
katma yazar kevinl, kaynak

UILabel alt sınıfı daraltılıyor

Basit bir çözüm, UILabel'ın alt sınıfını oluşturmak ve içsel içerik boyutunu değiştirmek.

@implementation WBSCollapsingLabel

- (CGSize)intrinsicContentSize
{
    if (self.isHidden) {
        return CGSizeMake(UIViewNoIntrinsicMetric, 0.0f);
    } else {
        return [super intrinsicContentSize];
    }
}

- (void)setHidden:(BOOL)hidden
{
    [super setHidden:hidden];

    [self updateConstraintsIfNeeded];
    [self layoutIfNeeded];
}

@end
10
katma
Şey ... harika soru. Genelde otomatik düzen konuları SO'da iyi bir şekilde ele alınmamıştır. Ayrıca birçok insanın kısıtlamalara bir çıkış bağladığını ve yüksekliği vurduğunu düşünüyorum. Alt sınıflandırma da biraz can sıkıcıdır.
katma yazar Cameron Lowell Palmer, kaynak
Kenar boşlukları H: | - (8) - [view1] - (12) - [hidden1] - (8) - |? Evet ... Haklısın, ama karelerin olduğu zaman da aynı sorun bu. Görünüm arasındaki boşlukların ele alındığından emin olmanız gerekir, ancak bu ayrı bir soru!
katma yazar Cameron Lowell Palmer, kaynak
Bu yaklaşımdaki sorun, genellikle sizin görüşünüzün etrafındaki boşlukları dikkate almamasıdır.
katma yazar tcurdt, kaynak
Bu, Kakao'da da işe yarayacak kadar basit bir çözümdür. UHUNYUMUŞTIRMAYINIZI anahtarını NSViewNoInstrinsicMetric , updateConstraintsIfNeeded olarak updateConstraintsForSubtreeIfNeeded olarak değiştirin. ve layoutSubtreeIfNeeded için layoutIfNeeded ve çekicilik gibi çalışır. Teşekkür ederim!
katma yazar bithavoc, kaynak
Bu gitmek için gerçekten basit ve zarif bir yol gibi görünüyor. Gerçekten işe yaramazsa neden daha yüksek oy verilmediğini merak ediyorum.
katma yazar software evolved, kaynak

Bu kategori, Otomatik Düzenleme kısıtlı görünümlerini daraltmayı gerçekten basit hale getirir:

https://github.com/depth42/OutolayoutExtensions

Sadece bir projeye ekledim ve harika çalışıyor.

4
katma
Bunu projemde kullanmaya çalışıyorum, ancak projemdeki görünümler için Xcode'ta yeni PWHidingMasterView public çıkışı bulunmuyor. Örnek projeyi açtığımda çıkış var. Projemden ve örneklemden farklı olanı anlayamıyorum. Herhangi bir ipucu?
katma yazar Ricardo Sanchez-Saez, kaynak

Bunu böyle yapabileceğini sanmıyorum. Etiket 2 için mizanpajı yaparsanız, etiket 1'den bir uzaklık kısıtlamasına dayanırsınız, etiket 1'in otomatik olarak çökmesini, içerik içermediğinde sıfır yüksekliğine getirmiş olsanız bile, etiket 2 hala bu mesafe kadar olacak, yani:

+----------------+
| +------------+ |
| + label 1    | |
| +------------+ |
|        ^       |
|        ^       !
| +------------+ |
| | label 2    | |
| +------------+ |
+----------------+

^ Autolayout mesafe kısıtlaması olduğunda - Label 1 dize boş olduğunda sıfıra nasıl dönüleceğini bilirse, yine de elde edersiniz:

+----------------+
| +------------+ |
|        ^       |
|        ^       !
| +------------+ |
| | label 2    | |
| +------------+ |
+----------------+

Maybe it is possible by creating your NSLayoutConstraint manually. You could make the second attribute be the height of label 1, make the constant zero, and then carefully work out what the multiplier would be to make the distance be what you want based on a multiple of the non-zero label height.

Ancak tüm bunları yaptıktan sonra, otomatik boyutlara sahip bir NSLabel alt sınıfını kodladınız, görsel bir dil yerine el ile bir kısıtlama nesnesi oluşturdunuz ve NSLayoutConstraint'ı kendi isteğinin ötesinde büktün.

Etiket 1'in dizgisi boşsa, etiket 2'nin çerçevesini değiştirmekten daha iyi olursun!

2
katma
0 sabitini ayarlamadan, arayüz oluşturucuda herhangi bir doğrudan seçenek mevcut mu?
katma yazar user2223516, kaynak

Burada, Interface Builder'ı kullanmak yerine programlı olarak nasıl ele aldığımı gösteren bir örnek var. Özetle; Yalnızca etkinleştirilmişse görünümü eklerim ve ardından alt görünümler üzerinde yinelemeye devam ediyorum, gittiğimde dikey kısıtlamalar ekliyorum.

Söz konusu görünümlerin bundan önce başlatıldığını unutmayın.

/*
  Begin Auto Layout
*/
NSMutableArray *constraints = [NSMutableArray array];
NSMutableDictionary *views = [[NSMutableDictionary alloc] init];


/*
  Label One
*/
if (enableLabelOne) {
    [contentView addSubview:self.labelOne];

    self.labelOne.translatesAutoresizingMaskIntoConstraints = NO;

    [views setObject:self.labelOne
              forKey:@"_labelOne"];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelOne(44)]"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelOne]-|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];
}

/*
    Label Two
*/
if (enableLabelTwo) {
    [contentView addSubview:self.labelTwo];

    self.labelTwo.translatesAutoresizingMaskIntoConstraints = NO;

    [views setObject:self.labelTwo
              forKey:@"_labelTwo"];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelTwo(44)]"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];
}

[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelTwo]-|"
                                                                         options:0
                                                                         metrics:nil
                                                                           views:views]];

/*
  Dynamically add vertical spacing constraints to subviews
*/
NSArray *subviews = [contentView subviews];

if ([subviews count] > 0) {
    UIView *firstView = [subviews objectAtIndex:0];
    UIView *secondView = nil;
    UIView *lastView = [subviews lastObject];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[firstView]"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:NSDictionaryOfVariableBindings(firstView)]];

    for (int i = 1; i < [subviews count]; i++) {
        secondView = [subviews objectAtIndex:i];
        [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[firstView]-10-[secondView]"
                                                                                 options:0
                                                                                 metrics:nil
                                                                                   views:NSDictionaryOfVariableBindings(firstView, secondView)]];
        firstView = secondView;
    }

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[lastView]-|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:NSDictionaryOfVariableBindings(lastView)]];
}


[self addConstraints:constraints];

Sadece lastView sınırını ayarlıyorum çünkü bu kod UIScrollView içindeki bir şeyden uyarlandı.

Bunu orijinal olarak Bu Yığın Taşımı yanıtına dayanarak uyguladım ve işleri kendi gereksinimlerime göre değiştirdim.

1
katma

Bunu yapmak için göze çarpan iyi bir yol buldum. David'in 'i ile benzerdir. İşte kodda nasıl çalışır. Süper görüntüyü ve tüm bu alt görünümleri, her zaman göstermeyenler bile oluşturdum. Süper görüntüye V: | - [_ btn] gibi kısıtlamaların birçoğunu ekledim. Bu kısıtlamaların sonunda gördüğünüz gibi, süper görüntüdeki tabana bağlantı yoktur. Daha sonra iki görüşün her iki durumu için kısıtlamalar dizisi yarattım, çünkü benim için fark bir 'Daha Fazla Seçenek' açıklama üçgeni. Daha sonra, duruma bağlı olarak üçgen tıklandığında, kısıtlamaları ve alt görünümleri buna göre ekleyip kaldırırım. Örneğin eklemek için şunu yapın:

[self.backgroundView removeConstraints:self.lessOptionsConstraints];
[self.backgroundView addSubview:self.nameField];
[self.backgroundView addConstraints:self.moreOptionsConstraints];

Kaldırdığım kısıtlamalar, düğmeyi V: [_ btn] - | gibi süper görüntünün altına bağladı. Eklediğim kısıtlar V: [_ btn] - [_ nameField] - | gibi görünüyor. Bu kısıtlamayı gördüğünüz gibi, yeni görünümü yukarıdaki orijinal görünümle süper görünümün alt kısmı arasındaki yeni görüntüyü yerleştirir. superview'in yüksekliği.

0
katma

Bu sorunu programlı olarak çözdüm. Üst üste birkaç düğmem var ve istediğimi gizlemeye karar verebilirim.

enter image description here

Bunların herhangi birinde gizli her zaman değişiklik yapmak için Haritacılık kullanılır.

let buttons = self.buttons!.filter { button in
    return !button.hidden
}

constrain(buttons, replace: self.constraintGroup) { buttons in
    let superview = buttons.first!.superview!

    buttons.first!.left == superview.left

    for var i = 1; i < buttons.count; i++ {
        buttons[i].left == buttons[i-1].right + 10
    }

    buttons.last!.right == superview.right
}
0
katma

Bunu yapmanın başka bir yolunu buldum. Bu metodoloji her yerde uygulanabilir, ölçekleme problemleri yoktur; ve kenar boşluklarını da işler. Ve bunun için 3. parti şeylere ihtiyacınız yok.

İlk olarak, bu düzeni kullanmayın:

V:|-?-[Label1]-10-[Label2]-10-|
H:|-?-[Label1]-?-|
H:|-20-[Label2]-20-|

Bunları yerine kullanın:

("|" is the real (outer) container)
V:|-?-[Label1]-0-[Label2HideableMarginContainer]-0-|
H:|-?-[Label1]-?-|
H:|-0-[Label2HideableMarginContainer]-0-|

("|" is Label2HideableMarginContainer)
V:|-10-[Label2]-10-|
H:|-20-[Label2]-20-|

Peki şimdi ne yaptık? Label2 düzeni doğrudan kullanılmaz; bir Margin-Container içine yerleştirilir. Bu kapsayıcıda Label2 proxy , 0 marjlı olarak kullanılır. Gerçek marjlar Margin-Container 'ın içine yerleştirilir.

Şimdi Label2 'i şu şekilde gizleyebiliriz:

  • Gizli ayarını YES olarak
  • olarak ayarlayarak

VE

  • Disabling the Top, Bottom, Leading VE Trailing constraints. So seek them out, than set Active to NO on them. This will cause the Margin-Container to have a Frame Size of (0,0); because it does have subview(s); but there aren't any (active) layout constraints which anchors those subviews to it.

Maybe a bit complex, but you only have to develop it once. All the logic can be put into a separate place, VE be reused every time you need to hide smg.

Burada C# Xamarin kodu, alt görünümleri/kodları Margin-Container görünümünün iç kenarlarına sabitleyen bu kısıtlamaları nasıl arayacağınız aşağıda açıklanmıştır:

public List SubConstraints { get; private set; }

private void ReadSubContraints()
{
    var constraints = View.Constraints;//View: the Margin-Container NSView
    if(constraints?.Any() ?? false)
    {
        SubConstraints = constraints.Where((NSLayoutConstraint c) => {
            var predicate = 
                c.FirstAttribute == NSLayoutAttribute.Top ||
                c.FirstAttribute == NSLayoutAttribute.Bottom ||
                c.FirstAttribute == NSLayoutAttribute.Leading ||
                c.FirstAttribute == NSLayoutAttribute.Trailing;
            predicate &= ViewVESubviews.Contains(c.FirstItem);//ViewVESubviews: The View VE View.Subviews
            predicate &= ViewVESubviews.Contains(c.SecondItem);
            return predicate;
        }).ToList();
    }
}
0
katma