3DTouch - Skalen auf dem iPhone: Fertigstellung

Im letzten Artikel haben wir uns mit der Arbeit mit 3DTouch auf dem iPhone befasst. Jetzt müssen wir noch ein paar Striche ausführen und unsere Bewerbung beenden.

Bild

Wie gesagt, die Hauptfunktionalität ist fertig, es gibt nur Verbesserungen:

  1. Wenn der Maximalwert erreicht ist, soll die Vibrationsreaktion wie im Artikel über haptisches Feedback auf dem iPhone 6s funktionieren
  2. Das Aktualisieren von Werten in UILabel erfolgt sehr schnell (ich glaube, Sie haben dies beim Testen bemerkt), sodass Sie etwas Glätte hinzufügen müssen.
  3. Am Druckpunkt sollte ein halbtransparenter Kreis erscheinen. Sein Durchmesser sollte mit zunehmendem Druck zunehmen und mit abnehmendem Druck abnehmen

Die ersten beiden Punkte kann ich weder mit Screenshots noch mit animierten Gifs anzeigen. Nehmen Sie daher die unten beschriebenen Ergänzungen vor und überprüfen Sie sie selbst auf Ihren Geräten. Und hier werde ich den dritten Punkt demonstrieren. Aber lassen Sie uns Add-Ons alles zusammen machen.

Vibrationsrückmeldung Haptische Rückmeldung


Wir importieren das AudioToolbox- Framework vor der Deklaration der ViewController- Klasse und fügen die isPlaySound- Eigenschaft hinzu, um die wiederholte Reaktion der Vibrationsreaktion auszuschließen.

import UIKit import AudioToolbox class ViewController: UIViewController { @IBOutlet weak var scaleView: ScaleView! @IBOutlet weak var forceLabel: UILabel! @IBOutlet weak var grammLabel: UILabel! var isPlaySound = true ... 

Nehmen Sie als Nächstes Änderungen an der Methode touchMoved (: :) vor , damit sie folgendermaßen aussieht:

  override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { cicrcleView.center = touch.location(in: view) if #available(iOS 9.0, *) { if traitCollection.forceTouchCapability == UIForceTouchCapability.available { if touch.force >= touch.maximumPossibleForce { forceLabel.text = "100%+ force" grammLabel.text = "385 " if isPlaySound { //  // 1 AudioServicesPlaySystemSound(1519) isPlaySound = false // 2 } } else { let force = (touch.force / touch.maximumPossibleForce) * 100 let grams = force * 385 / 100 let roundGrams = Int(grams) isPlaySound = true //  // 3 forceLabel.text = "\(Int(force))% force" grammLabel.text = "\(roundGrams) " } } } } } 

Nichts Kompliziertes - Wenn Sie die iOS-Anwendung ausführen und in diesem Fall den ViewController initialisieren und eine Eigenschaft der isPlaySound- Klasse erstellen, können Sie Sounds abspielen - einschließlich Vibrationsreaktionen. Wenn der maximale Druck erreicht ist, wird isPlaySound (1) überprüft und wenn dies zutrifft , wird eine Vibration ausgeführt und das Verbot (2) des Spielens der Vibration wird sofort ausgelöst. Dieses Verbot wird aufgehoben (3), wenn die Druckkraft unter den maximal möglichen Wert fällt.

Reibungsloses Update


Nun zur Glätte. Etikettenaktualisierungen erfolgen sehr schnell mit der Antwortgeschwindigkeit der Methode touchMoved (: :) , und dies sind mehrere hundert Vorgänge pro Sekunde. Um die Aktualisierungsrate des Etiketts zu verringern, habe ich eine Eigenschaft der ViewController- Klasse isUpdate hinzugefügt und die Beobachter der didSet- Eigenschaft festgelegt.

  var isUpdate = true { didSet { if isUpdate == false { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { self.isUpdate = oldValue } } } } 

Das Wesentliche einer solchen Konstruktion ist, dass sie nach 0,01 Sekunden auf true zurückkehrt, sobald wir diese Eigenschaft auf false setzen. Dementsprechend setzen wir beim Schreiben von Text in UILabel den Wert der isUpdate- Eigenschaft auf false und erlauben keine Aktualisierung der Beschriftungen, bis sie wahr werden . Daher werden die Aufzeichnungen bei uns nicht mehr als einmal alle Hundertstelsekunden aktualisiert.

Ändern Sie in der Methode touchMoved (: :) in dem Zweig, in dem die prozentuale Stärke und das Gewicht in Gramm angezeigt werden, den Code wie folgt:

 if isUpdate { forceLabel.text = "\(Int(force))% force" grammLabel.text = "\(roundGrams) " isUpdate = false } 

Dies reicht aus, um die Aktualisierung der Etiketten reibungslos zu gestalten

Berühren Sie die Visualisierung


Lassen Sie uns zunächst ein UIView erstellen und es durchscheinend und rund machen. Fügen Sie dazu eine Eigenschaft der ViewController- Klasse hinzu und nehmen Sie die Anfangseinstellungen in der viewDidLoad () -Methode vor

  let cicrcleView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80)) // View 80  80 override func viewDidLoad() { super.viewDidLoad() forceLabel.text = "0% force" grammLabel.text = "0 " cicrcleView.layer.cornerRadius = 40 //      View -   cicrcleView.alpha = 0.6 //  60% cicrcleView.backgroundColor = UIColor.red } 

Es gibt eine Eigenschaft mit einer Ansicht , aber an welcher Stelle sollte sie dem Bildschirm hinzugefügt werden? Es ist logisch, dass Sie im Moment anfangen zu berühren. Im ViewController müssen Sie die Methode touchBegan (: :) hinzufügen

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { cicrcleView.center = touch.location(in: view) // 1 view.addSubview(cicrcleView) // 2 } } 

Wir wählen auch die erste aus dem Satz von Berührungen aus und arbeiten mit dieser Berührung

  1. Stellen Sie den Mittelpunkt der Kreisansicht auf den Berührungspunkt ein
  2. Fügen Sie cicrcleView zum Bildschirm hinzu

Fügen Sie in der Methode touchMoved (: :) in dem Zweig, in dem Prozentsätze und Gewicht in Gramm verarbeitet werden, die folgende Zeile hinzu:

 cicrcleView.transform = CGAffineTransform.init(scaleX: CGFloat(1 + (grams / 5) / 20), y: CGFloat(1 + (grams / 5) / 20)) 

Hier setzen wir die Transformationsmatrix, um die Größe von cicrcleView in Höhe und Breite zu erhöhen. Die Werte, die ich in diese Matrix übertragen habe, sind das Ergebnis der Auswahl der bequemsten Werte. Auswahlmethode "poke". So können Sie experimentieren und die für Sie geeigneten Werte auswählen.

Und schließlich müssen Sie am Ende der Berührung die Umwandlung für cicrleView abbrechen und vom Bildschirm entfernen. Wir haben bereits eine Methode, mit der Sie sie ausarbeiten können. Fügen Sie in der Methode touchEnded (: :) zwei Zeilen hinzu:

  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { forceLabel.text = "0% force" grammLabel.text = "0 " //  cicrcleView.removeFromSuperview() //   cicrcleView.transform = .identity //     } 

Der vollständige ViewController- Code sieht folgendermaßen aus:

 import UIKit import AudioToolbox class ViewController: UIViewController { @IBOutlet weak var scaleView: ScaleView! @IBOutlet weak var forceLabel: UILabel! @IBOutlet weak var grammLabel: UILabel! var isPlaySound = true var isUpdate = true { didSet { if isUpdate == false { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { self.isUpdate = oldValue } } } } let cicrcleView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80)) override func viewDidLoad() { super.viewDidLoad() forceLabel.text = "0% force" grammLabel.text = "0 " cicrcleView.layer.cornerRadius = 40 cicrcleView.alpha = 0.6 cicrcleView.backgroundColor = UIColor.red } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { cicrcleView.center = touch.location(in: view) // 1 view.addSubview(cicrcleView) // 2 } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { cicrcleView.center = touch.location(in: view) if #available(iOS 9.0, *) { if traitCollection.forceTouchCapability == UIForceTouchCapability.available { if touch.force >= touch.maximumPossibleForce { forceLabel.text = "100%+ force" grammLabel.text = "385 " if isPlaySound { AudioServicesPlaySystemSound(1519) isPlaySound = false } } else { let force = (touch.force / touch.maximumPossibleForce) * 100 let grams = force * 385 / 100 let roundGrams = Int(grams) isPlaySound = true if isUpdate { forceLabel.text = "\(Int(force))% force" grammLabel.text = "\(roundGrams) " isUpdate = false } cicrcleView.transform = CGAffineTransform.init(scaleX: CGFloat(1 + (grams / 5) / 20), y: CGFloat(1 + (grams / 5) / 20)) } } } } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { forceLabel.text = "0% force" grammLabel.text = "0 " cicrcleView.removeFromSuperview() cicrcleView.transform = .identity } } 

ScaleView-Dateicode :

 import UIKit @IBDesignable class ScaleView: UIView { override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext() context?.setStrokeColor(UIColor.red.cgColor) context?.setLineWidth(14.0) context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 2 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) context?.strokePath() context?.setLineWidth(1.0) context?.setStrokeColor(UIColor.lightGray.cgColor) context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 4 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) context?.strokePath() } } 

Projekt auf GitHub verlinken

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


All Articles