我正在尝试创建一个UISlider
,它可以让你从一个数字数组中进行选择。每个滑块的位置应该是等距的,滑块应该会捕捉到每个位置,而不是在它们之间平滑地滑动。(这就是iOS 7中引入的设置
> 通用
> 文本大小
中滑块的行为方式。)
我想要选择的数字是:-3, 0, 2, 4, 7, 10和12。
(我对Objective-C非常陌生,因此完整的代码示例比代码片段更有帮助。=)
我正在尝试创建一个UISlider
,它可以让你从一个数字数组中进行选择。每个滑块的位置应该是等距的,滑块应该会捕捉到每个位置,而不是在它们之间平滑地滑动。(这就是iOS 7中引入的设置
> 通用
> 文本大小
中滑块的行为方式。)
我想要选择的数字是:-3, 0, 2, 4, 7, 10和12。
(我对Objective-C非常陌生,因此完整的代码示例比代码片段更有帮助。=)
其他答案有些可行,但这个方法可以让你在滑块的每个位置之间获得相同的固定间距。在这个例子中,你把滑块的位置视为一个数组的索引,该数组包含你感兴趣的实际数值。
@interface MyViewController : UIViewController {
UISlider *slider;
NSArray *numbers;
}
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
slider = [[UISlider alloc] initWithFrame:self.view.bounds];
[self.view addSubview:slider];
// These number values represent each slider position
numbers = @[@(-3), @(0), @(2), @(4), @(7), @(10), @(12)];
// slider values go from 0 to the number of values in your numbers array
NSInteger numberOfSteps = ((float)[numbers count] - 1);
slider.maximumValue = numberOfSteps;
slider.minimumValue = 0;
// As the slider moves it will continously call the -valueChanged:
slider.continuous = YES; // NO makes it call only once you let go
[slider addTarget:self
action:@selector(valueChanged:)
forControlEvents:UIControlEventValueChanged];
}
- (void)valueChanged:(UISlider *)sender {
// round the slider position to the nearest index of the numbers array
NSUInteger index = (NSUInteger)(slider.value + 0.5);
[slider setValue:index animated:NO];
NSNumber *number = numbers[index]; // <-- This numeric value you want
NSLog(@"sliderIndex: %i", (int)index);
NSLog(@"number: %@", number);
}
class MySliderStepper: UISlider {
private let values: [Float]
private var lastIndex: Int? = nil
let callback: (Float) -> Void
init(frame: CGRect, values: [Float], callback: @escaping (_ newValue: Float) -> Void) {
self.values = values
self.callback = callback
super.init(frame: frame)
self.addTarget(self, action: #selector(handleValueChange(sender:)), for: .valueChanged)
let steps = values.count - 1
self.minimumValue = 0
self.maximumValue = Float(steps)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func handleValueChange(sender: UISlider) {
let newIndex = Int(sender.value + 0.5) // round up to next index
self.setValue(Float(newIndex), animated: false) // snap to increments
let didChange = lastIndex == nil || newIndex != lastIndex!
if didChange {
lastIndex = newIndex
let actualValue = self.values[newIndex]
self.callback(actualValue)
}
}
}
slider.continuous = NO;
,它允许用户在拖动滑块时获得更平滑的操作。因为它只在用户完成拖动并将滑块移动到最接近的整数值时才评估valueChanged
函数。 - jdev15
值:@IBAction func timeSliderChanged(sender: UISlider) {
let newValue = Int(sender.value/15) * 15
sender.setValue(Float(newValue), animated: false)
}
@IBDesignable
class SnappableSlider: UISlider {
@IBInspectable
var interval: Int = 1
override init(frame: CGRect) {
super.init(frame: frame)
setUpSlider()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpSlider()
}
private func setUpSlider() {
addTarget(self, action: #selector(handleValueChange(sender:)), for: .valueChanged)
}
@objc func handleValueChange(sender: UISlider) {
let newValue = (sender.value / Float(interval)).rounded() * Float(interval)
setValue(Float(newValue), animated: false)
}
}
如果有人需要“snaping animation”(滑块停止时自动对齐),可以按照以下步骤操作:
您也可以在 Swift 中执行相同的操作:slider.isContinuous = false
ViewController
中添加以下 @IBAction
: @IBAction func sliderMoved(_ slider: UISlider){
let stepCount = 10
let roundedCurrent = (slider.value/Float(stepCount)).rounded()
let newValue = Int(roundedCurrent) * stepCount
slider.setValue(Float(newValue), animated: true)
}
我受到这个答案的启发。
-(int)roundSliderValue:(float)x {
if (x < -1.5) {
return -3;
} else if (x < 1.0) {
return 0;
} else if (x < 3.0) {
return 2;
} else if (x < 5.5) {
return 4;
} else if (x < 8.5) {
return 7;
} else if (x < 11.0) {
return 10;
} else {
return 12;
}
}
slider.continuous = YES;
[slider addTarget:self
action:@selector(valueChanged:)
forControlEvents:UIControlEventValueChanged];
-(void)valueChanged:(id)slider {
[slider setValue:[self roundSliderValue:slider.value] animated:NO];
}
和PengOne的方法类似,但我进行了手动舍入以使发生的情况更清晰。
- (IBAction)sliderDidEndEditing:(UISlider *)slider {
// default value slider will start at
float newValue = 0.0;
if (slider.value < -1.5) {
newValue = -3;
} else if (slider.value < 1) {
newValue = 0;
} else if (slider.value < 3) {
newValue = 2;
} else if (slider.value < 5.5) {
newValue = 4;
} else if (slider.value < 8.5) {
newValue = 7;
} else if (slider.value < 11) {
newValue = 10;
} else {
newValue = 12;
}
slider.value = newValue;
}
- (IBAction)sliderValueChanged:(id)sender {
UISlider *slider = sender;
float newValue = 0.0;
if (slider.value < -1.5) {
newValue = -3;
} else if (slider.value < 1) {
newValue = 0;
} else if (slider.value < 3) {
newValue = 2;
} else if (slider.value < 5.5) {
newValue = 4;
} else if (slider.value < 8.5) {
newValue = 7;
} else if (slider.value < 11) {
newValue = 10;
} else {
newValue = 12;
}
// and if you have a label displaying the slider value, set it
[yourLabel].text = [NSString stringWithFormat:@"%d", (int)newValue];
}