将 UIImage 作为“刻度线”添加到 UISlider

Posted

技术标签:

【中文标题】将 UIImage 作为“刻度线”添加到 UISlider【英文标题】:Adding UIImage's as "Tick Marks" to UISlider 【发布时间】:2015-05-25 00:32:07 【问题描述】:

预先总结一下我的问题:我正在尝试根据仅知道 UISlider 的持续时间来确定可以在滑块上放置图像的位置,并有一组时间循环遍历,相应地放置图像。

我一直在阅读有关 UISlider 的 Apple Docs,似乎没有本地方法可以根据浮点数组在 UISlider 上添加“刻度线”。 “刻度线”是指滑块上的线条,例如用于将广告放置在洗涤器上的线条。这是一个可视化:

现在,我有一个充满浮点数的数组;根据 UISlider 的值,我将使用浮动来删除刻度线。数组中浮点数的值每次都会不同。我想遍历我的 UISlider 的 .value 属性,相应地删除 UIImages。 UIImage 是我创建的小 png 资产的刻度线。我无法弄清楚的是循环遍历 UISlider 的 .value 属性并根据 UISlider 的未来位置放置 UIImage 背后的逻辑。数组中浮点数的值每次都会不同,所以我不能静态放置它们。有谁知道从哪里开始?我对 Objective-C 编程还是有点陌生​​。

我知道可以利用检索滑块在屏幕上的起始 X 坐标,如下所示:

- (float)xPositionFromSliderValue:(UISlider *)aSlider;

    float sliderRange = aSlider.frame.size.width - aSlider.currentThumbImage.size.width;
    float sliderOrigin = aSlider.frame.origin.x + (aSlider.currentThumbImage.size.width / 2.0);

    float sliderValueToPixels = (((aSlider.value-aSlider.minimumValue)/(aSlider.maximumValue-aSlider.minimumValu‌​e)) * sliderRange) + sliderOrigin);

    return sliderValueToPixels;

也许我可以在 for 循环中添加一个计算来根据该计算放置图像。我只是不太确定从哪里开始......

【问题讨论】:

UISlider 没有持续时间属性。你是说价值属性吗?如果是这样,请编辑您的问题。 是的,我的意思是持续时间,我的变量的名称是持续时间。 OP 已编辑。 另外,滑块的宽度与其最小值或最大值无关。它由滑块的 frame 属性决定。但是,它们无法获取滑块开始和结束的确切位置。 @MichaelL 没错,我更新了 OP,其中包含可以用来代替它的潜在代码。 【参考方案1】:

trackRectForBounds 和 thumbRectForBounds 方法是为 UISlider 子类化提供的,但您可以直接调用它们,它们会提前获取刻度中心。

- (float)sliderThumbCenter:(UISlider *)slider forValue:(float)value
    CGRect trackRect = [slider trackRectForBounds:slider.bounds];
    CGRect thumbRect = [slider thumbRectForBounds:slider.bounds trackRect:trackRect value:value];
    CGFloat centerThumb = CGRectGetMidX(thumbRect);
    return centerThumb;

使用自定义视图来绘制轨道可能比图像视图更容易,然后只需将滑块放在它上面并隐藏轨道。只需使滑块框架等于 TickView 的边界。真的,我认为 UISlider 子类会更好,但这有效!

@interface TickView : UIView
@property UIColor *tickColor;
@property int tickCount;
@property CGFloat tickHeight;
@property (weak) UISlider *slider;
@property float *ticks;
-(void)setTicks:(float *)ticks count:(int)tickCount;
@end


@implementation TickView
    __weak UISlider *_slider;


-(instancetype)initWithFrame:(CGRect)frame
    self = [super initWithFrame:frame];
    if (self) 
        self.tickColor = [UIColor grayColor];
        self.backgroundColor = [UIColor clearColor];
        self.tickCount = 7;
        self.ticks = malloc(sizeof(float) * self.tickCount);
        self.tickHeight = 10;
    
    return self;


- (void)drawRect:(CGRect)rect 
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(context, self.tickColor.CGColor);

    CGContextBeginPath(context);
    CGFloat centerY = rect.size.height / 2;
    CGContextMoveToPoint(context, 0, centerY);
    CGContextAddLineToPoint(context, rect.size.width, centerY);
    CGFloat tickTop = centerY - self.tickHeight / 2;
    CGFloat tickBottom = centerY + self.tickHeight / 2;
    CGFloat tickX = 0;

    if (self.slider) 
        for (int i = 0; i < self.tickCount; i++) 
            tickX = [self sliderThumbCenter:self.slider forValue:self.ticks[i]];
            CGContextMoveToPoint(context, tickX, tickTop);
            CGContextAddLineToPoint(context, tickX, tickBottom);
        
    
    else
        CGFloat tickSpacing = rect.size.width / (self.tickCount - 1);
        for (int i = 0; i < self.tickCount; i++) 
            CGContextMoveToPoint(context, tickX, tickTop);
            CGContextAddLineToPoint(context, tickX, tickBottom);
            tickX += tickSpacing;
        
    
    CGContextStrokePath(context);


-(void)setTicks:(float *)ticks count:(int)tickCount
    free(_ticks);
    _ticks = malloc(sizeof(float) * tickCount);
    memcpy(_ticks, ticks, sizeof(float) * tickCount);
    _tickCount = tickCount;
    [self setNeedsDisplay];

- (float)sliderThumbCenter:(UISlider *)slider forValue:(float)value
    CGRect trackRect = [slider trackRectForBounds:slider.bounds];
    CGRect thumbRect = [slider thumbRectForBounds:slider.bounds trackRect:trackRect value:value];
    CGFloat centerThumb = CGRectGetMidX(thumbRect);
    return centerThumb;

-(void)setSlider:(UISlider *)slider
    _slider = slider;

-(UISlider *)slider
    return _slider;

-(void)dealloc
    free(_ticks);

@end

【讨论】:

感谢您的意见!在您发布的第一种方法中,似乎调用会移动洗涤器,不是吗?我要完成的主要目标是根据只知道 UISlider 的持续时间来确定我可以在滑块上放置图像的位置,并有一系列时间来循环放置它们。 不,它不会移动拇指。它的目的是让拇指中心的 x 偏移量达到某个值。因此,如果您的滑块从 0 -> 10,并且您想知道拇指 位于 7 的位置(相对于滑块的框架,您将获得像 thisCGFloat xOffset = [self sliderThumbCenter:slider forValue:7]; 这样的 x 偏移量。您可以通过将 7 替换为 slider.value 来获得当前拇指中心 x 偏移量。【参考方案2】:

我认为您在定位刻度线时会遇到问题。但是,如果您的 UISlider 的父视图是“视图”,您可以像这样添加一个子视图:

[view addSubView:myTickView];

添加的子视图的位置由它的frame属性决定,在父视图坐标空间中。 要删除视图,请执行以下操作:

[myTickView removeFromSuperView];

您还可以循环浏览刻度视图并更改帧,但这些更改将被动画化,因此如果您这样做,刻度会显示为滑动,除非您关闭动画。

【讨论】:

以上是关于将 UIImage 作为“刻度线”添加到 UISlider的主要内容,如果未能解决你的问题,请参考以下文章

向 jQuery 滑块添加刻度线? [复制]

在 matplotlib imshow 中调整网格线和刻度线

在jQuery滑块上添加刻度线? [重复]

将 UIImage 视图作为子视图添加到 UIView 的实例

如何在 Python 中向直方图添加特定的 x 刻度线? [复制]

在 R 中,如何在显示日期的 x 轴上添加每月刻度线?