I try to create a UITexView with auto scrolling when press button start. And have a button stop, when pressed it will stop scrolling. Pressing button start again and it will continues to scroll down. How to handle this function.
I have research some code that this code below work with me.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"%f %f",_txvSentence.contentSize.width , _txvSentence.contentSize.height);
if (scrollingTimer == nil) {
scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:(35.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
NSLog(#"%#",scrollingTimer);
}
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
CGPoint scrollPoint = self.txvSentence.contentOffset;
//scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1);
scrollPoint = _txvSentence.contentOffset;
scrollPoint.y= scrollPoint.y+1;
[_txvSentence setContentOffset:scrollPoint animated:NO];
//[self.txvSentence setContentOffset:scrollPoint animated:NO];
}
But i cannot stop this animation. And how to set dynamic duration such as when come to the end of text it automatically stop.
Sorry because my bad english. If not understand please tell me where I will explain it clearly.
Try this:
self.scrollView.scrollEnabled = NO;
CGFloat scrollHeight = 100;
//===
- (void) spinWithOptions: (UIViewAnimationOptions) options {
// this spin completes 360 degrees every 2 seconds
[UIView animateWithDuration:10
delay:0
options:options
animations:^{
self.scrollView.contentOffset = CGPointMake(0, scrollHeight);
}
completion:^(BOOL finished) {
if (finished) {
if (animating) {
// if flag still set, keep spinning with constant speed
[self spinWithOptions: UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction];
} else if (options != UIViewAnimationOptionCurveEaseOut) {
// one last spin, with deceleration
[self spinWithOptions: UIViewAnimationOptionCurveEaseOut];
}
}
}];
}
- (void) startAnimating {
if (!animating) {
animating = YES;
[self spinWithOptions: UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction];
}
}
- (void) stopAnimating {
// set the flag to stop spinning after one last 90 degree increment
animating = NO;
}
You can use NSTimer.
// Global var
CGFloat scrollHeight = MAX_HEIGHT;
CGFloat currentOffsetY = 0.0f;
NSTimer *timer;
self.timer = [NSTimer scheduledTimerWithTimeInterval:YOUR_TIME_INTERVAL target:self selector:#selector(scrollText:) userInfo:nil repeats:YES];
- (void)scrollText:(NSTimer *)timer {
currentOffsetY++;
if (currentOffsetY >= MAX_HEIGHT) {
[self.timer invalide];
}
self.scrollView.contentOffset = CGPointMake(0, currentOffsetY);
}
// Your button action
- (void)stopAnimation:(UIButton *)button {
[self.timer invalide];
}
Related
So basically I have two methods that I run when the user clicks an Annotation in the map.
- (void) methodA{
[UIView animateWithDuration:kRequestButtonAnimationDuration animations:^(void){
self.button.transform = CGAffineTransformMakeTranslation(0,-(self.navigationController.view.frame.size.height - self.button.frame.origin.y)); }]; }
- (void) methodB:(double)value andBoolean:(BOOL) boolean{
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
if (boolean) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:value target:self selector:#selector(pullButtonUp) userInfo:nil repeats:NO];
} else{
self.timer = [NSTimer scheduledTimerWithTimeInterval:value target:self selector:#selector(showTabBar) userInfo:nil repeats:NO];
}}
-(void)pullButtonUp{
[(LLTabBarViewController*)self.tabBarController showTabBarAnimated];}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
[self methodA];
[self methodB:2.0 andBoolean:TRUE];
}
So during the first time I select an annotation, it works well: it runs methodA, then methodB after 2.0 seconds.
But when I try it again, it runs both A and B at the same time (basically methodA waits 2.0 seconds to execute).
Could this be related to Loops?
How should I track this problem? Any instrument? Which one?
I am a bit lost, help me please!
I think this is what you want to do
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
__weak typeof(self) weakSelf = self;
BOOL arbitraryBool = YES;
[UIView animateWithDuration:2
animations:^{
self.button.transform = CGAffineTransformMakeTranslation(0,-(self.navigationController.view.frame.size.height - self.button.frame.origin.y));
} completion:^(BOOL finished) {
if (finished) {
if (arbitraryBool) {
[weakSelf pullButtonUp];
} else {
[weakSelf showTabBar];
}
}
}]:
}
I am trying to get a button to move to random locations inside my view. However, the dot only moves at random when it is pressed. I also want it to fade to a different location if it is not pressed. I used CGRect because I need the dot to stay within the bounds of a specific view.
-(IBAction)randomRed:(id)sender
{
[self redDot];
CGRect senderFrame = [sender frame];
CGRect superBounds = [[sender superview ] bounds];
senderFrame.origin.x = (superBounds.size.width - senderFrame.size.width) * drand48();
senderFrame.origin.y = (superBounds.size.height - senderFrame.size.height) * drand48();
[sender setFrame:senderFrame];
counter = counter - 5;
scoreLabel.text = [NSString stringWithFormat:#"Points %i", counter];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Tapadot Red Dot Buzzer Short" ofType:#"mp3"];
sound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
sound.numberOfLoops = 1;
[sound play];
[self subtractOne];
[self performSelector:#selector(showRedDot) withObject:nil afterDelay:1.0];
}
-(void)startRedDot
{
if (counter ==0)
redDot = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(showRedDot)
userInfo:nil
repeats:YES];
}
-(void)showRedDot
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[redButton setAlpha:1];
[UIView commitAnimations];
[self performSelector:#selector(redDot) withObject:nil afterDelay:1.0];
}
-(void)redDot
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[redButton setAlpha:0];
[UIView commitAnimations];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setUpGame];
[self sizing];
}
Currently your random positioning code is only called when the button is pressed.
To get it to move Independent of button presses we should put it in its own method, which can invoke itself after a set duration.
First we need to get a reference to the instance of the button you want to move so we can manipulate it.
Then lets separate the movement code into its own method.
- (void) moveButtonRandomly {
CGSize limits;
CGPoint newPosition;
// Get limits
limits.width = self.view.frame.size.width - button.frame.size.width;
limits.height = self.view.frame.size.height - button.frame.size.height;
// Calculate new Position
newPosition = (CGPoint){ limits.width * drand48(), limits.height * drand48() };
// Set new frame
button.frame = (CGRect){ newPosition, button.frame.size };
}
Change your startRedDot to this, which will construct, and start the timer.
- (void) startRedDot {
redDotTimer = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(moveButtonRandomly)
userInfo:nil
repeats:YES];
[redDotTimer fire];
}
The animation is rather simple to add just create a new method which invokes two animations; One which fades out the button with a completion that moves the button, and fires off the next animation to fade it back in.
- (void) moveButtonWithAnimation {
CGFloat fadeDurration;
if ( !button )
return; // only invoke the button if it exists
fadeDurration = 0.4;
//Fade Out
[UIView animateWithDuration: fadeDurration animations:^{
button.alpha = 0.0f;
} completion:^(BOOL finished) {
// Move the button while it is not visible
[self moveButtonRandomly];
// Fade in
[UIView animateWithDuration: fadeDurration animations:^{
button.alpha = 1.0f;
}];
}];
}
Finally Edit the timers selector to be the animation method.
- (void) startRedDot {
redDotTimer = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(moveButtonWithAnimation)
userInfo:nil
repeats:YES];
[redDotTimer fire];
}
I am using NSTimer to move through my UIScrollview, but I can't get to make it stop at every page for like let's say a second or two so users can be able to preview and click if they want to or when they are scrolling around the images in the UIScrollview my Code is below....:
-(void) onTimer {
CGPoint rightOffset = CGPointMake(responseScroll.contentSize.width - responseScroll.bounds.size.width, 0);
[responseScroll setContentOffset:rightOffset animated:YES];
}
-(void)viewDidLoad {
/-------/
[NSTimer scheduledTimerWithTimeInterval:0.008 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
}
Make the timer interval 2.0:
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
This means that the timer will fire every 2 seconds.
If you want to shift one page over, you need to adjust your onTimer method:
CGPoint rightOffset = CGPointMake(responseScroll.contentOffset.x + responseScroll.frame.size.width, 0);
[responseScroll setContentOffset:rightOffset animated:YES];
Consider using UIAnimations instead
-(void)viewDidLoad{
[self moveScrollView];
}
-(void)moveScrollView{
CGPoint rightOffset = CGPointMake(responseScroll.contentOffset.x+responseScroll.bounds.size.width, 0);
if(rightOffset.x+responseScroll.bounds.size.width<=responseScroll.contentSize.width){
[UIView animateWithDuration:1 animations:^{
[responseScroll setContentOffset:rightOffset animated:NO];
} completion:^(BOOL finished) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self moveScrollView];
});
}];
}
}
Here is my answer, this is in swift. This will scroll the pages in scrollview infinitely.
private func startBannerSlideShow()
{
UIView.animate(withDuration: 6, delay: 0.1, options: .allowUserInteraction, animations: {
scrollviewOutlt.contentOffset.x = (scrollviewOutlt.contentOffset.x == scrollviewOutlt.bounds.width*2) ? 0 : scrollviewOutlt.contentOffset.x+scrollviewOutlt.bounds.width
}, completion: { (status) in
self.startBannerSlideShow()
})
}
I am using NSTimer and circular progress bar for the countdown timer i.e 15seconds
Its working with the following code but I am getting tick animation for the progress bar and not the smooth one, how to make it smooth animation
- (void)viewDidLoad
{
[super viewDidLoad];
self.labeledLargeProgressView.roundedCorners = NO;
self.labeledLargeProgressView.trackTintColor =[UIColor colorWithRed:0.0f/255.0f green:173.0f/255.0f blue:255.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.progressTintColor =[UIColor colorWithRed:255.0f/255.0f green:96.0f/255.0f blue:88.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.thicknessRatio = 1.0f;
self.labeledLargeProgressView.clockwiseProgress = YES;
[self.view addSubview:self.labeledLargeProgressView];
seconds = 15.0;
[self startAnimation];
}
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
}
else{
progress=labeledProgressView.progress + 0.06666667f;
[labeledProgressView setProgress:progress animated:YES];
seconds --;
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
- (void)stopAnimation
{
[self.timer invalidate];
self.timer = nil;
self.continuousSwitch.on = NO;
}
What i found out is a set of both UIview animations and progress view animatons that work much nicer and animate the progressview smoothly. If you just use the combination of animation and progressview animation it is fired directly without regard to the UIview animation timer.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0f
target: self
selector: #selector(updateTimer)
userInfo: nil
repeats: YES];
}
- (void)updateTimer
{
if (progressView.progress >= 1.0) {
[timer invalidate];
}
[UIView animateWithDuration:1 animations:^{
float newProgress = [self.progressView progress] + 0.125;
[self.progressView setProgress:newProgress animated:YES];
}];
}
Feel free to adjust the animation times to even better and smooth transitions
I solved it by myself what I did is I am updating more frequently 0.1f instead of 1.0f
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
_counter = 0;
}
else{
progress=labeledProgressView.progress + 0.00666667f;
_counter ++;
[labeledProgressView setProgress:progress animated:YES];
if(_counter % 10 == 0){
seconds --;
}
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
I have a simple explosion animation that works just fine in any method in my class. However I want to call it once the timer runs out, from the timer update method. The problem is it will not work from here for whatever reason (something to do with the timer surely). It simply unhides my image.. no animation. I cannot figure out how to get it to work.
- (void)explosionAnimation
{
imgExplosion.hidden=FALSE;
//set starting point of explosion
CGRect explosionFrame = self.imgExplosion.frame;
explosionFrame.origin.x = explosionFrame.origin.y = -960.0f;
explosionFrame.size.width = explosionFrame.size.height = 1920.0f;
[UIView animateWithDuration:1.5f animations:^{
self.imgExplosion.frame = explosionFrame;
} completion:^(BOOL finished) {
self.imgExplosion.hidden = YES;
}];
}
-(void) createTimer
{
// Create timer instance
if (timer != nil){
[timer invalidate];
hasTimerStarted = NO;
}
// Initialize the timer.
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerUpdater)
userInfo:nil repeats:YES];
}
- (void)timerUpdater{
if(!hasTimerStarted){
intTotalSeconds = [strTotalNumberofSeconds intValue];
hasTimerStarted = YES;
}
else{
intTotalSeconds--;
self.lblTimer.text = [self revertTimeToString:intTotalSeconds];
}
// if totalSeconds hits zero, then time is up! You lose!
if (intTotalSeconds == 0){
[timer invalidate];
[self explosionAnimation];
hasTimerStarted = NO;
[self addPlayAgainButton];
}
}
Try putting some delay or call explosion method on Main Thread like
[self performSelector:#Selector(explosionAnimation) withObject:nil afterDelay:1.0];