Support haptic feedback on new Magic Keyboard
This commit is contained in:
parent
3cb0f46533
commit
5abd265195
|
@ -204,14 +204,19 @@ class FastAccountSwitcherViewController: UIViewController {
|
|||
@objc private func handleLongPress(_ recognizer: UIGestureRecognizer) {
|
||||
switch recognizer.state {
|
||||
case .began:
|
||||
show()
|
||||
|
||||
#if !os(visionOS)
|
||||
if #available(iOS 17.5, *) {
|
||||
UIImpactFeedbackGenerator(style: .heavy, view: view).impactOccurred(at: CGPoint(x: view.bounds.midX, y: view.bounds.midY))
|
||||
selectionChangedFeedbackGenerator = UISelectionFeedbackGenerator(view: view)
|
||||
} else {
|
||||
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
|
||||
selectionChangedFeedbackGenerator = UISelectionFeedbackGenerator()
|
||||
}
|
||||
selectionChangedFeedbackGenerator?.prepare()
|
||||
#endif
|
||||
|
||||
show()
|
||||
|
||||
case .changed:
|
||||
let location = recognizer.location(in: view)
|
||||
|
||||
|
@ -260,7 +265,11 @@ class FastAccountSwitcherViewController: UIViewController {
|
|||
|
||||
#if !os(visionOS)
|
||||
if hapticFeedback {
|
||||
if #available(iOS 17.5, *) {
|
||||
selectionChangedFeedbackGenerator?.selectionChanged(at: location)
|
||||
} else {
|
||||
selectionChangedFeedbackGenerator?.selectionChanged()
|
||||
}
|
||||
selectionChangedFeedbackGenerator?.prepare()
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -282,7 +282,11 @@ private class VideoScrubbingControl: UIControl {
|
|||
sendActions(for: .editingDidBegin)
|
||||
|
||||
#if !os(visionOS)
|
||||
if #available(iOS 17.5, *) {
|
||||
feedbackGenerator = UIImpactFeedbackGenerator(style: .light, view: self)
|
||||
} else {
|
||||
feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||||
}
|
||||
feedbackGenerator!.prepare()
|
||||
#endif
|
||||
|
||||
|
@ -301,8 +305,12 @@ private class VideoScrubbingControl: UIControl {
|
|||
let newFractionComplete = max(0, min(1, unclampedFractionComplete))
|
||||
#if !os(visionOS)
|
||||
if newFractionComplete != fractionComplete && (newFractionComplete == 0 || newFractionComplete == 1) {
|
||||
if #available(iOS 17.5, *) {
|
||||
feedbackGenerator!.impactOccurred(intensity: 0.5, at: location)
|
||||
} else {
|
||||
feedbackGenerator!.impactOccurred(intensity: 0.5)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fractionComplete = newFractionComplete
|
||||
sendActions(for: .editingChanged)
|
||||
|
|
|
@ -150,7 +150,13 @@ class CustomAlertActionsView: UIControl {
|
|||
private var separatorSizeConstraints: [NSLayoutConstraint] = []
|
||||
|
||||
#if !os(visionOS)
|
||||
private let generator = UISelectionFeedbackGenerator()
|
||||
private lazy var generator: UISelectionFeedbackGenerator = {
|
||||
if #available(iOS 17.5, *) {
|
||||
UISelectionFeedbackGenerator(view: self)
|
||||
} else {
|
||||
UISelectionFeedbackGenerator()
|
||||
}
|
||||
}()
|
||||
#endif
|
||||
private var currentSelectedActionIndex: Int?
|
||||
|
||||
|
@ -313,7 +319,13 @@ class CustomAlertActionsView: UIControl {
|
|||
actionButtons[currentSelectedActionIndex].backgroundColor = nil
|
||||
}
|
||||
#if !os(visionOS)
|
||||
if #available(iOS 17.5, *) {
|
||||
let view = selectedButton!.element
|
||||
let location = convert(CGPoint(x: view.bounds.midX, y: view.bounds.midY), from: view)
|
||||
generator.selectionChanged(at: location)
|
||||
} else {
|
||||
generator.selectionChanged()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,13 @@ class PollOptionsView: UIControl {
|
|||
static let scaledTransform = CGAffineTransform(scaleX: 0.95, y: 0.95)
|
||||
|
||||
#if !os(visionOS)
|
||||
private let generator = UISelectionFeedbackGenerator()
|
||||
private lazy var generator: UISelectionFeedbackGenerator = {
|
||||
if #available(iOS 17.5, *) {
|
||||
UISelectionFeedbackGenerator(view: self)
|
||||
} else {
|
||||
UISelectionFeedbackGenerator()
|
||||
}
|
||||
}()
|
||||
#endif
|
||||
|
||||
override var isEnabled: Bool {
|
||||
|
@ -159,7 +165,11 @@ class PollOptionsView: UIControl {
|
|||
animator.startAnimation()
|
||||
|
||||
#if !os(visionOS)
|
||||
if #available(iOS 17.5, *) {
|
||||
generator.selectionChanged(at: view.center)
|
||||
} else {
|
||||
generator.selectionChanged()
|
||||
}
|
||||
generator.prepare()
|
||||
#endif
|
||||
|
||||
|
@ -172,7 +182,9 @@ class PollOptionsView: UIControl {
|
|||
|
||||
override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
|
||||
let location = touch.location(in: self)
|
||||
let newIndex = optionView(at: location)?.1
|
||||
let newIndexAndOption = optionView(at: location)
|
||||
let newIndex = newIndexAndOption?.1
|
||||
let option = newIndexAndOption?.0
|
||||
|
||||
if newIndex != currentSelectedOptionIndex {
|
||||
currentSelectedOptionIndex = newIndex
|
||||
|
@ -189,8 +201,12 @@ class PollOptionsView: UIControl {
|
|||
animator.startAnimation()
|
||||
|
||||
#if !os(visionOS)
|
||||
if newIndex != nil {
|
||||
if let option {
|
||||
if #available(iOS 17.5, *) {
|
||||
generator.selectionChanged(at: option.center)
|
||||
} else {
|
||||
generator.selectionChanged()
|
||||
}
|
||||
generator.prepare()
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,13 @@ class ScrollingSegmentedControl<Value: Hashable>: UIScrollView, UIGestureRecogni
|
|||
private var changeSelectionPanRecognizer: UIGestureRecognizer!
|
||||
private var selectedOptionAtStartOfPan: Value?
|
||||
#if !os(visionOS)
|
||||
private lazy var selectionChangedFeedbackGenerator = UISelectionFeedbackGenerator()
|
||||
private lazy var selectionChangedFeedbackGenerator: UISelectionFeedbackGenerator = {
|
||||
if #available(iOS 17.5, *) {
|
||||
UISelectionFeedbackGenerator(view: self)
|
||||
} else {
|
||||
UISelectionFeedbackGenerator()
|
||||
}
|
||||
}()
|
||||
#endif
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
|
@ -111,14 +117,20 @@ class ScrollingSegmentedControl<Value: Hashable>: UIScrollView, UIGestureRecogni
|
|||
|
||||
func setSelectedOption(_ value: Value, animated: Bool) {
|
||||
guard selectedOption != value,
|
||||
options.contains(where: { $0.value == value }) else {
|
||||
let index = options.firstIndex(where: { $0.value == value }) else {
|
||||
return
|
||||
}
|
||||
|
||||
#if !os(visionOS)
|
||||
if selectedOption != nil {
|
||||
if #available(iOS 17.5, *) {
|
||||
let optionView = optionsStack.arrangedSubviews[index]
|
||||
let location = convert(CGPoint(x: optionView.bounds.midX, y: optionView.bounds.midY), from: optionView)
|
||||
selectionChangedFeedbackGenerator.selectionChanged(at: location)
|
||||
} else {
|
||||
selectionChangedFeedbackGenerator.selectionChanged()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
selectedOption = value
|
||||
|
@ -158,15 +170,19 @@ class ScrollingSegmentedControl<Value: Hashable>: UIScrollView, UIGestureRecogni
|
|||
// MARK: Interaction
|
||||
|
||||
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
guard gestureRecognizer === self.panGestureRecognizer else {
|
||||
return true
|
||||
}
|
||||
|
||||
let beganOnSelectedOption: Bool
|
||||
if let selectedIndex = options.firstIndex(where: { $0.value == selectedOption }),
|
||||
optionsStack.arrangedSubviews[selectedIndex].frame.contains(self.panGestureRecognizer.location(in: optionsStack)) {
|
||||
optionsStack.arrangedSubviews[selectedIndex].frame.contains(gestureRecognizer.location(in: optionsStack)) {
|
||||
beganOnSelectedOption = true
|
||||
} else {
|
||||
beganOnSelectedOption = false
|
||||
}
|
||||
|
||||
// only begin changing selection if the gesutre started on the currently selected item
|
||||
// only begin changing selection if the gesture started on the currently selected item
|
||||
// otherwise, let the scroll view handle things
|
||||
if gestureRecognizer == self.changeSelectionPanRecognizer {
|
||||
return beganOnSelectedOption
|
||||
|
@ -223,7 +239,12 @@ class ScrollingSegmentedControl<Value: Hashable>: UIScrollView, UIGestureRecogni
|
|||
}
|
||||
animator.startAnimation()
|
||||
#if !os(visionOS)
|
||||
if #available(iOS 17.5, *) {
|
||||
let locationInSelf = convert(location, from: optionsStack)
|
||||
selectionChangedFeedbackGenerator.selectionChanged(at: locationInSelf)
|
||||
} else {
|
||||
selectionChangedFeedbackGenerator.selectionChanged()
|
||||
}
|
||||
#endif
|
||||
return true
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue