Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UISlider highlight state with different thumb width than normal

I'm trying to implement a custom UISlider (subclass of UISlider), that behaves in a similar way to the native slider that has a glow around the thumb when it's highlighted. I'm having trouble with this, though.

The (effective) width of the highlighted thumb is obviously greater than the normal thumb (due to the glow). If I add transparent pixel padding to the normal state image, so that both images have the same width, the issue is that the normal state thumb never looks like it reaches the end of the track (it does reach the end, but the padding makes it appear otherwise).

If I use thumbRectForBounds: to offset the thumb to line up correctly with the beginning of the track, it only makes the issue worse at the other end.

If I keep both images only as wide as they need to be (ie, no padding on the normal state, and the two are not the same width), I've gotten closer. I can set the offset independently in thumbRectForBounds: based on the UIControl.state, but it seems like the there's some math magic going on behind the scenes. The only place where the UISlider thinks the images for both states line up perfectly is the exact center.

It seems like I may need to implement some math that determines the offset of the highlight state based on it relative position along the track. It would need an y-offset of zero at the center (the UISlider would center both images, which means they align). At the extremes, it would need a y-offset that completely makes up for the glow. And in between it would need to interpolate the y-offset.

This seems like a lot of work to recreate something the native slider does though, so perhaps I'm missing something obvious.

Update Current solution:

It's not entirely portable, since it makes some assumptions about the size of the glow being added. I'm adding the glow with an image rather than drawing it directly to the CALayer. I haven't tested how performant this is yet.

Essentially I create a layer that's a square whose dimensions are the height of the default state thumb image, center it over the thumb, and then draw the glow (only the glow, not a separate image of a thumb with a glow, as would be done with a hightlight state image) into the layer.

- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value {
  CGRect r = [super thumbRectForBounds:bounds trackRect:rect value:value];

  [thumbHighlightOverlayLayer removeFromSuperlayer];
  thumbHighlightOverlayLayer = [CALayer layer]; 

  int x = r.origin.x + (r.size.width / 2) - (r.size.height / 2);
  thumbHighlightOverlayLayer.frame = CGRectMake(x, r.origin.y, r.size.height, r.size.height);

  UIImage* thumbHighlightOverlayImage = [UIImage imageNamed:@"thumb-highlight"];
  thumbHighlightOverlayLayer.contents = (id)thumbHighlightOverlayImage.CGImage;

  switch (self.state) {
    case UIControlStateHighlighted:
      [[self layer] addSublayer:thumbHighlightOverlayLayer];
      break;
    default:
      break;
  }

  return r;
}
like image 256
farski Avatar asked May 03 '12 16:05

farski


1 Answers

instead of adding glow effect in the image, it may be better to add it dynamically. you can use CALayer to add glow effect.

CALayer

like image 113
Tejesh Alimilli Avatar answered Sep 21 '22 17:09

Tejesh Alimilli