@@ -35,8 +35,12 @@ static inline BOOL TORoundedButtonFloatsMatch(CGFloat firstValue, CGFloat second
3535 return fabs (firstValue - secondValue) > FLT_EPSILON;
3636}
3737
38- static inline BOOL TORoundedButtonIsDynamicBackground (TORoundedButtonBackgroundStyle backgroundStyle) {
39- return backgroundStyle != TORoundedButtonBackgroundStyleSolid;
38+ static inline BOOL TORoundedButtonIsSolidBackground (TORoundedButtonBackgroundStyle backgroundStyle) {
39+ return backgroundStyle == TORoundedButtonBackgroundStyleSolid;
40+ }
41+
42+ static inline BOOL TORoundedButtonIsTintableBackground (TORoundedButtonBackgroundStyle backgroundStyle) {
43+ return backgroundStyle != TORoundedButtonBackgroundStyleBlur;
4044}
4145
4246// --------------------------------------------------------------------
@@ -147,10 +151,6 @@ - (void)_roundedButtonCommonInit TOROUNDEDBUTTON_OBJC_DIRECT {
147151 _containerView.userInteractionEnabled = NO ;
148152 [self addSubview: _containerView];
149153
150- // Create the image view which will show the button background
151- _backgroundView = [self _makeBackgroundViewWithStyle: _backgroundStyle];
152- [_containerView addSubview: _backgroundView];
153-
154154 // The foreground content view
155155 [_containerView addSubview: _contentView];
156156
@@ -161,6 +161,17 @@ - (void)_roundedButtonCommonInit TOROUNDEDBUTTON_OBJC_DIRECT {
161161 [self addTarget: self action: @selector (_didDragInside ) forControlEvents: UIControlEventTouchDragEnter];
162162}
163163
164+ - (void )didMoveToSuperview {
165+ [super didMoveToSuperview ];
166+ if (self.superview == nil || _backgroundView != nil ) {
167+ return ;
168+ }
169+
170+ // Defer making the background until we're added to the subview in case the user changes it
171+ _backgroundView = [self _makeBackgroundViewWithStyle: _backgroundStyle];
172+ [_containerView insertSubview: _backgroundView atIndex: 0 ];
173+ }
174+
164175- (void )_makeTitleLabelIfNeeded TOROUNDEDBUTTON_OBJC_DIRECT {
165176 if (_titleLabel) { return ; }
166177
@@ -182,13 +193,12 @@ - (void)_makeTitleLabelIfNeeded TOROUNDEDBUTTON_OBJC_DIRECT {
182193
183194- (UIView *)_makeBackgroundViewWithStyle : (TORoundedButtonBackgroundStyle)style TOROUNDEDBUTTON_OBJC_DIRECT {
184195 UIView *backgroundView = nil ;
185- if (TORoundedButtonIsDynamicBackground (style)) {
196+ if (! TORoundedButtonIsSolidBackground (style)) {
186197 // Create a glass or blur style based on the associated style
187198 UIVisualEffect *effect = nil ;
188199 if (@available (iOS 26.0 , *)) {
189200 if (style == TORoundedButtonBackgroundStyleGlass) {
190201 UIGlassEffect *const glassEffect = [UIGlassEffect effectWithStyle: _glassStyle];
191- glassEffect.interactive = YES ;
192202 glassEffect.tintColor = self.tintColor ;
193203 effect = glassEffect;
194204 }
@@ -208,7 +218,7 @@ - (UIView *)_makeBackgroundViewWithStyle:(TORoundedButtonBackgroundStyle)style T
208218 if (@available (iOS 26.0 , *)) {
209219 backgroundView.cornerConfiguration = _cornerConfiguration;
210220 } else {
211- backgroundView.clipsToBounds = TORoundedButtonIsDynamicBackground (style);
221+ backgroundView.clipsToBounds = ! TORoundedButtonIsSolidBackground (style);
212222 backgroundView.layer .cornerRadius = _cornerRadius;
213223 }
214224
@@ -253,6 +263,7 @@ - (void)layoutSubviews {
253263 _titleLabel.frame = CGRectIntegral (_titleLabel.frame );
254264}
255265
266+ // We need to declare this since we explicitly define it in the header
256267- (void )sizeToFit { [super sizeToFit ]; }
257268
258269- (CGSize)sizeThatFits : (CGSize)size {
@@ -282,11 +293,32 @@ - (CGSize)sizeThatFits:(CGSize)size {
282293 return newSize;
283294}
284295
296+ - (void )_setBackgroundTintColor : (UIColor *)tintColor {
297+ if (_backgroundStyle == TORoundedButtonBackgroundStyleBlur) {
298+ return ;
299+ }
300+ #ifdef __IPHONE_26_0
301+ if (@available (iOS 26.0 , *)) {
302+ if (_backgroundStyle == TORoundedButtonBackgroundStyleGlass) {
303+ UIGlassEffect *effect = [UIGlassEffect effectWithStyle: UIGlassEffectStyleRegular];
304+ effect.tintColor = tintColor;
305+ [(UIVisualEffectView *)_backgroundView setEffect: effect];
306+ } else {
307+ _backgroundView.backgroundColor = tintColor;
308+ }
309+ } else {
310+ _backgroundView.backgroundColor = tintColor;
311+ }
312+ #else
313+ _backgroundView.backgroundColor = tintColor;
314+ #endif
315+ }
316+
285317- (void )tintColorDidChange {
286318 [super tintColorDidChange ];
287- if (TORoundedButtonIsDynamicBackground (_backgroundStyle)) { return ; }
319+ if (! TORoundedButtonIsTintableBackground (_backgroundStyle)) { return ; }
288320 _titleLabel.backgroundColor = [self _labelBackgroundColor ];
289- _backgroundView. backgroundColor = self.tintColor ;
321+ [ self _setBackgroundTintColor: self .tintColor] ;
290322 [self setNeedsLayout ];
291323}
292324
@@ -311,10 +343,8 @@ - (void)_updateTappedTintColorForTintColor TOROUNDEDBUTTON_OBJC_DIRECT {
311343}
312344
313345- (UIColor *)_labelBackgroundColor TOROUNDEDBUTTON_OBJC_DIRECT {
314- // Always return clear if tapped
315- if (_isTapped || TORoundedButtonIsDynamicBackground (_backgroundStyle)) { return [UIColor clearColor ]; }
316-
317- // Return clear if the tint color isn't opaque
346+ // Always return clear if we're not overlaying on a completely solid BG
347+ if (_isTapped || !TORoundedButtonIsSolidBackground (_backgroundStyle)) { return [UIColor clearColor ]; }
318348 const BOOL isClear = CGColorGetAlpha (self.tintColor .CGColor ) < (1 .0f - FLT_EPSILON);
319349 return isClear ? [UIColor clearColor ] : self.tintColor ;
320350}
@@ -367,19 +397,20 @@ - (void)_didDragInside {
367397#pragma mark - Animation -
368398
369399- (void )_setBackgroundColorTappedAnimated : (BOOL )animated TOROUNDEDBUTTON_OBJC_DIRECT {
370- if (!_tappedTintColor || TORoundedButtonIsDynamicBackground (_backgroundStyle)) { return ; }
400+ if (!_tappedTintColor || ! TORoundedButtonIsTintableBackground (_backgroundStyle)) { return ; }
371401
372402 // Toggle the background color of the title label
373403 void (^updateTitleOpacity)(void ) = ^{
374404 self->_titleLabel .backgroundColor = [self _labelBackgroundColor ];
375405 };
376406
377407 // -----------------------------------------------------
378-
408+
409+ UIColor *const destinationColor = _isTapped ? _tappedTintColor : self.tintColor ;
379410 void (^animationBlock)(void ) = ^{
380- self-> _backgroundView . backgroundColor = self-> _isTapped ? self-> _tappedTintColor : self. tintColor ;
411+ [ self _setBackgroundTintColor: destinationColor] ;
381412 };
382-
413+
383414 void (^completionBlock)(BOOL ) = ^(BOOL completed){
384415 if (completed == NO ) { return ; }
385416 updateTitleOpacity ();
@@ -399,7 +430,6 @@ - (void)_setBackgroundColorTappedAnimated:(BOOL)animated TOROUNDEDBUTTON_OBJC_DI
399430 animations: animationBlock
400431 completion: completionBlock];
401432 }
402-
403433}
404434
405435- (void )_setLabelAlphaTappedAnimated : (BOOL )animated TOROUNDEDBUTTON_OBJC_DIRECT {
@@ -443,7 +473,7 @@ - (void)_setButtonScaledTappedAnimated:(BOOL)animated TOROUNDEDBUTTON_OBJC_DIREC
443473 self->_containerView .transform = CGAffineTransformScale (CGAffineTransformIdentity,
444474 scale,
445475 scale);
446- };
476+ };
447477
448478 // If we're not animating, just call the blocks manually
449479 if (!animated) {
@@ -529,9 +559,7 @@ - (void)setTextPointSize:(CGFloat)textPointSize {
529559- (void )setTintColor : (UIColor *)tintColor {
530560 [super setTintColor: tintColor];
531561 [self _updateTappedTintColorForTintColor ];
532- if (!TORoundedButtonIsDynamicBackground (_backgroundStyle)) {
533- _backgroundView.backgroundColor = tintColor;
534- }
562+ [self _setBackgroundTintColor: tintColor];
535563 _titleLabel.backgroundColor = [self _labelBackgroundColor ];
536564 [self setNeedsLayout ];
537565}
@@ -567,7 +595,7 @@ - (void)setCornerRadius:(CGFloat)cornerRadius {
567595 _backgroundView.cornerConfiguration = _cornerConfiguration;
568596 } else {
569597 _backgroundView.layer .cornerRadius = _cornerRadius;
570- _backgroundView.layer .masksToBounds = TORoundedButtonIsDynamicBackground (_backgroundStyle);
598+ _backgroundView.layer .masksToBounds = ! TORoundedButtonIsSolidBackground (_backgroundStyle);
571599 }
572600#else
573601 _backgroundView.layer .cornerRadius = _cornerRadius;
@@ -592,18 +620,8 @@ - (void)setBackgroundStyle:(TORoundedButtonBackgroundStyle)backgroundStyle {
592620 _backgroundStyle = backgroundStyle;
593621 [_backgroundView removeFromSuperview ];
594622 _backgroundView = [self _makeBackgroundViewWithStyle: _backgroundStyle];
623+ [_containerView insertSubview: _backgroundView atIndex: 0 ];
595624 _titleLabel.backgroundColor = [self _labelBackgroundColor ];
596- const BOOL isGlass = backgroundStyle == TORoundedButtonBackgroundStyleGlass;
597- if (!isGlass) {
598- _containerView.hidden = NO ;
599- [_containerView insertSubview: _backgroundView atIndex: 0 ];
600- [_containerView addSubview: _contentView];
601- } else {
602- UIVisualEffectView *glassView = (UIVisualEffectView *)_backgroundView;
603- _containerView.hidden = YES ;
604- [self insertSubview: glassView atIndex: 0 ];
605- [glassView.contentView addSubview: _contentView];
606- }
607625 [self setNeedsLayout ];
608626}
609627
@@ -613,7 +631,7 @@ - (void)setBlurStyle:(UIBlurEffectStyle)blurStyle {
613631 }
614632
615633 _blurStyle = blurStyle;
616- if (! TORoundedButtonIsDynamicBackground ( _backgroundStyle) || ![_backgroundView isKindOfClass: [UIVisualEffectView class ]]) {
634+ if (_backgroundStyle != TORoundedButtonBackgroundStyleBlur || ![_backgroundView isKindOfClass: [UIVisualEffectView class ]]) {
617635 return ;
618636 }
619637
@@ -625,7 +643,7 @@ - (void)setGlassStyle:(UIGlassEffectStyle)glassStyle {
625643 if (_glassStyle == glassStyle) { return ; }
626644 _glassStyle = glassStyle;
627645
628- if (! TORoundedButtonIsDynamicBackground ( _backgroundStyle) || ![_backgroundView isKindOfClass: [UIVisualEffectView class ]]) {
646+ if (_backgroundStyle != TORoundedButtonBackgroundStyleGlass || ![_backgroundView isKindOfClass: [UIVisualEffectView class ]]) {
629647 return ;
630648 }
631649
0 commit comments