Skip to content
This repository
Browse code

Support stretchable-height image-based backgrounds

- SMCalloutImageBackgroundView now attempts to resize its images to fit the callout's height.
- System graphics are now loaded as stretchable with sane defaults, even though they weren't really designed to be stretched it works very well (except for the gloss point not being in the middle).
- Closes #36
  • Loading branch information...
commit 0fd8fdb339b5db8ba9c984935a2e0d474cf48824 1 parent 8be4534
Nick Farina authored

Showing 1 changed file with 20 additions and 11 deletions. Show diff stats Hide diff stats

  1. +20 11 SMCalloutView.m
31 SMCalloutView.m
@@ -18,8 +18,8 @@ @interface UIView (SMFrameAdditions)
18 18
19 19 NSTimeInterval kSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0;
20 20
21   -#define CALLOUT_MIN_WIDTH 75 // our background graphics limit us to this minimum width...
22   -#define CALLOUT_HEIGHT 70 // ...and allow only for this exact height.
  21 +#define CALLOUT_DEFAULT_MIN_WIDTH 75 // our image-based background graphics limit us to this minimum width...
  22 +#define CALLOUT_DEFAULT_HEIGHT 70 // ...and allow only for this exact height.
23 23 #define CALLOUT_DEFAULT_WIDTH 153 // default "I give up" width when we are asked to present in a space less than our min width
24 24 #define TITLE_MARGIN 17 // the title view's normal horizontal margin from the edges of our callout view
25 25 #define TITLE_TOP 11 // the top of the title view when no subtitle is present
@@ -140,13 +140,13 @@ - (CGFloat)calloutHeight {
140 140 if (self.contentView)
141 141 return self.contentView.$height + TITLE_TOP*2 + ANCHOR_HEIGHT + BOTTOM_ANCHOR_MARGIN;
142 142 else
143   - return CALLOUT_HEIGHT;
  143 + return CALLOUT_DEFAULT_HEIGHT;
144 144 }
145 145
146 146 - (CGSize)sizeThatFits:(CGSize)size {
147 147
148 148 // odd behavior, but mimicking the system callout view
149   - if (size.width < CALLOUT_MIN_WIDTH)
  149 + if (size.width < CALLOUT_DEFAULT_MIN_WIDTH)
150 150 return CGSizeMake(CALLOUT_DEFAULT_WIDTH, self.calloutHeight);
151 151
152 152 // calculate how much non-negotiable space we need to reserve for margin and accessories
@@ -185,7 +185,7 @@ - (CGSize)sizeThatFits:(CGSize)size {
185 185 }
186 186
187 187 // ensure we're big enough to fit our graphics!
188   - preferredWidth = fmaxf(preferredWidth, CALLOUT_MIN_WIDTH);
  188 + preferredWidth = fmaxf(preferredWidth, CALLOUT_DEFAULT_MIN_WIDTH);
189 189
190 190 // ask to be smaller if we have space, otherwise we'll fit into what we have by truncating the title/subtitle.
191 191 return CGSizeMake(fminf(preferredWidth, size.width), self.calloutHeight);
@@ -479,11 +479,11 @@ @implementation SMCalloutBackgroundView
479 479
480 480 + (SMCalloutBackgroundView *)systemBackgroundView {
481 481 SMCalloutImageBackgroundView *background = [SMCalloutImageBackgroundView new];
482   - background.leftCapImage = [self embeddedImageNamed:@"SMCalloutViewLeftCap"];
483   - background.rightCapImage = [self embeddedImageNamed:@"SMCalloutViewRightCap"];
484   - background.topAnchorImage = [self embeddedImageNamed:@"SMCalloutViewTopAnchor"];
485   - background.bottomAnchorImage = [self embeddedImageNamed:@"SMCalloutViewBottomAnchor"];
486   - background.backgroundImage = [self embeddedImageNamed:@"SMCalloutViewBackground"];
  482 + background.leftCapImage = [[self embeddedImageNamed:@"SMCalloutViewLeftCap"] stretchableImageWithLeftCapWidth:16 topCapHeight:20];
  483 + background.rightCapImage = [[self embeddedImageNamed:@"SMCalloutViewRightCap"] stretchableImageWithLeftCapWidth:0 topCapHeight:20];
  484 + background.topAnchorImage = [[self embeddedImageNamed:@"SMCalloutViewTopAnchor"] stretchableImageWithLeftCapWidth:0 topCapHeight:33];
  485 + background.bottomAnchorImage = [[self embeddedImageNamed:@"SMCalloutViewBottomAnchor"] stretchableImageWithLeftCapWidth:0 topCapHeight:20];
  486 + background.backgroundImage = [[self embeddedImageNamed:@"SMCalloutViewBackground"] stretchableImageWithLeftCapWidth:0 topCapHeight:20];
487 487 return background;
488 488 }
489 489
@@ -642,6 +642,15 @@ - (void)layoutSubviews {
642 642 bottomAnchor.image = self.bottomAnchorImage;
643 643 leftBackground.image = self.backgroundImage;
644 644 rightBackground.image = self.backgroundImage;
  645 +
  646 + // stretch the images to fill our vertical space. The system background images aren't really stretchable,
  647 + // but that's OK because you'll probably be using title/subtitle rather than contentView if you're using the
  648 + // system images, and in that case the height will match the system background heights exactly and no stretching
  649 + // will occur. However, if you wish to define your own custom background using prerendered images, you could
  650 + // define stretchable images using -stretchableImageWithLeftCapWidth:TopCapHeight and they'd get stretched
  651 + // properly here if necessary.
  652 + leftCap.$height = rightCap.$height = leftBackground.$height = rightBackground.$height = self.$height - 13;
  653 + topAnchor.$height = bottomAnchor.$height = self.$height;
645 654
646 655 BOOL pointingUp = self.arrowPoint.y < self.$height/2;
647 656
@@ -650,7 +659,7 @@ - (void)layoutSubviews {
650 659 bottomAnchor.hidden = pointingUp;
651 660
652 661 // if we're pointing up, we'll need to push almost everything down a bit
653   - CGFloat dy = !topAnchor.hidden ? TOP_ANCHOR_MARGIN : 0;
  662 + CGFloat dy = pointingUp ? TOP_ANCHOR_MARGIN : 0;
654 663 leftCap.$y = rightCap.$y = leftBackground.$y = rightBackground.$y = dy;
655 664
656 665 leftCap.$x = 0;

0 comments on commit 0fd8fdb

Please sign in to comment.
Something went wrong with that request. Please try again.