UISlider 突出显示状态,拇指宽度与正常不同

Posted

技术标签:

【中文标题】UISlider 突出显示状态,拇指宽度与正常不同【英文标题】:UISlider highlight state with different thumb width than normal 【发布时间】:2012-05-03 16:14:12 【问题描述】:

我正在尝试实现一个自定义 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;

【问题讨论】:

***.com/questions/755510/customizing-uislider-look 问题主要是关于轨道图像,而不是拇指图像。编写我自己的滑块可能仍然是这里唯一的答案,但由于我正在尝试重新创建本机行为,我仍然想知道是否有办法避免需要这样做。 【参考方案1】:

与其在图像中添加发光效果,不如动态添加。您可以使用 CALayer 来添加发光效果。

CALayer

【讨论】:

这将是相当困难的,因为 UISlider 似乎没有任何可以添加阴影的子视图或子层。 就像 Andreas 说的那样,这并不完全直截了当,因为无法直接访问拇指图像的视图,但我想出了一个似乎可行的解决方案。谢谢你的想法,Tejesh。 @farski 谢谢。如果您能分享有效的解决方案,那就太好了。 上周我将它添加到我的原始帖子中。【参考方案2】:

您可以滚动自己的滑块,这并不像听起来那么复杂,但仍需要几个小时的编码。

但是,最简单的解决方案是也设置自定义轨道图像:

    使用填充创建自定义“最小”/“最大”轨道图像 (透明像素)在左侧/右侧。内边距应与发光半径减去拇指半径 (11pt) 一样大。 使用setMinimumTrackImage:forState: 将图像应用到您的 UISlider 和 setMaximumTrackImage:forState: 根据添加的填充大小增加滑块宽度

【讨论】:

【参考方案3】:

我在我的一个应用程序的自定义滑块中遇到了类似的问题。与普通滑块不同,轨道是静态数字线,因此我不需要单独的最小和最大轨道图像。然而,我需要一个超大的拇指热点。所以我用透明像素的额外填充制作了我的拇指图像,并将透明图像分配给轨道。可见轨道只是滑块后面的一个 UIImageView(实际上是一组滑块后面的一个 UIImageView)。滑块的边缘远远超出轨道图像的边缘。

我的建议是通过组合多个视图而不是打破自定义 UISlider 的限制来构建您想要的滑块的视觉结构。如果你可以不改变轨道,你可以复制我的技术。或者,您可以操纵一个或两个 UIView 的框架,以便在滑块更改值时调整自定义轨道。如果您需要在应用程序中多次使用相同的滑块,您可以将视图组打包到 UIView 子类中。根据您的滑块操作的复杂程度,可能会出现一个更谨慎的选择,即制作自定义控件。

【讨论】:

以上是关于UISlider 突出显示状态,拇指宽度与正常不同的主要内容,如果未能解决你的问题,请参考以下文章

自定义 UI 滑块,拇指图像大小问题

UISlider 的 minView 超出了它的边界和拇指的中心

自定义 UISlider 外观

具有清晰背景的 UISlider 拇指图像在其后面显示轨道

如何移除 UISlider 的预填充

UISlider 拇指中心位于轨道的起点和终点