【问题标题】:Thumb image does not move to the edge of UISlider拇指图像不会移动到 UISlider 的边缘
【发布时间】:2014-02-26 13:26:42
【问题描述】:

即使它的值为最大值或最小值,拇指图像也不会移动到边缘。

有谁知道如何让它一直移动到滑块的边缘?

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UISlider *slider;
@end

@implementation ViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIImage* sliderBarMinImage = [[UIImage imageNamed:@"slider_bar_3_min"] stretchableImageWithLeftCapWidth:8.0 topCapHeight:0.0];
UIImage* sliderBarImage = [[UIImage imageNamed:@"slider_bar_3_max"] stretchableImageWithLeftCapWidth:8.0 topCapHeight:0.0];
UIImage* sliderThumbImage= [[UIImage imageNamed:@"slider_thumb_3"] stretchableImageWithLeftCapWidth:8.0 topCapHeight:0.0];

[self.slider setMinimumTrackImage:sliderBarMinImage forState:UIControlStateNormal];
[self.slider setMaximumTrackImage:sliderBarImage forState:UIControlStateNormal];
[self.slider setThumbImage:sliderThumbImage forState:UIControlStateNormal];
}
@end

【问题讨论】:

    标签: ios slider


    【解决方案1】:

    您看到的是 UISlider 显然按设计工作。

    默认情况下,在极值处,拇指的边缘与轨道的边缘对齐,而不是拇指的中心位于轨道的边缘。因此,如果您提供的缩略图图像的左右边缘不是不透明的,那么这是一个问题,因为这样下面的轨道就会变得可见。

    一个部分修复是覆盖thumbRectForBounds(_:trackRect:value:),以便拇指的中心范围跨越滑块的宽度。下面的代码显示了这一点:

    class CenteredThumbSlider : UISlider {
      override func thumbRectForBounds(bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect
      {
        let unadjustedThumbrect = super.thumbRectForBounds(bounds, trackRect: rect, value: value)
        let thumbOffsetToApplyOnEachSide:CGFloat = unadjustedThumbrect.size.width / 2.0
        let minOffsetToAdd = -thumbOffsetToApplyOnEachSide
        let maxOffsetToAdd = thumbOffsetToApplyOnEachSide
        let offsetForValue = minOffsetToAdd + (maxOffsetToAdd - minOffsetToAdd) * CGFloat(value / (self.maximumValue - self.minimumValue))
        var origin = unadjustedThumbrect.origin
        origin.x += offsetForValue
        return CGRect(origin: origin, size: unadjustedThumbrect.size)
      }
    }
    

    但是,我会说这只是一个部分修复,因为我不相信这也会修改拇指点击区域的位置,所以上面的修复有一个不幸的副作用是拇指比默认情况下更不容易触摸,因为滑块仍然会更靠近滑块的中心侦听触摸。

    【讨论】:

    • 我相信你想乘以 CGFloat((value - self.minimumValue) / (self.maximumValue - self.minimumValue)) 而不是 CGFloat(value / (self.maximumValue - self.minimumValue) )) 考虑非零值
    【解决方案2】:

    我最近不得不处理滑块的自定义(子类),包括在滑块上添加刻度线。拇指图像不以该值为中心,并且由于您替换了图像,因此根据实现,它位于应有的位置。 为了做你想做的事,我不得不使用

    调整拇指图像的位置
    - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
    

    【讨论】:

      【解决方案3】:

      如果没有更改,最受好评的答案对我不起作用。这就是所做的——它是UISlider 的替代品:

      class Slider: UISlider {
      
          override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float)->CGRect {
      
                  var thumbRect = super.thumbRect(forBounds: bounds, trackRect: rect, value: value)
      
                  //determine value dependent offset
                  var offsetForValue: CGFloat = 0
                  if value != 0 {offsetForValue = thumbRect.size.width * CGFloat(value / (self.maximumValue - self.minimumValue)) - ((value > 0) ? 2 : -2)}
      
                  //apply offset to thumb rect
                  thumbRect.origin.x += offsetForValue
      
                  return thumbRect
          }
      }
      

      【讨论】:

        【解决方案4】:

        代替

        [self.slider setMinimumTrackImage:sliderBarMinImage forState:UIControlStateNormal];
        [self.slider setMaximumTrackImage:sliderBarImage forState:UIControlStateNormal];
        [self.slider setThumbImage:sliderThumbImage forState:UIControlStateNormal];
        

        尝试像这样设置外观代理

        [[UISlider appearance] setMinimumTrackImage:sliderBarMinImage forState:UIControlStateNormal];
        [[UISlider appearance] setMaximumTrackImage:sliderBarImage forState:UIControlStateNormal];
        [[UISlider appearance] setThumbImage:sliderThumbImage forState:UIControlStateNormal];
        

        【讨论】:

          【解决方案5】:

          您会看到它已经移动到滑块的边缘。这是因为拇指图像滑块有这样的角落,所以你感觉它没有移动到边缘。

          如果您想确认这一点,请尝试与拇指图像中的方形图像相同的代码。

          希望对你有帮助。

          【讨论】:

            【解决方案6】:

            它可能不是最有效的,但它似乎工作正常。这是在 Objective-C 中实现它的另一种简单方法。基本上,您将使用“pixelAdjustment”变量来获得所需的滑块。

            - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:   (float)value {
                float multValue = value - 0.5;
                float pixelAdjustment = 30; //This is the value you need to change depending on the size of the thumb image of your slider.
                float xOriginDelta = (multValue * (bounds.size.width - pixelAdjustment));
            
                CGRect adjustedRect = CGRectMake(bounds.origin.x + xOriginDelta, bounds.origin.y, bounds.size.width, bounds.size.height);
                return adjustedRect;
            }
            

            【讨论】:

              【解决方案7】:

              我通过继承 UISlider 创建了类似的滑块。 在情节提要中,如果滑块拇指未获得触摸事件,您可以设置高度约束以在运行时增加高度。

              static float const SLIDER_OFFSET = 10.0;
              
              //Get thumb rect for larger track rect than actual to move slider to edges
                  -(CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value {
                      UIImage *image = self.currentThumbImage;
              
                  rect.origin.x -= SLIDER_OFFSET;
                  rect.size.width += (SLIDER_OFFSET*2);
                  CGRect thumbRect = [super thumbRectForBounds:bounds trackRect:rect value:value];
                  return CGRectMake(thumbRect.origin.x, rect.origin.y+2, image.size.width, image.size.height);
              }
              
              //Make track rect smaller than bounds
              -(CGRect)trackRectForBounds:(CGRect)bounds  {
                  bounds.origin.x += SLIDER_OFFSET;
                  bounds.size.width -= (SLIDER_OFFSET*2);
                  CGRect trackRect = [super trackRectForBounds:bounds];
              
                  return CGRectMake(trackRect.origin.x, trackRect.origin.y, trackRect.size.width, trackRect.size.height);
              }
              

              【讨论】:

                【解决方案8】:

                我找到了一个更简单的解决方案,它也有一个非常流畅的用户体验。

                我基本上只是将.highlighted 图像设置为与.normal 相同的值。这是代码。

                    seekBar.setThumbImage(thumbImage, for: .normal)
                    seekBar.setThumbImage(thumbImage, for: .highlighted)
                

                【讨论】:

                  【解决方案9】:

                  所以我对这个问题的解决方案是让滑块的颜色 Min Track 和 Max Track 透明,然后在 initWithCoder 中绘制一个新的轨道,并在 continueTrackingWithTouch 中更新轨道的大小。

                  -(AnalogueSlider *)initWithCoder:(NSCoder *)coder :(NSArray *)labels {
                      self = [super initWithCoder:coder];
                  
                      trackRect = [self trackRectForBounds:self.bounds];
                      thumbRect = [self thumbRectForBounds:self.bounds trackRect:trackRect value:self.value];
                  
                      // drawn a new track
                      leftTrack = [[UIView alloc] initWithFrame:CGRectMake(trackRect.origin.x+thumbRect.size.width/2.0, trackRect.origin.y, thumbRect.origin.x-thumbRect.size.width, trackRect.size.height)];
                      leftTrack.backgroundColor = [UIColor blueColor];
                      [self insertSubview:leftTrack belowSubview:self];
                  
                      rightTrack = [[UIView alloc] initWithFrame:CGRectMake(thumbRect.origin.x+thumbRect.size.width/2.0, trackRect.origin.y, trackRect.size.width-thumbRect.origin.x, trackRect.size.height)];
                      rightTrack.backgroundColor = [UIColor grayColor];
                      [self insertSubview:rightTrack belowSubview:self];
                  
                      return self;
                  }
                  
                  -(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
                      thumbRect = [self thumbRectForBounds:self.bounds trackRect:trackRect value:self.value];
                      leftTrack.frame = CGRectMake(trackRect.origin.x+thumbRect.size.width/2.0, trackRect.origin.y, thumbRect.origin.x-thumbRect.size.width, trackRect.size.height);
                      rightTrack.frame = CGRectMake(thumbRect.origin.x+thumbRect.size.width/2.0, trackRect.origin.y, trackRect.size.width-thumbRect.origin.x, trackRect.size.height);
                  
                      return [super continueTrackingWithTouch:touch withEvent:event];
                  }
                  

                  这允许拇指图像比轨道移动得更远,因此拇指的中心位于轨道的末端。

                  最后:

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多