Wie verschiebe ich mit dem automatischen Layout andere Ansichten, wenn eine Ansicht ausgeblendet ist?

332

Ich habe meine benutzerdefinierte Zelle in IB entworfen, sie in Unterklassen unterteilt und meine Steckdosen mit meiner benutzerdefinierten Klasse verbunden. Ich habe drei Unteransichten im Zelleninhalt: UIView (cdView) und zwei Labels (titleLabel und emailLabel). Abhängig von den für jede Zeile verfügbaren Daten möchte ich manchmal, dass UIView und zwei Beschriftungen in meiner Zelle angezeigt werden und manchmal nur zwei Beschriftungen. Ich versuche, Einschränkungen auf diese Weise festzulegen, wenn ich die UIView-Eigenschaft auf versteckt setze oder sie aus der Übersicht entferne. Die beiden Beschriftungen werden nach links verschoben. Ich habe versucht, die führende UIView-Einschränkung für 10 Pixel auf Superview (Zelleninhalt) und für 10 Pixel auf UILabels führende Einschränkung für die nächste Ansicht (UIView) zu setzen. Später in meinem Code

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];

if ([record.imageURL is equalToString:@""]) {
     cell.cdView.hidden = YES;
}

Ich verstecke meine cell.cdView und möchte, dass die Beschriftungen nach links verschoben werden, jedoch in Cell an derselben Position bleiben. Ich habe versucht, cell.cdView aus der Übersicht zu entfernen, aber es hat auch nicht funktioniert. Ich habe ein Bild angehängt, um zu verdeutlichen, worum es mir geht.

Zelle

Ich weiß, wie man das programmgesteuert macht, und ich suche nicht nach dieser Lösung. Ich möchte Einschränkungen in IB festlegen und erwarte, dass sich meine Unteransichten dynamisch verschieben, wenn andere Ansichten entfernt oder ausgeblendet werden. Ist dies in IB mit Auto-Layout möglich?

.....
Guferos
quelle
Ändern Sie Einschränkungen Wert Laufzeit - überprüfen Sie diese Antwort
Kampai
Für diesen speziellen Fall können Sie auch eine UIStackView verwenden. Wenn Sie die CD verstecken, nehmen die Etiketten ihren Platz ein
Marco Pappalardo

Antworten:

373

Es ist möglich, aber Sie müssen ein wenig zusätzliche Arbeit leisten. Es gibt ein paar konzeptionelle Dinge, die zuerst aus dem Weg geräumt werden müssen:

  • Versteckte Ansichten, auch wenn sie nicht zeichnen, nehmen dennoch am automatischen Layout teil und behalten normalerweise ihre Rahmen bei , sodass andere verwandte Ansichten an ihren Plätzen verbleiben.
  • Wenn Sie eine Ansicht aus ihrer Übersicht entfernen, werden auch alle zugehörigen Einschränkungen aus dieser Ansichtshierarchie entfernt.

In Ihrem Fall bedeutet dies wahrscheinlich:

  • Wenn Sie festlegen, dass Ihre linke Ansicht ausgeblendet ist, bleiben die Beschriftungen erhalten, da diese linke Ansicht immer noch Platz beansprucht (auch wenn sie nicht sichtbar ist).
  • Wenn Sie Ihre linke Ansicht entfernen, werden Ihre Beschriftungen wahrscheinlich mehrdeutig eingeschränkt, da Sie keine Einschränkungen mehr für die linken Ränder Ihrer Beschriftungen haben.

Was Sie tun müssen, ist , Ihre Etiketten mit Bedacht zu stark einzuschränken. Lassen Sie Ihre vorhandenen Einschränkungen (10 Punkte Platz in der anderen Ansicht) in Ruhe, fügen Sie jedoch eine weitere Einschränkung hinzu: Stellen Sie die linken Ränder Ihrer Beschriftungen mit einer nicht erforderlichen Priorität 10 Punkte vom linken Rand ihrer Übersicht entfernt ein (die standardmäßig hohe Priorität funktioniert wahrscheinlich gut).

Wenn Sie möchten, dass sie sich nach links bewegen, entfernen Sie die linke Ansicht vollständig. Die obligatorische 10-Punkte-Einschränkung für die linke Ansicht verschwindet zusammen mit der Ansicht, auf die sie sich bezieht, und es bleibt nur eine Einschränkung mit hoher Priorität, dass die Beschriftungen 10 Punkte von ihrer Übersicht entfernt sind. Beim nächsten Layoutdurchlauf sollte dies dazu führen, dass sie nach links erweitert werden, bis sie die Breite der Übersicht ausfüllen, jedoch mit Ihrem Abstand um die Kanten.

Eine wichtige Einschränkung: Wenn Sie Ihre linke Ansicht jemals wieder im Bild haben möchten, müssen Sie sie nicht nur wieder in die Ansichtshierarchie einfügen, sondern gleichzeitig alle Einschränkungen wiederherstellen . Dies bedeutet, dass Sie eine Möglichkeit benötigen, Ihre 10pt-Abstandsbeschränkung zwischen der Ansicht und ihren Beschriftungen wiederherzustellen, wenn diese Ansicht erneut angezeigt wird.

Tim
quelle
8
Obwohl diese Antwort sicherlich funktionieren wird, scheint IMO eine übermäßige Einschränkung für die Behandlung verschiedener Anwendungsfälle ein Codegeruch zu sein - insbesondere, da Sie alle Einschränkungen für alle entfernten Ansichten wiederherstellen müssten, die Sie erneut anzeigen möchten.
Memmons
Meiner Meinung nach ist dies nicht der richtige Weg. Sie sollten stattdessen eine Breiten- / Höhenbeschränkung für die Ansicht verwenden, die Sie ausblenden möchten.
ullstrm
26
Ich bin respektvoll anderer Meinung. Wenn Sie (zum Beispiel) die Breite der Ansicht auf 0 setzen, treten zwei Probleme auf. Erstens haben Sie jetzt einen doppelten Abstand zwischen der Übersicht und der sichtbaren Ansicht: |-(space)-[hidden(0)]-(space)-[visible]ist effektiv |-(2*space)-[visible]. Zweitens kann diese Ansicht abhängig von ihrem eigenen Ansichtsunterbaum und den Einschränkungen Einschränkungen auslösen. Sie können nicht garantieren, dass Sie eine Ansicht mit einer Breite von 0 willkürlich einschränken und weiterarbeiten können.
Tim
1
Wenn Sie eine Ansicht mit einer intrinsischen Inhaltsgröße verwenden, scheint Tims Antwort der einzigartige Weg zu sein.
Balkoth
Danke Tim. Ich habe eine Einschränkung von 0 mit einer höheren Priorität festgelegt, um Inkompatibilitäten mit Einschränkungen zu vermeiden, aber jetzt ist mir klar, dass das Problem mit dem doppelten Abstand besteht. Ich hatte dieses Problem nicht, weil ich die beiden Ansichten nie zusammen gezeigt habe (mein Fall |-[otherViews]-[eitherThis][orThis]-|:), aber ich würde irgendwann auf dieses Problem stoßen.
Ferran Maylinch
207

Das Hinzufügen oder Entfernen von Einschränkungen zur Laufzeit ist eine schwere Operation, die die Leistung beeinträchtigen kann. Es gibt jedoch eine einfachere Alternative.

Richten Sie für die Ansicht, die Sie ausblenden möchten, eine Breitenbeschränkung ein. Beschränken Sie die anderen Ansichten mit einer führenden horizontalen Lücke zu dieser Ansicht.

Aktualisieren Sie .constantzum Ausblenden die Breitenbeschränkung auf 0.f. Die anderen Ansichten bewegen sich automatisch nach links, um die Position einzunehmen.

Siehe meine andere Antwort hier für weitere Details:

Wie ändere ich Beschriftungsbeschränkungen zur Laufzeit?

Max MacLeod
quelle
29
Das einzige Problem bei dieser Lösung ist, dass der Rand links das Doppelte dessen ist, was Sie wahrscheinlich wollen. Daher würde ich auch eine dieser Einschränkungen aktualisieren, aber selbst dann denke ich, dass dies weniger Arbeit ist als das Entfernen der Unteransicht.
José Manuel Sánchez
2
@ skinsfan00atg Wenn Sie eine Ansicht mit einer intrinsischen Inhaltsgröße verwenden, können Sie diese Lösung nicht verwenden.
Balkoth
2
@MaxMacLeod Wenn Sie die Priorität für das Umarmen von Inhalten verringern, verwenden Sie nicht die intrinsische Inhaltsgröße, sondern die durch die Einschränkung angegebene Größe.
Balkoth
2
@ MaxMacLeod Ok, ich habe verstanden, was du meinst. Sie müssen die Komprimierungswiderstandspriorität im Code auf 0 setzen (nicht auf den Inhalt), wenn Sie die Ansicht ausblenden und diesen Wert erneut anzeigen möchten. Abgesehen davon müssen Sie im Interface Builder eine Einschränkung hinzufügen, um die Größe der Ansicht auf 0 zu setzen. Diese Einschränkung muss im Code nicht berührt werden.
Balkoth
1
Das funktioniert tatsächlich für mich, vielen Dank
FritzB
87

Für diejenigen, die nur iOS 8+ unterstützen , ist eine neue boolesche Eigenschaft aktiv . Es wird helfen, nur die erforderlichen Einschränkungen dynamisch zu aktivieren

PS Constraint-Steckdose muss stark und nicht schwach sein.

Beispiel:

@IBOutlet weak var optionalView: UIView!
@IBOutlet var viewIsVisibleConstraint: NSLayoutConstraint!
@IBOutlet var viewIsHiddenConstraint: NSLayoutConstraint!

func showView() {
    optionalView.isHidden = false
    viewIsVisibleConstraint.isActive = true
    viewIsHiddenConstraint.isActive = false
}

func hideView() {
    optionalView.isHidden = true
    viewIsVisibleConstraint.isActive = false
    viewIsHiddenConstraint.isActive = true
}

Um einen Fehler im Storyboard zu beheben, müssen Sie das InstalledKontrollkästchen für eine dieser Einschränkungen deaktivieren .

UIStackView (iOS 9+)
Eine weitere Option besteht darin, Ihre Ansichten einzuschließenUIStackView . Sobald die Ansicht ausgeblendet ist, UIStackViewwird das Layout automatisch aktualisiert

Silmaril
quelle
aktiv funktioniert teilweise. Aber wenn ich es in einer wiederverwendbaren Zelle verwende, funktioniert es von Aktivieren bis Deaktivieren, aber nicht, wenn Deaktivieren aktiviert wird. Irgendwelche Ideen? Oder könnten Sie vielleicht ein Beispiel geben?
Aoke Li
10
Dies liegt daran, dass die deaktivierte Einschränkung nicht geladen oder freigegeben wird. Ihr Constraint Outlet sollte stark und nicht schwach sein
Silmaril
Wo finden wir diese "aktive" Eigenschaft?
Lakshmi Reddy
Es scheint, dass Überbeschränkung + Einschränkungsaktivität die vernünftigste Antwort sein kann.
Ting Yi Shih
68

UIStackViewpositioniert seine Ansichten automatisch neu, wenn die hiddenEigenschaft in einer ihrer Unteransichten geändert wird (iOS 9+).

UIView.animateWithDuration(1.0) { () -> Void in
   self.mySubview.hidden = !self.mySubview.hidden
}

Wechseln Sie in diesem WWDC-Video zu 11:48, um eine Demo zu erhalten:

Geheimnisse des automatischen Layouts, Teil 1

5bars
quelle
Ich habe eine verschachtelte Stapelansicht versteckt und die gesamte Stapelansicht ist verschwunden.
Ian Warburton
5
Dies sollte die akzeptierte Antwort sein. Befolgen Sie die Apple-Empfehlungen von wwdc 2015 zum Design des Interface Builder.
Thibaut Noah
@thibautnoah Und was ist dann mit iOS 8-Unterstützung?
Gepäck
5
@bagage Wenn Sie nicht Facebook oder Google sind, können Sie es löschen. Mit der Abdeckung über iOS 9 hinaus unterstützen Sie mehr als 90% der Geräte, mehr als genug. Die Unterstützung unten wird Ihren Entwicklungsprozess lähmen und Sie daran hindern, die neuesten Funktionen imo
thibaut noah
16

Mein Projekt verwendet eine benutzerdefinierte @IBDesignableUnterklasse von UILabel(um Konsistenz in Farbe, Schriftart, Einfügungen usw. sicherzustellen) und ich habe Folgendes implementiert:

override func intrinsicContentSize() -> CGSize {
    if hidden {
        return CGSizeZero
    } else {
        return super.intrinsicContentSize()
    }
}

Dadurch kann die Beschriftungsunterklasse am automatischen Layout teilnehmen, nimmt jedoch keinen Platz ein, wenn sie ausgeblendet ist.

Robert Atkins
quelle
13

Für die Googler: Aufbauend auf Max 'Antwort, um das Polsterungsproblem zu lösen, das viele bemerkt haben, habe ich einfach die Höhe des Etiketts erhöht und diese Höhe als Trennzeichen anstelle der tatsächlichen Polsterung verwendet. Diese Idee kann für jedes Szenario mit Ansichten erweitert werden.

Hier ist ein einfaches Beispiel:

IB Screenshot

In diesem Fall ordne ich die Höhe des Autorenetiketts einem geeigneten zu IBOutlet:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

und wenn ich die Höhe der Einschränkung auf setze, behalten 0.0fwir die "Auffüllung" bei, da die Höhe der Wiedergabetaste dies zulässt.

jterry
quelle
Für diejenigen, die neu in NSLayoutConstraintIch glaube, dass Sie die constantEigenschaft Ihrer aktualisieren möchten authorLabelHeight.
Kyle
8

Verbinden Sie die Einschränkung zwischen uiview und Beschriftungen als IBOutlet und setzen Sie das Prioritätselement auf einen niedrigeren Wert, wenn Sie hidden = YES setzen

n0c
quelle
3
Sie können die Priorität einer NSLayoutConstraint nach ihrer Einrichtung nicht mehr anpassen. Sie müssen eine neue Einschränkung mit einer anderen Priorität entfernen und lesen.
Tim
7
Ich habe diese Methode zum Laufen gebracht. Ich habe einen Fall, der eine Beschriftung und eine Schaltfläche verwendet, in denen ich die Schaltfläche ausblenden und die Beschriftung erweitern muss. Ich habe zwei Einschränkungen, eine anfangs mit der Priorität 751 und die andere mit der Priorität 750. Wenn ich dann die Schaltfläche ausblende, drehe ich die Prioritäten um und die Länge des Etiketts wächst. Es sollte beachtet werden, dass beim Versuch, die höhere Priorität 1000 festzulegen, die Fehlermeldung "Das Mutieren einer Priorität von erforderlich zu nicht für eine installierte Einschränkung (oder umgekehrt) wird nicht unterstützt." Angezeigt wird. Also nicht und es scheint dir gut zu gehen. Xcode 5.1 / viewDidLoad.
John Bushnell
8

Am Ende habe ich 2 xibs erstellt. Eins mit der linken Ansicht und eins ohne. Ich habe beide im Controller registriert und dann entschieden, welche während cellForRowAtIndexPath verwendet werden soll.

Sie verwenden dieselbe UITableViewCell-Klasse. Der Nachteil ist, dass es eine gewisse Verdoppelung des Inhalts zwischen den xibs gibt, aber diese Zellen sind ziemlich einfach. Der Vorteil ist, dass ich nicht viel Code habe, um das Entfernen der Ansicht, das Aktualisieren von Einschränkungen usw. manuell zu verwalten.

Im Allgemeinen ist dies wahrscheinlich eine bessere Lösung, da es sich um technisch unterschiedliche Layouts handelt und daher unterschiedliche xibs haben sollten.

[self.table registerNib:[UINib nibWithNibName:@"TrackCell" bundle:nil] forCellReuseIdentifier:@"TrackCell"];
[self.table registerNib:[UINib nibWithNibName:@"TrackCellNoImage" bundle:nil] forCellReuseIdentifier:@"TrackCellNoImage"];

TrackCell *cell = [tableView dequeueReusableCellWithIdentifier:(appDelegate.showImages ? @"TrackCell" : @"TrackCellNoImage") forIndexPath:indexPath];
Michael Peterson
quelle
7

In diesem Fall ordne ich die Höhe des Autorenetiketts einem geeigneten IBOutlet zu:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

und wenn ich die Höhe der Einschränkung auf 0.0f setze, behalten wir das "Auffüllen" bei, da die Höhe der Wiedergabetaste dies zulässt.

cell.authorLabelHeight.constant = 0;

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Mitul Marsoniya
quelle
6

Verwenden Sie zwei horizontale und vertikale UIStackView-Ansichten. Wenn eine Unteransicht im Stapel ausgeblendet ist, werden andere Stapel-Unteransichten verschoben. Verwenden Sie Verteilung -> Proportional für vertikalen Stapel mit zwei UILabels füllen und müssen Sie für die erste UIView festgelegte Breiten- und Höhenkonstanten festlegenGeben Sie hier die Bildbeschreibung ein

Roman Solodyashkin
quelle
2

Versuchen Sie dies, ich habe unten Code implementiert,

Ich habe eine Ansicht auf ViewController, in der drei weitere Ansichten hinzugefügt wurden. Wenn eine Ansicht ausgeblendet ist, werden zwei weitere Ansichten verschoben. Befolgen Sie die nachstehenden Schritte. ,

1.ViewController.h-Datei

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIView *viewOne;
@property (strong, nonatomic) IBOutlet UIView *viewTwo;
@property (strong, nonatomic) IBOutlet UIView *viewThree;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewOneWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewTwoWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewThreeWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewBottomWidth;
@end

2.ViewController.m

 #import "ViewController.h"
 @interface ViewController ()
{
  CGFloat viewOneWidthConstant;
  CGFloat viewTwoWidthConstant;
  CGFloat viewThreeWidthConstant;
  CGFloat viewBottomWidthConstant;
}
@end

@implementation ViewController
@synthesize viewOne, viewTwo, viewThree;

- (void)viewDidLoad {
  [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a 
  nib.

  /*
   0  0   0
   0  0   1
   0  1   0
   0  1   1
   1  0   0
   1  0   1
   1  1   0
   1  1   1
   */

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:YES];


  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

 //    [viewOne setHidden:YES];
 //    [viewTwo setHidden:YES];
 //    [viewThree setHidden:NO];

//    [viewOne setHidden:YES];
//    [viewTwo setHidden:YES];
//    [viewThree setHidden:YES];

 [self hideShowBottomBar];
  }

- (void)hideShowBottomBar
{
  BOOL isOne = !viewOne.isHidden;
  BOOL isTwo = !viewTwo.isHidden;
  BOOL isThree = !viewThree.isHidden;

  viewOneWidthConstant = _viewOneWidth.constant;
  viewTwoWidthConstant = _viewTwoWidth.constant;
  viewThreeWidthConstant = _viewThreeWidth.constant;
  viewBottomWidthConstant = _viewBottomWidth.constant;

   if (isOne && isTwo && isThree) {
    // 0    0   0
    _viewOneWidth.constant = viewBottomWidthConstant / 3;
    _viewTwoWidth.constant = viewBottomWidthConstant / 3;
    _viewThreeWidth.constant = viewBottomWidthConstant / 3;
    }
    else if (isOne && isTwo && !isThree) {
     // 0    0   1
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = 0;
    }
   else if (isOne && !isTwo && isThree) {
    // 0    1   0
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
    }
    else if (isOne && !isTwo && !isThree) {
    // 0    1   1
    _viewOneWidth.constant = viewBottomWidthConstant;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && isTwo && isThree) {
    // 1    0   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
   }
   else if (!isOne && isTwo && !isThree) {
    // 1    0   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && !isTwo && isThree) {
    // 1    1   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant;
   }
   else if (isOne && isTwo && isThree) {
    // 1    1   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
  }

 - (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
 }
 @end

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Hoffnung Also diese Logik wird jemandem helfen.

Jaywant Khedkar
quelle
1

In meinem Fall setze ich die Konstante der Höhenbeschränkung auf 0.0fund setze auch die hiddenEigenschaft auf YES.

Um die Ansicht (mit den Unteransichten) wieder anzuzeigen, habe ich das Gegenteil getan: Ich habe die Höhenkonstante auf einen Wert ungleich Null gesetzt und die hiddenEigenschaft auf gesetzt NO.

testen
quelle
1

Ich werde horizontale Stapelansicht verwenden. Es kann den Rahmen entfernen, wenn die Unteransicht ausgeblendet ist.

In der Abbildung unten ist die rote Ansicht der eigentliche Container für Ihren Inhalt und verfügt über 10pt nachgestellten Speicherplatz für die orangefarbene Übersicht (ShowHideView). Verbinden Sie dann ShowHideView mit IBOutlet und zeigen / verbergen / entfernen Sie ihn programmgesteuert.

  1. Dies ist, wenn die Ansicht sichtbar / installiert ist.

Ansicht ist sichtbar

  1. In diesem Fall ist die Ansicht ausgeblendet / nicht installiert.

Ansicht wird ausgeblendet / entfernt

Mnemonik23
quelle
1

Dies ist meine andere Lösung mit Prioritätsbeschränkung. Die Idee ist, die Breite auf 0 zu setzen.

  1. Erstellen Sie eine Containeransicht (orange) und legen Sie die Breite fest. Geben Sie hier die Bildbeschreibung ein

  2. Erstellen Sie eine Inhaltsansicht (rot) und setzen Sie den nachfolgenden Bereich 10pt auf Übersicht (orange). Beachten Sie die Einschränkungen für den nachgestellten Speicherplatz. Es gibt zwei nachfolgende Einschränkungen mit unterschiedlicher Priorität. Niedrig (= 10) und Hoch (<= 10). Dies ist wichtig, um Mehrdeutigkeiten zu vermeiden. Geben Sie hier die Bildbeschreibung ein

  3. Setzen Sie die Breite der orangefarbenen Ansicht auf 0, um die Ansicht auszublenden. Geben Sie hier die Bildbeschreibung ein

Mnemonik23
quelle
0

Wie von no_scene vorgeschlagen, können Sie dies definitiv tun, indem Sie die Priorität der Einschränkung zur Laufzeit ändern. Dies war für mich viel einfacher, da ich mehr als eine blockierende Ansicht hatte, die entfernt werden musste.

Hier ist ein Ausschnitt mit ReactiveCocoa:

RACSignal* isViewOneHiddenSignal = RACObserve(self.viewModel, isViewOneHidden);
RACSignal* isViewTwoHiddenSignal = RACObserve(self.viewModel, isViewTwoHidden);
RACSignal* isViewThreeHiddenSignal = RACObserve(self.viewModel, isViewThreeHidden);
RAC(self.viewOne, hidden) = isViewOneHiddenSignal;
RAC(self.viewTwo, hidden) = isViewTwoHiddenSignal;
RAC(self.viewThree, hidden) = isViewThreeHiddenSignal;

RAC(self.viewFourBottomConstraint, priority) = [[[[RACSignal
    combineLatest:@[isViewOneHiddenSignal,
                    isViewTwoHiddenSignal,
                    isViewThreeHiddenSignal]]
    and]
    distinctUntilChanged]
    map:^id(NSNumber* allAreHidden) {
        return [allAreHidden boolValue] ? @(780) : @(UILayoutPriorityDefaultHigh);
    }];

RACSignal* updateFramesSignal = [RACObserve(self.viewFourBottomConstraint, priority) distinctUntilChanged];
[updateFramesSignal
    subscribeNext:^(id x) {
        @strongify(self);
        [self.view setNeedsUpdateConstraints];
        [UIView animateWithDuration:0.3 animations:^{
            [self.view layoutIfNeeded];
        }];
    }];
Skensell
quelle
0

Für den Fall, dass dies jemandem hilft, habe ich eine Hilfsklasse für die Verwendung visueller Formatbeschränkungen erstellt . Ich benutze es in meiner aktuellen App.

AutolayoutHelper

Es ist vielleicht ein bisschen auf meine Bedürfnisse zugeschnitten, aber Sie finden es vielleicht nützlich oder möchten es ändern und Ihren eigenen Helfer erstellen.

Ich muss Tim für seine Antwort oben , diese Antwort über UIScrollView und auch dieses Tutorial danken .

Ferran Maylinch
quelle
0

So würde ich meine Ansichten neu ausrichten, um Ihre Lösung zu erhalten:

  1. Ziehen Sie eine UIImageView per Drag & Drop und platzieren Sie sie links.
  2. Ziehen Sie eine UIView per Drag & Drop und platzieren Sie sie rechts von UIImageView.
  3. Ziehen Sie zwei UILabels in diese UIView, deren führende und nachfolgende Einschränkungen Null sind.
  4. Setzen Sie die führende Einschränkung von UIView mit 2 Beschriftungen auf Superview anstelle von UIImagView.
  5. Wenn UIImageView ausgeblendet ist, setzen Sie die führende Einschränkungskonstante für die Übersicht auf 10 px. Andernfalls setzen Sie die führende Einschränkungskonstante auf 10 px + UIImageView.width + 10 px.

Ich habe eine eigene Daumenregel erstellt. Wenn Sie eine uiview ausblenden / anzeigen müssen, deren Einschränkungen möglicherweise betroffen sind, fügen Sie alle betroffenen / abhängigen Unteransichten in einer uiview hinzu und aktualisieren Sie die führende / nachfolgende / top / bottom-Einschränkungskonstante programmgesteuert.

Deepak Thakur
quelle
0

Dies ist eine alte Frage, aber ich hoffe trotzdem, dass es helfen wird. Wenn Sie von Android kommen, haben Sie auf dieser Plattform eine praktische Methode isVisible, um es aus der Ansicht auszublenden, aber auch den Rahmen nicht zu berücksichtigen, wenn das Autolayout die Ansicht zeichnet.

Mit der Erweiterung und der Erweiterung "uiview" können Sie eine ähnliche Funktion in ios ausführen (nicht sicher, warum sie nicht bereits in UIKit enthalten ist). Hier eine Implementierung in Swift 3:

    func isVisible(_ isVisible: Bool) {
        self.isHidden = !isVisible
        self.translatesAutoresizingMaskIntoConstraints = isVisible
        if isVisible { //if visible we remove the hight constraint 
            if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first){
                self.removeConstraint(constraint)
            }
        } else { //if not visible we add a constraint to force the view to have a hight set to 0
            let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal , toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 0)
            self.addConstraint(height)
        }
        self.layoutIfNeeded()
    }
Vincent Choubard
quelle
0

Der richtige Weg, dies zu tun, besteht darin, Einschränkungen mit isActive = false zu deaktivieren. Beachten Sie jedoch, dass durch Deaktivieren einer Einschränkung diese entfernt und freigegeben wird, sodass Sie starke Steckdosen für sie haben müssen.

Hogdotmac
quelle
0

Die einfachste Lösung ist die Verwendung von UIStackView (horizontal). Zur Stapelansicht hinzufügen: erste Ansicht und zweite Ansicht mit Beschriftungen. Setzen Sie dann die isHidden-Eigenschaft der ersten Ansicht auf false. Alle Einschränkungen werden berechnet und automatisch aktualisiert.

Oleh Kudinov
quelle
0

Ich denke, das ist die einfachste Antwort. Bitte überprüfen Sie, ob es funktioniert:

        StackFullView.layer.isHidden = true
        Task_TopSpaceSections.constant = 0.   //your constraint of top view

Überprüfen Sie hier https://www.youtube.com/watch?v=EBulMWMoFuw

Gowthaman M.
quelle