3DTouch - Escalas no iPhone: Conclusão

No último artigo, vimos como trabalhar com o 3DTouch no iPhone. Agora, resta concluir algumas pinceladas e finalizar nosso aplicativo.

imagem

Como eu disse, a principal funcionalidade está pronta, existem apenas melhorias:

  1. Ao atingir o valor máximo, desejo que a resposta à vibração funcione como no artigo de feedback da Haptic no iPhone 6s
  2. A atualização dos valores no UILabel acontece muito rapidamente (acho que você notou isso ao testar), portanto, é necessário adicionar alguma suavidade.
  3. Um círculo semitransparente deve aparecer no momento do pressionamento. Seu diâmetro deve aumentar com o aumento da pressão e diminuir com a diminuição da pressão

Os dois primeiros pontos que não posso exibir usando capturas de tela ou gifs animados. Portanto, faça as adições descritas abaixo e verifique você mesmo em seus dispositivos. E aqui vou demonstrar o terceiro ponto. Mas vamos adicionar complementos juntos.

Feedback de vibração Feedback de háptica


Importamos a estrutura AudioToolbox antes da declaração da classe ViewController e também adicionamos a propriedade isPlaySound para excluir a resposta repetida da resposta de vibração.

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

Em seguida, faça alterações no método touchesMoved (: :) para que fique assim:

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

Nada complicado - quando você executa o aplicativo iOS e, nesse caso, ao inicializar o ViewController e criar uma propriedade da classe isPlaySound, habilitamos a capacidade de reproduzir sons - incluindo respostas de vibração. Quando a pressão máxima é atingida, isPlaySound (1) é verificado e, se for verdade , a vibração é executada e a proibição (2) de reproduzir a vibração é imediatamente acionada. Esta proibição é levantada (3) se a força de prensagem se tornar menor que o valor máximo possível.

Atualização suave


Agora sobre suavidade. As atualizações de rótulos acontecem muito rapidamente, com a velocidade de resposta do método touchesMoved (: :) , e são centenas de operações por segundo. Para reduzir a taxa de atualização do rótulo, adicionei uma propriedade da classe ViewController isUpdate e defina os observadores da propriedade didSet .

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

A essência dessa construção é que, assim que configuramos esta propriedade como false, ela retorna para true após 0,01 segundos. Assim, ao escrever texto em UILabel, definiremos o valor da propriedade isUpdate como false e não permitiremos atualizar os rótulos até que se torne verdadeiro . Portanto, os registros serão atualizados conosco no máximo uma vez a cada centésimo de segundo.

No método touchesMoved (: :) , no ramo em que exibimos a% força e peso em gramas, altere o código da seguinte maneira:

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

Isso será suficiente para dar suavidade ao atualizar rótulos

Visualização por toque


Primeiro, vamos criar um UIView e torná-lo translúcido e redondo. Para fazer isso, adicione uma propriedade da classe ViewController e faça as configurações iniciais no método 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 } 

Existe uma propriedade, ela tem uma View , mas em que ponto ela deve ser adicionada à tela? É lógico que, no momento em que você começa a tocar. No ViewController, você precisa adicionar o método 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 } } 

Também selecionamos o primeiro do conjunto de toques e trabalhamos com esse toque

  1. Defina o centro do círculoVer como o ponto de toque
  2. Adicione cicrcleView à tela

No método touchesMoved (: :) na ramificação onde são processadas porcentagens e peso em gramas, adicione a linha:

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

Aqui, definimos a matriz de transformação para aumentar o tamanho do cicrcleView em altura e largura. Os valores que transferi para essa matriz são o resultado da seleção dos valores mais convenientes. Método de seleção "puxão". Assim, você pode experimentar e escolher os valores que são convenientes para você.

E, finalmente, no final do toque, você precisa cancelar a transformação do cicrleView e removê-lo da tela. Já temos um método no qual você pode trabalhar com isso. No método touchesEnded (: :) , adicione duas linhas:

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

O código completo do ViewController é assim:

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

Código do arquivo 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() } } 

Vincular projeto no GitHub

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


All Articles