我正在尝试实现一个自定义 UISlider(UISlider 的子类),其行为方式类似于在突出显示时在拇指周围发光的本机滑块。不过,我遇到了麻烦。
高亮拇指的(有效)宽度明显大于正常拇指(由于发光)。如果我向正常状态图像添加透明像素填充,以便两个图像具有相同的宽度,问题是正常状态拇指看起来永远不会到达轨道的末端(它确实到达了末端,但填充使它以其他方式出现)。
如果我使用 thumbRectForBounds: 偏移拇指以与轨道的开头正确对齐,它只会使另一端的问题变得更糟。
如果我只保留两个图像所需的宽度(即,在正常状态下没有填充,并且两者的宽度不同),我已经更接近了。我可以在 thumbRectForBounds: 中独立设置偏移量:基于 UIControl.state,但似乎在幕后发生了一些数学魔术。UISlider 认为两个状态的图像完美对齐的唯一位置是精确的中心。
似乎我可能需要实现一些数学运算,根据沿轨道的相对位置确定突出显示状态的偏移量。它需要在中心的 y 偏移为零(UISlider 将使两个图像居中,这意味着它们对齐)。在极端情况下,它需要一个完全弥补发光的 y 偏移。在两者之间,它需要插入 y 偏移量。
不过,要重新创建本机滑块所做的事情似乎需要做很多工作,所以也许我遗漏了一些明显的东西。
更新 当前解决方案:
它不是完全可移植的,因为它对所添加的辉光的大小做出了一些假设。我正在使用图像添加发光,而不是直接将其绘制到 CALayer。我还没有测试过它的性能如何。
本质上,我创建了一个正方形的图层,其尺寸是默认状态拇指图像的高度,将其居中于拇指上,然后绘制发光(只有发光,而不是带有发光的拇指的单独图像,就像使用高亮状态图像完成)到图层中。
- (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;
}