Ios 拇指图像不会移动到UISlider的边缘

Ios 拇指图像不会移动到UISlider的边缘,ios,slider,Ios,Slider,拇指图像不会移动到边缘,即使其值为“最大”或“最小” 有人知道如何让它一直移动到滑块的边缘吗 @interface ViewController () @property (weak, nonatomic) IBOutlet UISlider *slider; @end @implementation ViewController - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; UIImage* sl

拇指图像不会移动到边缘,即使其值为“最大”或“最小”

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

@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

而不是

[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];

我最近不得不处理滑块(子类)的定制,包括在滑块上添加记号。Thumb图像不以值为中心,因为您替换了图像,所以根据实现将其定位在应该的位置。 为了做你们想做的事,我必须用手指调整拇指图像的位置

- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value

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

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

一个部分修复方法是覆盖
thumbRectForBounds(uu2;: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)
  }
}

但是,我想说这只是一个局部修复,因为我不认为这也会修改拇指轻触区域的位置,因此上述修复具有不幸的副作用,使拇指比默认情况下更不容易触摸,由于滑块仍在侦听更多朝向滑块中心的触摸。

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

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


我希望它能对您有所帮助。

我通过对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);
}

如果没有改变,大多数被否决的答案对我来说都不起作用。这就是我们所做的——它是对
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
    }
}

这可能不是最有效的,但似乎效果很好。这是在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;
}

我发现了一个更简单的解决方案,它也有一个非常平滑的用户体验

我基本上只是将突出显示的
.highlighted
图像设置为与
.normal
相同的值。这是密码

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

因此,我对这个问题的解决方案是使滑块“最小轨迹”和“最大轨迹”的颜色透明,然后在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];
}
这允许拇指图像移动得比轨迹更远,因此拇指的中心位于轨迹的末端

最后:


我相信您希望用CGFloat((value-self.minimumValue)/(self.maximumValue-self.minimumValue))而不是CGFloat(value/(self.maximumValue-self.minimumValue))来计算非零值