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.

Wie gesagt, die Hauptfunktionalität ist fertig, es gibt nur Verbesserungen:
- Wenn der Maximalwert erreicht ist, soll die Vibrationsreaktion wie im Artikel über haptisches Feedback auf dem iPhone 6s funktionieren
- 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.
- 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)
Wir wählen auch die erste aus dem Satz von Berührungen aus und arbeiten mit dieser Berührung
- Stellen Sie den Mittelpunkt der Kreisansicht auf den Berührungspunkt ein
- 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 "
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