Set Continuous Feedback and Duration For UISlider:setValue:animated

Discussion in 'iPhone/iPad Programming' started by Darkroom, Dec 3, 2009.

  1. Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #1
    i would like to slow down the setValue:animated animation duration from it's default (which i assume is 0.25f) to about 2 seconds. additionally, i need to have continuous feedback of the slider's value while it is animating. how can this be accomplished? i assume i'll have to write my own method to achieve this behavior, but i'm a bit fuzzy on the logic behind this.

    any guides or suggestions?

    [EDIT] i'm thinking this could be accomplished thru a loop, using setValue:animated:NO thru steps that multiply (speed up) in the loop until the value of the slider becomes the desired value. if anyone has any better ideas please let me know. my idea seems like a big hack.

    [EDIT AGAIN] yeah, that totally didn't work. it seems i had forgotten how fast for loops can execute. :rolleyes:
     
  2. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #2
    ok so i managed to control the animation curve and duration by simply throwing the setValue method of the slider in an animation block - should have been my first thought, really.

    Code:
    [UIView beginAnimations:@"returnSliderToInitialValue" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    [UIView setAnimationDuration:0.50];
    
    [mySlider setValue:0.0];
    
    [UIView commitAnimations];
    
    now all i have to do is figure out how to execute the UIControlEvenValueChanged for each step of the animation... i'm not sure this is even possible. any ideas or confirmation on the possibility of this?
     
  3. macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #3
    Have you tried using "performSelector:withObject:afterDelay:"?
     
  4. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #4
    the problem with the animation block is that the value of the slider is set immediately as the animation is only starting.

    i'm currently trying to work it out using setAnimationDidStopSelector: in the animation block, but i'm having coder's block right now.

    here is my current state of mind:
    Code:
    - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
    	{
    	if (([animationID isEqualToString:@"returnSliderToInitialValue"]) && finished)
    		NSLog(@"done");//send back to returnSliderToInitialValue until value is 0.0f;
    	}
    	
    - (IBAction)returnSliderToInitialValue:(UISlider *)sender
    	{
    	float initialValue = 0.0;
    	float releasedValue = roundf([sender value]);
    	float distanceFromInitialValue = (fabsf(initialValue - releasedValue));
    	NSLog(@"%f", distanceFromInitialValue);
    	
    	
    	[UIView beginAnimations:@"returnSliderToInitialValue" context:NULL];
    	[UIView setAnimationDelegate:self];
    	[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
    	[UIView setAnimationCurve:UIViewAnimationCurveLinear];
    	[UIView setAnimationDuration:2.0];
    
    	[pitchSlider setValue: distanceFromInitialValue - 0.5];
    	
    	[UIView commitAnimations];
    	} 
    
     
  5. macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #5
    Here's what I'm getting at:

    Suppose you have a film that you want to display. Your view is currently displaying the first frame of the film. You have a method called "showNextFrame". It could work kind of like this:

    Code:
    - (void)showNextFrame
    {
        NSInteger nextFrame = ([self currentFrame] + 1);
    
        [self setCurrentFrame: nextFrame];
    
    //  Update the currently displayed image with the next image.
    
    //  If the film has more frames, show the next after a delay.
    
        if ([self currentFrame] < [self lastFrame])
        {
            [self performSelector: @selector(showNextFrame) withObject: nil afterDelay: (1.0 / 24)];
        }
    }
    This should give you a way to make a "manual animation" and make whatever method calls you want in-between frames.
     
  6. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #6
    i just tried your suggestion. unfortunately the slider is quite slow moving back to it's original position, even if afterDelay is set to zero.
     
  7. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #7
    i'm going to submit a feature request / bug to apple about this. i think if a continuous UISlider's value can be set and animated then the animation should also be continuous.
     
  8. macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #8
    So you need to call a certain method every time your slider changes value? Kind of like how bindings work on the desktop?
     
  9. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #9
    yes. i'm creating a music app that has a pitch wheel (similar to those found on MIDI keyboards) that returns to it's original, center position when released. the value's output will be controlling an audio unit. currently, since the values don't animate with the slider's thumb while using setValue:animated:, the sound output will not be as fluid as it should be - unless i manage to find a way to do what i want, but that seems pretty unlikely.

    i do, however, see this as a non-issue if setValue:animated is used, since the default animation speed is so fast that the value output would hardly be noticed. however, setting the continuous slider's value in it's own slower animation block doesn't work either.

    i've submitted a bug report to apple.
     
  10. macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #10
    Have you tried creating a subclass of UISlider and overriding the "value" method? If you call "setValue:animated:" and the class calls "value" with each tick, that might do the job.
     
  11. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #11
    in case of an oversight i'd be nervous to do that without using the actual code as a guide. you don't happen to have that do you?

    or maybe i could just call [super setValue:value] from my custom method?
     
  12. macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #12
    Yea, I was thinking to try:

    Code:
    - (float)value
    {
        NSLog(@"Value Changed")
        
        float returnValue = [super value];
        
        return returnValue;
    }
    and see if your console logs with each value.
     
  13. thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #13
    i don't think that would work. the problem seems to be that the animation block (either the default one or one i've created myself) which animates the UISlider's thumb uses only one value. i think the only way to make this work is to have the slider post it's value during each step of the animation, which i think would require quite a complex animation block.
     

Share This Page