UISlider smoothly changes the cost

I have a UIslider setting the position for AVAdioRecording:

CGRect frame = CGRectMake(50.0, 230.0, 200.0, 10.0); aSlider = [[UISlider alloc] initWithFrame:frame]; // Set a timer which keep getting the current music time and update the UISlider in 1 sec interval sliderTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES]; // Set the maximum value of the UISlider aSlider.maximumValue = player.duration; // Set the valueChanged target [aSlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged]; [self.ViewA addSubview:aSlider]; - (void)updateSlider { // Update the slider about the music time [UIView beginAnimations:@"returnSliderToInitialValue" context:NULL]; [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; [UIView setAnimationDuration:1.3]; aSlider.value = player.currentTime; [UIView commitAnimations]; } - (IBAction)sliderChanged:(UISlider *)sender { // Fast skip the music when user scroll the UISlider [player stop]; [player setCurrentTime:aSlider.value]; [player prepareToPlay]; [player play]; } 

There are three questions I would like to ask.

1) Why animation to change the value does not work? 2) Why does the position of the slider move only when I release my finger from the button and do not follow it? 3) Does NSTimer use the best way to do this? I heard that NSTimer consumes a lot of memory ...

+6
source share
3 answers

Why value animation doesn't work

You obviously found the value property. Check the documentation and you will see this offer

To make an animated transition from the current value to the new value, you must use the setValue:animated: method instead.

So, as the documentation says, use

 [aSlider setValue:player.currentTime animated:YES]; 

Why do you only get events when you release your finger

The reason you only get events when you release your finger is because your slider is not continuous. From the documentation for the continuous property:

If YES , the slider continuously transmits update events to the appropriate target action method. If NO , the slider sends an action event only when the user releases the thumb of the slider to set the final value.

NSTimer is not the best way

No, using NSTimer to animate changes, as this is definitely not the best way, I would say that it is very bad practice to use a timer. Not only is this inefficient and possibly inaccurate, but you are also losing built-in support to facilitate animation.

If you really cannot do this without a timer, you should at least use CADisplayLink instead of NSTimer . It is designed to work with user interface updates (unlike NSTimer, which is not).

+15
source

You should probably use them:

  • Set the slider property to continuous in YES when you create the slider,

    in your case aSlider.continuous = YES;

  • Use the setValue:animated method,

    in your case [aSlider setValue:player.currentTime animated:YES];

+5
source

I was looking for a solution in which I add a target to my UISlider that will only start once when the user stops moving the slider.

I wanted to keep the value selected once, and not every update, so I deseleceted continous with NO . I just realized that a constant NO will not animate the slider. Therefore, after some attempts, I found out that UISlider will be animated if you use self.slider setValue:animated: in combination with [UIView animateWithDuration:animations:] as follows:

Add target

 [self.sliderSkill addTarget:self action:@selector(skillChange) forControlEvents:UIControlEventValueChanged]; 

Target method

 - (void)skillChange{ CGFloat fValue = self.sliderSkill.value; [UIView animateWithDuration:0.5f animations:^{ if( fValue < 1.5f ){ [self.slider setValue:1 animated:YES]; } else if( fValue > 1.5f && fValue < 2.5f ){ [self.slider setValue:2 animated:YES]; } else { [self.slider setValue:3 animated:YES]; } }]; } 

Maybe someone can use this!

+3
source

Source: https://habr.com/ru/post/953860/


All Articles