3DTouch - Timbangan pada iPhone: Penyelesaian

Pada artikel terakhir, kami melihat bekerja dengan 3DTouch di iPhone. Sekarang tinggal menyelesaikan beberapa pukulan dan menyelesaikan aplikasi kami.

gambar

Seperti yang saya katakan, fungsi utama sudah siap, hanya ada peningkatan:

  1. Ketika mencapai nilai maksimum, saya ingin respons getaran berfungsi seperti pada artikel umpan balik Haptic di iPhone 6s
  2. Memperbarui nilai dalam UILabel terjadi sangat cepat, (saya pikir Anda perhatikan ini saat pengujian) sehingga Anda perlu menambahkan beberapa kehalusan.
  3. Lingkaran semitransparan akan muncul pada titik penekanan. Diameternya harus meningkat dengan meningkatnya tekanan dan penurunan dengan penurunan tekanan

Dua poin pertama yang saya tidak bisa tampilkan menggunakan screenshot atau menggunakan animasi gif . Karena itu, buat penambahan yang dijelaskan di bawah ini dan periksa sendiri di perangkat Anda. Dan di sini saya akan menunjukkan poin ketiga. Tapi mari kita add-on melakukan semuanya bersama-sama.

Umpan balik getaran Umpan balik haptic


Kami mengimpor kerangka AudioToolbox sebelum deklarasi kelas ViewController , dan juga menambahkan properti isPlaySound untuk mengecualikan respons berulang dari respons getaran.

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 ... 

Selanjutnya, buat perubahan pada metode touchesMoved (: :) sehingga terlihat seperti ini:

  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) " } } } } } 

Tidak ada yang rumit - ketika Anda menjalankan aplikasi iOS, dan dalam hal ini, ketika menginisialisasi ViewController dan membuat properti dari kelas isPlaySound, kami memungkinkan kemampuan untuk memutar suara - termasuk respons getaran. Ketika tekanan maksimum tercapai, isPlaySound (1) dicentang dan jika itu benar , getaran dilakukan dan larangan (2) untuk memainkan getaran segera dipicu. Larangan ini diangkat (3) jika gaya penekan menjadi kurang dari nilai maksimum yang dimungkinkan.

Pembaruan lancar


Sekarang tentang kehalusan. Pembaruan label datang dengan sangat cepat, dengan kecepatan respons metode touchesMoved (: :) , dan ini beberapa ratus operasi per detik. Untuk mengurangi kecepatan refresh label, saya menambahkan properti dari kelas ViewController isUpdate dan mengatur pengamat properti didSet .

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

Inti dari konstruksi semacam itu adalah bahwa segera setelah kami menyetel properti ini menjadi false, ia kembali ke true setelah 0,01 detik. Karenanya, saat menulis teks ke UILabel, kami akan menetapkan nilai properti isUpdate ke false dan tidak akan mengizinkan memperbarui label hingga menjadi benar . Karenanya, catatan akan diperbarui dengan kami tidak lebih dari sekali setiap seratus detik.

Dalam metode touchesMoved (: :) , di cabang tempat kami menampilkan% kekuatan dan berat dalam gram, ubah kode sebagai berikut:

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

Ini akan cukup untuk memberikan kelancaran saat memperbarui label

Sentuh visualisasi


Pertama, mari kita buat UIView dan membuatnya tembus dan bulat. Untuk melakukan ini, tambahkan properti dari kelas ViewController dan buat pengaturan awal dalam metode viewDidLoad ()

  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 } 

Ada properti, ia memiliki View , tetapi pada titik apa ia harus ditambahkan ke layar? Adalah logis bahwa pada saat Anda mulai menyentuh. Di ViewController Anda perlu menambahkan metode touchesBegan (: :)

  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 } } 

Kami juga memilih yang pertama dari set sentuhan dan bekerja dengan sentuhan ini

  1. Setel pusat circleView ke titik sentuh
  2. Tambahkan cicrcleView ke layar

Dalam metode touchesMoved (: :) di cabang tempat persentase dan berat gram diproses, tambahkan baris:

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

Di sini kita mengatur matriks transformasi untuk meningkatkan ukuran cicrcleView dalam tinggi dan lebar. Nilai-nilai yang saya transfer ke matriks ini adalah hasil dari pemilihan nilai yang paling nyaman. Metode pemilihan "menyodok." Jadi Anda bisa bereksperimen dan memilih nilai-nilai yang sesuai untuk Anda.

Dan akhirnya, di akhir sentuhan, Anda perlu membatalkan transformasi untuk cicrleView dan menghapusnya dari layar. Kami sudah memiliki metode untuk mengatasinya. Dalam metode touchesEnded (: :) , tambahkan dua baris:

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

Kode ViewController lengkap terlihat seperti ini:

 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 } } 

Kode File ScaleView :

 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() } } 

Tautkan proyek di GitHub

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


All Articles