Skip to content

Commit 831bd3c

Browse files
committed
Added haptic API to the button
1 parent 11b3b60 commit 831bd3c

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

TORoundedButton/TORoundedButton.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ typedef NS_ENUM(NSInteger, TORoundedButtonBackgroundStyle) {
3333
TORoundedButtonBackgroundStyleGlass
3434
};
3535

36+
/// The types of impacts that the button can generate when tapped by the user.
37+
typedef NS_ENUM(NSInteger, TORoundedButtonImpactStyle) {
38+
TORoundedButtonImpactStyleNone = -1,
39+
TORoundedButtonImpactStyleLight = UIImpactFeedbackStyleLight,
40+
TORoundedButtonImpactStyleMedium = UIImpactFeedbackStyleMedium,
41+
TORoundedButtonImpactStyleHeavy = UIImpactFeedbackStyleHeavy
42+
};
43+
3644
NS_SWIFT_NAME(RoundedButtonDelegate)
3745
@protocol TORoundedButtonDelegate <NSObject>
3846

@@ -75,6 +83,9 @@ IB_DESIGNABLE @interface TORoundedButton : UIControl
7583
/// The style, whether static or dynamic of the button's background view.
7684
@property (nonatomic, assign) TORoundedButtonBackgroundStyle backgroundStyle;
7785

86+
/// The haptic impact style that this button will generate when tapped by the user. (Default is medium)
87+
@property (nonatomic, assign) TORoundedButtonImpactStyle impactStyle;
88+
7889
/// When `backgroundStyle` is set to `.blur`, the specific blur style to apply.
7990
@property (nonatomic, assign) UIBlurEffectStyle blurStyle;
8091

TORoundedButton/TORoundedButton.m

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ @implementation TORoundedButton {
6363
/** Maintain a reference to the corner configuration in case we swap out the background view */
6464
UICornerConfiguration *_cornerConfiguration API_AVAILABLE(ios(26.0));
6565
#endif
66+
67+
/** The current haptic feedback generator that will play vibrations when the button is tapped. */
68+
UIImpactFeedbackGenerator *_impactGenerator;
6669
}
6770

6871
#pragma mark - View Creation -
@@ -118,6 +121,7 @@ - (void)_roundedButtonCommonInit TOROUNDEDBUTTON_OBJC_DIRECT {
118121
_tappedTintColorBrightnessOffset = !TORoundedButtonFloatIsZero(_tappedTintColorBrightnessOffset) ?: -0.15f;
119122
_contentInset = (UIEdgeInsets){15.0, 15.0, 15.0, 15.0};
120123
_blurStyle = UIBlurEffectStyleDark;
124+
_impactStyle = TORoundedButtonImpactStyleMedium;
121125

122126
// Set the corner radius depending on system version
123127
#ifdef __IPHONE_26_0
@@ -211,6 +215,19 @@ - (UIView *)_makeBackgroundViewWithStyle:(TORoundedButtonBackgroundStyle)style T
211215
return backgroundView;
212216
}
213217

218+
- (UIImpactFeedbackGenerator *)_makeImpactGeneratorWithStyle:(TORoundedButtonImpactStyle)style TOROUNDEDBUTTON_OBJC_DIRECT {
219+
if (style == TORoundedButtonImpactStyleNone) {
220+
return nil;
221+
}
222+
223+
const UIImpactFeedbackStyle impactStyle = (UIImpactFeedbackStyle)style;
224+
if (@available(iOS 17.5, *)) {
225+
return [UIImpactFeedbackGenerator feedbackGeneratorWithStyle:impactStyle forView:self];
226+
}
227+
228+
return [[UIImpactFeedbackGenerator alloc] initWithStyle:impactStyle];
229+
}
230+
214231
#pragma mark - View Lifecycle -
215232

216233
- (void)didMoveToSuperview {
@@ -222,6 +239,11 @@ - (void)didMoveToSuperview {
222239
// Defer making the background until we're added to the subview in case the user changes it
223240
_backgroundView = [self _makeBackgroundViewWithStyle:_backgroundStyle];
224241
[_containerView insertSubview:_backgroundView atIndex:0];
242+
243+
// If the button has been configured to set up an impact generator, create it now.
244+
if (_impactStyle != TORoundedButtonImpactStyleNone && !_impactGenerator) {
245+
_impactGenerator = [self _makeImpactGeneratorWithStyle:_impactStyle];
246+
}
225247
}
226248

227249
- (void)tintColorDidChange {
@@ -308,6 +330,9 @@ - (CGSize)sizeThatFits:(CGSize)size {
308330
- (void)_didTouchDownInside {
309331
_isTapped = YES;
310332

333+
// Preheat the impact generator to prepare playing it when we tap up.
334+
[_impactGenerator prepare];
335+
311336
// The user touched their finger down into the button bounds
312337
[self _setLabelAlphaTappedAnimated:NO];
313338
[self _setBackgroundColorTappedAnimated:YES];
@@ -317,6 +342,9 @@ - (void)_didTouchDownInside {
317342
- (void)_didTouchUpInside {
318343
_isTapped = NO;
319344

345+
// Play the impact.
346+
[_impactGenerator impactOccurred];
347+
320348
// The user lifted their finger up from inside the button bounds
321349
[self _setLabelAlphaTappedAnimated:YES];
322350
[self _setBackgroundColorTappedAnimated:YES];
@@ -585,6 +613,12 @@ - (void)setEnabled:(BOOL)enabled {
585613
_containerView.alpha = enabled ? 1 : 0.4;
586614
}
587615

616+
- (void)setImpactStyle:(TORoundedButtonImpactStyle)impactStyle {
617+
if (_impactStyle == impactStyle) { return; }
618+
_impactStyle = impactStyle;
619+
_impactGenerator = [self _makeImpactGeneratorWithStyle:impactStyle];
620+
}
621+
588622
#pragma mark - Private -
589623

590624
- (void)_setBackgroundTintColor:(UIColor *)tintColor TOROUNDEDBUTTON_OBJC_DIRECT {

0 commit comments

Comments
 (0)