Programmgesteuertes Erstellen von Schnittstellenelementen mit PureLayout (Teil 1)

Hallo Habr! Ich präsentiere Ihnen die Übersetzung des Artikels Programmgesteuertes Erstellen von UIViews-Einschränkungen mithilfe von PureLayout von Aly Yaka.

Bild

Heute werde ich Sie durch die Erstellung einer einfachen Benutzeroberfläche für mobile Anwendungen mit Code führen, ohne Storyboards oder NIBs zu verwenden. Ich werde nicht auf Diskussionen darüber eingehen, was besser ist, da alles seine Vor- und Nachteile hat. Ich werde also nur einen Link hinterlassen, der auf diese Angelegenheit eingeht .

Im zweiten Teil dieses Handbuchs werden einige der am häufigsten verwendeten Elemente der Benutzeroberfläche für mobile Anwendungen mit Code erstellt, darunter eine Navigationsleiste, eine Tabellenansicht und Zellen mit dynamischer Größe.

Rückblick


Dieses Tutorial wurde mit Xcode 9 und Swift 4 geschrieben. Ich gehe auch davon aus, dass Sie mit Xcode, Swift und CocoaPods vertraut sind.

Beginnen wir ohne weitere Verzögerung mit der Erstellung unseres Projekts: einer einfachen Kontaktkartenanwendung. In diesem Artikel erfahren Sie, wie Sie die Benutzeroberfläche Ihrer Anwendung in Code erstellen. Daher enthält sie keine Logik bezüglich der Funktionalität der Anwendung, es sei denn, dies ist für die Zwecke dieses Handbuchs erforderlich.

Programmgesteuertes Erstellen von Einschränkungen mit PureLayout


Projekteinrichtung


Starten Sie zunächst Xcode -> "Neues Xcode-Projekt erstellen". Wählen Sie "Single View App" und klicken Sie auf "Weiter".

Bild

Benennen Sie das Projekt so, wie Sie möchten. Ich habe beschlossen, es ContactCard zu nennen. Deaktivieren Sie alle drei Optionen unten und wählen Sie Swift als Programmiersprache aus. Klicken Sie dann auf Weiter.

Bild

Wählen Sie einen Speicherort auf Ihrem Computer aus, um das Projekt zu speichern. Deaktivieren Sie "Git-Repository auf meinem Mac erstellen".

Da wir in diesem Projekt keine Storyboards oder NIBs verwenden, löschen Sie das "Main.storyboard", das sich im Projektnavigator befindet:

Bild

Klicken Sie anschließend im Projektnavigator und auf der Registerkarte „Allgemein“ auf das Projekt, suchen Sie den Abschnitt mit den Bereitstellungsinformationen und löschen Sie alles, was in der „Hauptschnittstelle“ geschrieben ist. Dies teilt Xcode mit, welche Storyboard-Datei beim Starten der Anwendung geladen werden soll. Da wir jedoch gerade "Main.storyboard" gelöscht haben, findet Xcode diese Datei nicht, was zum Absturz der Anwendung führt.

Bild

ViewController erstellen


Wenn Sie die Anwendung jetzt ausführen, wird ein schwarzer Bildschirm angezeigt, da die Anwendung jetzt keine Quelle für die Benutzeroberfläche hat. Im nächsten Teil werden wir sie erstellen. Öffnen Sie "AppDelegate.swift" und fügen Sie in der application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) Dieses Codefragment ein:

 self.window = UIWindow(frame: UIScreen.main.bounds) let viewController = ViewController() self.window?.rootViewController = viewController self.window?.makeKeyAndVisible() 

Dieser Code bietet ein Fenster für die Benutzerinteraktion mit der Anwendung, das normalerweise in "ViewController.swift" zu finden ist. Um schnell zu überprüfen, ob alles funktioniert, gehen Sie zu "ViewController.swift" und viewDidLoad() in der viewDidLoad() -Methode die folgende Zeile ein:

 self.view.backgroundColor = .blue 

Führen Sie nun die Anwendung aus.

Um zwischen Dateien in Xcode zu navigieren, verwenden Sie die Hotkeys „⇧⌘O“ und geben Sie den Dateinamen oder sogar das gesuchte Codefragment ein. Auf dem Bildschirm wird eine Liste der Dateien angezeigt, aus denen Sie auswählen können.

Nach dem Starten der Anwendung sollte dies das Ergebnis auf dem Bildschirm Ihres Simulators sein:

Bild

Natürlich werden wir dieses ekelhafte Blau nicht verwenden, also ändern Sie einfach den Hintergrund in Weiß, indem Sie .blue durch .white in viewDidLoad () .

UI-Entwicklung


Um unsere Benutzeroberfläche zu erstellen, werden wir eine Bibliothek verwenden , die unser Leben viel einfacher macht. Um PureLayout zu installieren, müssen Sie zuerst Ihr Terminal öffnen und cd und dann ein Leerzeichen eingeben, Ihren Projektordner in das Terminal ziehen und die Eingabetaste drücken. Führen Sie nun die folgenden Befehle im Terminal aus:

  • pod init
  • Pod installieren

Dies sollte die Ausgabe Ihres Terminals nach dem zweiten Befehl sein:

Bild

Schließen Sie danach Xcode, öffnen Sie den Ordner im Finder und Sie sollten "<Ihr Projektname> .xcworkspace" finden. Dies wird geöffnet, um auf unsere Anwendung zuzugreifen, falls wir jemals CocoaPods verwenden müssen. Suchen Sie nun die Datei mit dem Namen "PodFile" und schreiben Sie die folgende Zeile unter den Ausdruck "use_frameworks" use_frameworks!

 pod “PureLayout 

Führen Sie die pod install erneut in Ihrem Terminal aus und erstellen Sie dann Ihr Projekt, indem Sie „Befehl + B“ drücken.

Kaffeepause


Nachdem alles eingerichtet ist, beginnen wir mit der eigentlichen Arbeit. Gehen Sie zu "ViewController.swift" und trinken Sie eine Tasse Kaffee, denn so wird das Endergebnis aussehen:

Bild

Erstellen Sie ImageView


Fügen Sie die import PureLayout Zeile unter import UIKit damit Sie die Bibliothek in dieser Datei verwenden können. Anschließend erstellen wir unter der Klassendeklaration und außerhalb einer Funktion zunächst die faule (faule) Avatar ImageView Variable wie folgt:

 lazy var avatar: UIImageView = { let imageView = UIImageView(image: UIImage(named: "avatar.jpg")) imageView.autoSetDimensions(to: CGSize(width: 128.0, height: 128.0)) imageView.layer.borderWidth = 3.0 imageView.layer.borderColor = UIColor.lightGray.cgColor imageView.layer.cornerRadius = 64.0 imageView.clipsToBounds = true return imageView }() 

Speichern Sie das Bild auf dem Desktop, das Sie als Avatar verwenden möchten, und ziehen Sie es in Xcode im Ordner <Ihr Projektname>, in meinem Fall "ContactCard". Aktivieren Sie das Kontrollkästchen "Elemente bei Bedarf kopieren" .

Bild

Schreiben Sie danach den Namen dieser Datei zusammen mit ihrer Erweiterung in die UIImage-Deklaration anstelle von "avatar.jpg".

Für diejenigen unter Ihnen, die es nicht wissen, ähneln Lazy-Variablen normalen Variablen, außer dass sie erst initialisiert werden (oder Speicherplatz zugewiesen wird), bis sie zum ersten Mal benötigt oder aufgerufen werden . Dies bedeutet, dass verzögerte Variablen nicht initialisiert werden, wenn der View Controller initialisiert wird, sondern einen späteren Zeitpunkt erwarten, an dem sie wirklich benötigt werden, was Verarbeitungsleistung und Speicherplatz für andere Prozesse spart. Dies ist besonders nützlich, wenn Sie Komponenten der Benutzeroberfläche initialisieren.

PureLayout in Aktion


Wie Sie in der Initialisierung sehen können, ist die Zeile imageView.autoSetDimensions (to: CGSize (width: 128.0, height: 128.0)) PureLayout in Aktion. In einer Zeile legen wir eine Grenze für die Höhe und Breite der UIImageView fest, und alle erforderlichen NSLayoutConstraints werden erstellt, ohne dass große Funktionsaufrufe erforderlich sind. Wenn Sie programmgesteuert Einschränkungen erstellen wollten, haben Sie sich höchstwahrscheinlich bereits in diese wunderbare Bibliothek verliebt.

Um dieses Bild rund zu machen, setzen wir seinen Winkelradius auf die Hälfte seiner Breite oder Höhe, was 64,0 Punkten entspricht. Setzen Sie außerdem die Eigenschaft clipsToBounds auf true , um dem Bild clipsToBounds , dass alles clipsToBounds soll, was außerhalb des gerade festgelegten Radius liegt.

Anschließend erstellen wir eine UIView, die als oberste Ansicht hinter dem grau gestrichenen Avatar dient. Deklarieren Sie die folgende Lazy-Variable für diese Ansicht:

 lazy var upperView: UIView = { let view = UIView() view.autoSetDimension(.height, toSize: 128) view.backgroundColor = .gray return view }() 

Unteransichten hinzufügen


Bevor wir fortfahren, erstellen wir eine func addSubviews () -Funktion, die die gerade erstellten Ansichten (und alle anderen, die wir erstellen werden) als Unteransichten zum Ansichtscontroller hinzufügt:

 func addSubviews() { self.view.addSubview(avatar) self.view.addSubview(upperView) } 

viewDidLoad (): self.addSubviews () nun die folgende Zeile zu viewDidLoad (): self.addSubviews ()

Einschränkungen festlegen


Um eine Vorstellung davon zu bekommen, wie weit wir gekommen sind, setzen wir diesen beiden Arten Grenzen. Erstellen Sie eine weitere Funktion namens func setupConstraints() und fügen Sie die folgenden Einschränkungen ein:

 func setupConstraints() { avatar.autoAlignAxis(toSuperviewAxis: .vertical) avatar.autoPinEdge(toSuperviewEdge: .top, withInset: 64.0) upperView.autoPinEdge(toSuperviewEdge: .left) upperView.autoPinEdge(toSuperviewEdge: .right) upperView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .bottom) } 

viewDidLoad() nun in viewDidLoad() setupConstraints() wie folgt auf: self.setupConstraints() . Fügen Sie dies hinzu, addSubviews() . Dies sollte die endgültige Schlussfolgerung sein:

Bild

Bringen Sie den Avatar in den Vordergrund


Leider möchte ich das nicht erhalten. Wie Sie sehen können, liegt unsere upperView über dem Avatar. Dies liegt an der Tatsache, dass wir vor der upperView subviews einen Avatar als subviews upperView haben. Da sich diese Unteransichten in irgendeiner Form auf dem Stapel befinden, erhalten wir dieses Ergebnis. Um dies zu beheben, können wir diese beiden Zeilen einfach durch andere ersetzen, aber es gibt noch einen anderen Trick, den ich Ihnen zeigen möchte: self.view.bringSubview (toFront: avatar) .

Diese Methode überträgt den Avatar vom unteren Rand des Stapels nach oben. Wählen Sie also die Methode aus, die Ihnen am besten gefällt. Aus Gründen der Lesbarkeit ist es natürlich besser, Unteransichten in der Reihenfolge hinzuzufügen, in der sie angezeigt werden sollen, wenn sie sich überschneiden. Beachten Sie jedoch, dass sich die ersten hinzugefügten Unteransichten am unteren Rand des Stapels befinden und daher alle anderen sich überschneidenden Ansichten darüber angezeigt werden.
Und so sollte es eigentlich aussehen:

Bild

Segmentierte Steuerung erstellen


Als Nächstes erstellen wir ein segmentiertes Steuerelement, einen grauen Balken mit drei Abschnitten. Tatsächlich ist ein segmentiertes Steuerelement einfach zu erstellen. Gehen Sie wie folgt vor:

 lazy var segmentedControl: UISegmentedControl = { let control = UISegmentedControl(items: ["Personal", "Social", "Resumè"]) control.autoSetDimension(.height, toSize: 32.0) control.selectedSegmentIndex = 0 control.layer.borderColor = UIColor.gray.cgColor control.tintColor = .gray return control }() 

Ich glaube, dass alles klar ist. Der einzige Unterschied besteht darin, dass wir nach der Initialisierung eine Reihe von Zeichenfolgen bereitstellen. Jede Zeile repräsentiert die Überschrift eines unserer gewünschten Abschnitte. Wir setzen außerdem selectedSegmentIndex auf 0, wodurch das segmentierte Steuerelement angewiesen wird, das erste Segment während der Initialisierung auszuwählen / auszuwählen. Der Rest ist nur ein Stil zum Spielen.

Fahren wir nun fort und fügen Sie es als Unteransicht hinzu, indem Sie am Ende der Funktion addCubviews(): self.view.addSubview(segmentedControl) die folgende Zeile addCubviews(): self.view.addSubview(segmentedControl) und seine Einschränkungen lauten wie folgt:

  segmentedControl.autoPinEdge(toSuperviewEdge: .left, withInset: 8.0) segmentedControl.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0) segmentedControl.autoPinEdge(.top, to: .bottom, of: avatar, withOffset: 16.0) 

Wir teilen dem segmentierten Steuerelement mit, dass wir es an der linken Seite der Übersicht anbringen möchten. Wir möchten jedoch das Intervall geringfügig erhöhen und nicht direkt am Bildschirmrand anbringen. Wenn Sie bemerken, verwende ich das sogenannte Acht-Punkte-Gitter, bei dem alle Abstände und Größen ein Vielfaches von acht sind. Ich mache dasselbe auf der rechten Seite des segmentierten Steuerelements. Was die letzte Einschränkung betrifft, sagt er, dass ein Scheitelpunkt mit einem Intervall von 16 Punkten an der Basis des Avatars angebracht wird.

Führen Sie den Code aus, nachdem Sie die oben genannten Einschränkungen zu func setupConstraints() und stellen Sie sicher, dass er folgendermaßen aussieht:

Bild

Hinzufügen eines Buttons


Nun kommen wir zum letzten Teil der Benutzeroberfläche des Lehrbuchs, der eine Schaltfläche „Bearbeiten“ ist. Fügen Sie die folgende faule Variable hinzu:

 lazy var editButton: UIButton = { let button = UIButton() button.setTitle("Edit", for: .normal) button.setTitleColor(.gray, for: .normal) button.layer.cornerRadius = 4.0 button.layer.borderColor = UIColor.gray.cgColor button.layer.borderWidth = 1.0 button.tintColor = .gray button.backgroundColor = .clear button.autoSetDimension(.width, toSize: 96.0) button.autoSetDimension(.height, toSize: 32.0) return button }() 

Machen Sie sich keine Sorgen darüber, wie groß die Initialisierung ist, sondern achten Sie darauf, wie ich den Titel und seine Farbe button.setTitle button.setTitleColor button.setTitle und button.setTitleColor . Aus bestimmten Gründen können wir den Titel einer Schaltfläche nicht festlegen, indem wir direkt auf ihr titleLabel zugreifen. Dies liegt daran, dass es unterschiedliche titleLabel für die Schaltfläche gibt und viele gerne unterschiedliche Überschriften / Farben für unterschiedliche Status haben.

Fügen Sie nun die Schaltfläche wie die übrigen Komponenten als Unteransicht hinzu und fügen Sie die folgenden Einschränkungen hinzu, damit sie dort angezeigt wird, wo sie sein sollte:

 editButton.autoPinEdge(.top, to: .bottom, of: upperView, withOffset: 16.0) editButton.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0) 

Hier haben wir nur die rechten und oberen Grenzen für die Schaltfläche festgelegt, da wir ihr eine Größe gegeben haben, sie sich nicht erweitert und nichts anderes benötigt wird. Führen Sie nun das Projekt aus, um das Endergebnis zu sehen:

Bild

Ein paar aktuelle Notizen


Üben Sie, fügen Sie so viele Oberflächenelemente hinzu, wie Sie möchten. Erstellen Sie Ansichten aller Anwendungen, die Ihnen schwer fallen. Fangen Sie einfach an und erhöhen Sie schrittweise die Schwierigkeit. Zeichnen Sie UI-Komponenten auf ein Blatt Papier, um sich vorzustellen, wie sie zusammenpassen.
Im zweiten Teil erweitere ich dieses Handbuch, um eine Navigationsleiste, eine Tabellenansicht und Zellen mit dynamischer Größe im Code zu erstellen.

Source: https://habr.com/ru/post/de444854/


All Articles