3DTouch-在iPhone上缩放:完成

上一篇文章中,我们研究了如何在iPhone上使用3DTouch。 现在,需要完成几个步骤并完成我们的应用程序。

图片

正如我所说,主要功能已经准备就绪,只有改进之处:

  1. 当达到最大值时,我希望振动响应像iPhone 6s上的触觉反馈文章一样起作用
  2. UILabel中的值更新非常迅速(我认为您在测试时注意到了这一点),因此需要增加一些平滑度。
  3. 半透明的圆圈应该出现在按压点处。 其直径应随压力增加而增大,而随压力减小而减小

前两点我无法使用屏幕截图或动画gif来显示 。 因此,进行如下所述的添加操作,然后在设备上自行检查。 在这里,我将说明第三点。 但是,让我们的附加组件一起完成这一切。

振动反馈触觉反馈


我们在ViewController类的声明之前导入AudioToolbox框架,并添加isPlaySound属性以排除振动响应的重复响应。

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

接下来,对touchesMoved(::)方法进行更改,使其看起来像这样:

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

没什么复杂的-当您运行iOS应用程序时,在这种情况下,当初始化ViewController并创建isPlaySound类的属性时我们启用了播放声音的功能-包括振动响应。 当达到最大压力时,检查isPlaySound (1),如果为true ,则执行振动,并立即触发播放振动的禁止(2)。 如果按压力小于最大可能值,则取消此禁止(3)。

顺利更新


现在介绍平滑度。 标签更新以touchesMoved(::)方法的响应速度非常快地完成,这是每秒几百次操作。 为了降低标签的刷新率,我添加了ViewController isUpdate类的属性,并设置了didSet属性observers

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

这种构造的本质是,只要将此属性设置为false,它就会在0.01秒后返回true。 因此,在将文本写入UILabel时,我们将isUpdate属性的值设置为false ,直到变为true时才允许更新标签。 因此,记录与我们的更新不会超过百分之一秒。

touchesMoved(::)方法中,在显示以克为单位的强度和重量百分比的分支中,更改代码,如下所示:

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

这足以在更新标签时提供平滑度

触摸可视化


首先,让我们创建一个UIView并使它半透明和圆形。 为此,添加ViewController类的属性并在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 } 

有一个属性,它具有View ,但是应该在什么时候将其添加到屏幕上? 在您开始接触时,这是合乎逻辑的。 在ViewController中,您需要添加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 } } 

我们还从一组触摸中选择第一个,并使用该触摸

  1. circleView的中心设置为接触点
  2. cicrcleView添加到屏幕

在处理百分比和重量(克)的分支的touchesMoved(::)方法中,添加以下行:

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

在这里,我们设置转换矩阵以增加cicrcleView的高度和宽度。 我转移到此矩阵的值是选择最方便的值的结果。 选择方法“戳”。 因此,您可以进行实验并选择方便的值。

最后,在触摸结束时,您需要取消cicrleView的转换并将其从屏幕上删除。 我们已经有了一种可以解决的方法。 在touchesEnded(::)方法中,添加两行:

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

完整的ViewController代码如下所示:

 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文件代码

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

GitHub上的链接项目

Source: https://habr.com/ru/post/zh-CN417339/


All Articles