I have a subview named courseOptionsView that I want to show and hide with buttons and under certain conditions. When I use a swipe gesture the view works and is positioned correctly, but when I make the exact same call to the function with another button it repositions it, but it repositions it to the original position it was in instead of the coordinates I'm sending. :/ I'm stumped.
*edit
It seems that when I ++ or -- from cHNumber it resets subview. Any ideas?
IBOutlet UIView *courseOptionsView;
- (IBAction)nextHole:(id)sender;
- (IBAction)showCourseOptionsView:(id)sender;
- (IBAction)hideCourseOptionsView:(id)sender;
//show and hide functions
-(void) showCourseOptions{
if(activeRound){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:1.0];
[courseOptionsView setFrame:CGRectMake(50, 44, 200, 455)];
}
}
-(void) hideCourseOptions{
if(activeRound){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:1.0];
[courseOptionsView setFrame:CGRectMake(-200, 44, 200, 455)];
}
}
// swipe calls
- (IBAction)showCourseOptionsView:(id)sender {
[self showCourseOptions];
}
- (IBAction)hideCourseOptionsView:(id)sender {
[self hideCourseOptions];
}
//button call
- (IBAction)nextHole:(id)sender
{
int totalStrokes = 0;
int totalPlusMinus = 0;
//[courseOptionsView setFrame:CGRectMake(0, 44, 200, 455)];
//[self showCourseOptions];
//save current hole
if(cHStrokes != [[currentRound objectForKey:[NSString stringWithFormat:#"hole%i",cHNumber]] intValue] ||
cHPutts != [[currentRound objectForKey:[NSString stringWithFormat:#"hole%i_putts",cHNumber]] intValue]){
[self saveCurrentHole];
}
// calculate and display +/- and strokes
for (int i = 0; i < ([currentRound count]/2); i++){
totalStrokes += [[currentRound objectForKey:[NSString stringWithFormat:#"hole%i",i+1]] intValue];
totalPlusMinus += [[[selectedScoreCardData objectAtIndex:0] objectForKey:[NSString stringWithFormat:#"hole%i_par",i+1]] intValue];
}
totalPlusMinus = totalStrokes - totalPlusMinus;
self.totalStrokesLabel.text = [NSString stringWithFormat:#"%i", totalStrokes];
self.totalPlusMinusLabel.text = [NSString stringWithFormat:#"%i",totalPlusMinus];
//set to next hole
/*-------------------
| SHOW VIEW HERE
--------------------*/
if(cHNumber == 17){
self.nextHoleButton.enabled = NO;
[self showCourseOptions];
}
if(cHNumber == 1){
self.prevHoleButton.enabled = YES;
}
cHNumber ++;
self.cHNumberLabel.text = [NSString stringWithFormat:#"%i", cHNumber];
[self populateScoreCard];
[strokePickerView reloadAllComponents];
if(([currentRound count]/2) < cHNumber){
[strokePickerView selectRow:cHStrokes - 1 inComponent:0 animated:YES];
[strokePickerView selectRow:0 inComponent:1 animated:YES];
}else{
[strokePickerView selectRow:[[currentRound objectForKey:[NSString stringWithFormat:#"hole%i",cHNumber]] intValue] - 1 inComponent:0 animated:YES];
[strokePickerView selectRow:[[currentRound objectForKey:[NSString stringWithFormat:#"hole%i_putts",cHNumber]] intValue] inComponent:1 animated:YES];
}
}
I think that maybe after you position the view you are calling another function that changes the layout again. A possible candidate is populateScoreCard.
Related
Can someone tell me why this code isn't removing the subview that's being animated? The views are stacking up and the second time I dismiss the view, it won't animate and there are now two instances of subView with tag 99. It wasn't released the first time.
for (UIView *subview in [self.smallView subviews]) {
NSLog(#"view:%#",subview);
if (subview.tag == 99) {
[UIView animateWithDuration:.5
animations:^{
subview.alpha = 0;
}
completion:^(BOOL finished){
subview.alpha = 0;
[subview removeFromSuperview];
}];
}
}
Here's how I add the subview, viewVC is a ViewController Subclass and smallView is where I add my map and is the container for all the views.
#property (nonatomic, retain) CustomViewController *viewVC;
viewVC = [self.storyboard instantiateViewControllerWithIdentifier:#"VIEWVC"];
viewVC.view.frame = CGRectMake(20, 20, 280, 371);
viewVC.view.layer.cornerRadius = 15;
viewVC.view.tag = 99;
viewVC.view.alpha = 0;
[self.smallView addSubview:viewVC.view];
[UIView animateWithDuration:.5
animations:^{
viewVC.view.alpha = 1;
}
completion:^(BOOL finished){
viewVC.view.alpha = 1;
}];
I think the problem might be that you're removing an object from the array you're iterating through, which will cause problems. Try this:
NSArray *subviews = [NSArray arrayWithArray:[self.smallView subviews]];
for (UIView *subview in subviews) {
NSLog(#"view:%#",subview);
if (subview.tag == 99) {
[UIView animateWithDuration:.5
animations:^{
subview.alpha = 0;
}
completion:^(BOOL finished){
subview.alpha = 0;
[subview removeFromSuperview];
}];
}
}
This way, you are no longer removing an object from the array you are iterating through.
Could you please clarify why you are checking for the value of subview.tag to be 99? Is it at all possible that the code in the if statement isn't getting called at all? Throw in some NSLog calls, and see if your code within that if statement is even executing. If it is, then you should check out the methods that you are invoking within the if statement and make sure that they are all okay.
I have the following animation block:
[UIView animateWithDuration:3.0 animations:^{
NSLog(#"INDEX %d", index);
[self.visibleViewControllers_ enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
UIViewController *viewController = (UIViewController *)obj;
if (viewController.view.tag != index){
if (viewController.view.tag < index){
NSLog(#"LOWER VIEW WITH TAG %d", viewController.view.tag);
[viewController.view setFrameY:self.contentOffset.y - viewController.view.frameHeight];
} else if (viewController.view.tag > index){
NSLog(#"UPPER VIEW WITH TAG %d", viewController.view.tag);
[viewController.view setFrameY:600];
} else {
[viewController.view setFrame:CGRectMake(0, self.contentOffset.y, selectedView.frameWidth, 460)];
}
}
}];
//[selectedView setFrame:CGRectMake(0, self.contentOffset.y, selectedView.frameWidth, 460)];
}completion:^(BOOL finished){
[self.visibleViewControllers_ enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
UIViewController *viewController = (UIViewController *)obj;
NSLog(#"VIEW CONTROLLER Y IS %f AT INDEX %d", viewController.view.frameY, viewController.view.tag);
}];
}];
Basically it's a dictionary of view controllers that it's view I want to animate, but what's weird is that it only performs one animation. Not all. Why is this? Is it possible to do enumeration inside an animation block?
enumerate your views and animate them in your enumeration
[self.visibleViewControllers_ enumerateKeysAndObjectsUsingBlock:^
[UIView animation.....
you did one animation and enumerate all view in this animation. just turn it around
Have you tried something like this:
- (void) startAnimationLoop {
keyIndex = 0;
keysToLoopThrough = [self.visibleViewControllers_ allKeys];
[self animate];
}
- (void) animate {
UIViewController *viewController = [self.visibleViewControllers_ objectForKey:[keysToLoopThrough objectAtIndex:keyIndex]];
[UIView animateWithDuration:3.0 animations:^{
if (viewController.view.tag != index){
if (viewController.view.tag < index){
NSLog(#"LOWER VIEW WITH TAG %d", viewController.view.tag);
[viewController.view setFrameY:self.contentOffset.y - viewController.view.frameHeight];
} else if (viewController.view.tag > index){
NSLog(#"UPPER VIEW WITH TAG %d", viewController.view.tag);
[viewController.view setFrameY:600];
} else {
[viewController.view setFrame:CGRectMake(0, self.contentOffset.y, selectedView.frameWidth, 460)];
}
}
}completion:^(BOOL finished){
keyIndex++;
if (keyIndex < [keysToLoopThrough count])
[self animate];
else NSLog("Finished");
}];
}
Ha ii every body ,how can we implement a page-curl in tableview,i have a tableview which contains pages of the book and i have implement the touch events in the tableview cell for next chapter and previous chapter,left-swipe for next and right-swipe for previous chapter,when we swipe the tableview it reloads the next chapter and previous chapter content,it really works well but i want it in a page-curl animation,when the user swipe left or right tableview loads content with a page-curl animation.Is that possible to do in a tableview cell?my code for left and right swipe for chapter navigation as follows.
-(void) handleSwipeGesture:(UISwipeGestureRecognizer*)recognizer {
if(![delegate.selectedChapter isEqualToString:[NSString stringWithFormat:#"%d",[DbHandler mNumberOfChaptersInBook:delegate.selectedBook]]]) {
// if the currentChapter is the last then do nothing
delegate.selectedChapter = [NSString stringWithFormat:#"%d",[delegate.selectedChapter intValue] + 1];
[delegate reloadVerses];
[self resetReadViewToVerse:1];
[table removeGestureRecognizer:recognizer];
}
if (recognizer.state==UIGestureRecognizerStateBegan ) {
self.table.scrollEnabled = NO;
}
else if(recognizer.state==UIGestureRecognizerStateEnded) {
self.table.scrollEnabled = YES;
}
return;
}
-(void) handleSwipeGestureleft:(UISwipeGestureRecognizer*)recognizer {
if(![delegate.selectedChapter isEqualToString:#"1"])
{
delegate.selectedChapter = [NSString stringWithFormat:#"%d",[delegate.selectedChapter intValue] - 1];
[delegate reloadVerses];
[self resetReadViewToVerse:1];
[table removeGestureRecognizer:recognizer];
}
if (recognizer.state==UIGestureRecognizerStateBegan ) {
self.table.scrollEnabled = NO;
}
else if(recognizer.state==UIGestureRecognizerStateEnded) {
self.table.scrollEnabled = YES;
}
return;
}
Thanks in advance.
I got the answer.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationDelay:0.0];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDidStopSelector:#selector(animCompleteHandler:finished:context:)];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[UIView commitAnimations];
just put this code inside the methods.Thanks
I have 5 pictures inside an infinite scrollView.
So in order to make that scrollView infinite/circular I positioned my images like this:
5 1 2 3 4 5 1
meaning: last picture first picture second picture.....last picture first picture
And in order for it to become infinite I have the following code:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if(self.scrollView.contentOffset.x == 0){
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width*pathImages.count, 0, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
else if (self.scrollView.contentOffset.x == self.view.frame.size.width*(pathImages.count+1)) {
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
}
which means that when I'm at the last picture the contentOffset of the scrollView is set to go to the first picture-in this way I get an infinite scrollView.
What I wanted next was for my scrollView to slide automatically-for this I set a timer which calls one method-onTimer:
- (void) onTimer{
NSLog(#"flip pages");
if(h < pathImages.count*self.view.frame.size.width)
{
h+= self.view.frame.size.width;
}
else
{
h=self.view.frame.size.width;
}
if(self.scrollView.contentOffset.x == 0){
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width*pathImages.count, 0, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
else
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ self.scrollView.contentOffset = CGPointMake(h, 0); }
completion:NULL];
}
This magic line:
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ self.scrollView.contentOffset = CGPointMake(h, 0); }
completion:NULL];
does the scoll automatically with animation.
Everything is great except this:
after I view the last picture I should set the offset of scroll view in order to get back to the first picture with animation.
Well if I do that:
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ [self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO]; }
completion:NULL];
}
after the last picture is viewed in order to get to the first picture...it loops through all the other pictures.
What I want is this:after I view the last picture to get me back to the first picture which should be loaded on screen using animation, but without viewing all the other pictures between them.Thanks
If I see this correctly, the problem is, that you again use the animation to scroll the view back to zero position. I believe you need to modify the last bit of code you posted to something like this:
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];//no animation on returning
[self onTimer];//even if this code is already inside method "onTimer"
}
Rather then what you are doing try using a scrollview that displays only 3 to 5 images at the time (if they are fullscreen). If you will have many images in your application, it will crash because of high memory consumption. Try playing with this test example that does nearly what you want:
HEADER:
#import <Foundation/Foundation.h>
#interface IScrollView : UIScrollView <UIScrollViewDelegate> {
NSMutableArray *imagePaths;
UIImageView *imageViews[3];
NSInteger currentImage;
NSTimer *animationTimer;//weak link
}
#end
SOURCE:
#import "IScrollView.h"
#implementation IScrollView
- (UIImage *)imageFromResourcesWithName:(NSString *)name {
UIImage *ret = [[UIImage alloc] initWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:name]];
return [ret autorelease];
}
- (id)initWithFrame:(CGRect)frame {
if((self = [super initWithFrame:frame])) {
imagePaths = [[NSMutableArray alloc] init];
[imagePaths addObject:#"imag1.png"];
[imagePaths addObject:#"imag2.png"];
[imagePaths addObject:#"imag3.png"];
[imagePaths addObject:#"imag4.png"];
[imagePaths addObject:#"imag5.png"];
imageViews[0] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*0, .0f, 320.0f, 480.0f)];
imageViews[1] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*1, .0f, 320.0f, 480.0f)];
imageViews[2] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*2, .0f, 320.0f, 480.0f)];
[self addSubview:imageViews[0]];
[self addSubview:imageViews[1]];
[self addSubview:imageViews[2]];
imageViews[0].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:0]];
imageViews[1].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:1]];
imageViews[2].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:2]];
currentImage = 1;
self.contentOffset = CGPointMake(320.0f*currentImage, .0f);
self.contentSize = CGSizeMake(3.0f*320.0f, 480.0f);
self.delegate = self;
animationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:#selector(scrollFragment) userInfo:nil repeats:YES];
}
return self;
}
- (void)repositionIfNeeded {
CGFloat offsetX = self.contentOffset.x;
NSInteger iCount = [imagePaths count];
if(offsetX > 320.0f*1.75f) {
self.contentOffset = CGPointMake(offsetX-320.0f, .0f);
imageViews[0].image = imageViews[1].image;
imageViews[1].image = imageViews[2].image;
NSInteger imageToLoad = currentImage+2;
if(imageToLoad>iCount-1)
imageToLoad -= iCount;
imageViews[2].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:imageToLoad]];
currentImage++;
if(currentImage>iCount-1)
currentImage -= iCount;
}
else if(offsetX < 320.0f*.25f) {
self.contentOffset = CGPointMake(offsetX+320.0f, .0f);
imageViews[2].image = imageViews[1].image;
imageViews[1].image = imageViews[0].image;
NSInteger imageToLoad = currentImage-2;
if(imageToLoad<0)
imageToLoad += iCount;
imageViews[0].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:imageToLoad]];
currentImage--;
if(currentImage<0)
currentImage += iCount;
}
}
- (void)scrollFragment {
self.contentOffset = CGPointMake(self.contentOffset.x+1.0, .0f);
[self repositionIfNeeded];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self repositionIfNeeded];
}
- (void)dealloc {
[imageViews[0] release];
[imageViews[1] release];
[imageViews[2] release];
[imagePaths release];
}
#end
Ha ii everybody,i am familiar with pullDownToRefresh in tableview but in want pulluptorefresh in my application like the pocket-sword bible application chapter loading pull-up for next-chapter and pulldown for previous chapter,i done the ordinary pulldown method,but i want pull-up,i tried to customize the existing pulldown code but no luck,i tried more than 4 days for this. i want to implement pull-up below the footer just like the pulldown just-above the header.
anyone have any idea about this please help me.
Kind regards Nipin.
- (void)addPullToRefreshHeader {
refreshHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0 - REFRESH_HEADER_HEIGHT, 320, REFRESH_HEADER_HEIGHT)];
refreshHeaderView.backgroundColor = [UIColor clearColor];
refreshLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, REFRESH_HEADER_HEIGHT)];
refreshLabel.backgroundColor = [UIColor lightGrayColor];
refreshLabel.font = [UIFont boldSystemFontOfSize:16.0];
refreshLabel.textColor = [UIColor whiteColor];
refreshLabel.textAlignment = UITextAlignmentCenter;
refreshArrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrow.png"]];
refreshArrow.frame = CGRectMake((REFRESH_HEADER_HEIGHT - 27) / 2,
(REFRESH_HEADER_HEIGHT - 44) / 2,
27, 44);
refreshSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
refreshSpinner.frame = CGRectMake((REFRESH_HEADER_HEIGHT - 20) / 2, (REFRESH_HEADER_HEIGHT - 20) / 2, 20, 20);
refreshSpinner.hidesWhenStopped = YES;
[refreshHeaderView addSubview:refreshLabel];
[refreshHeaderView addSubview:refreshArrow];
[refreshHeaderView addSubview:refreshSpinner];
[self.table addSubview:refreshHeaderView];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if (isLoading) return;
isDragging = YES;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (isLoading) {
// Update the content inset, good for section headers
if (scrollView.contentOffset.y > 0)
self.table.contentInset = UIEdgeInsetsZero;
else if (scrollView.contentOffset.y >= -REFRESH_HEADER_HEIGHT)
self.table.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (isDragging && scrollView.contentOffset.y < 0) {
// Update the arrow direction and label
[UIView beginAnimations:nil context:NULL];
if (scrollView.contentOffset.y < -REFRESH_HEADER_HEIGHT) {
// User is scrolling above the header
refreshLabel.text = #"Release to previous chapter...";
[refreshArrow layer].transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
} else { // User is scrolling somewhere within the header
refreshLabel.text = #"Pull down to previous chapter..";
[refreshArrow layer].transform = CATransform3DMakeRotation(M_PI * 2, 0, 0, 1);
}
[UIView commitAnimations];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (isLoading) return;
isDragging = NO;
if (scrollView.contentOffset.y <= -REFRESH_HEADER_HEIGHT) {
// Released above the header
[self startLoading];
}
}
- (void)startLoading {
isLoading = YES;
delegate.selectedChapter = [NSString stringWithFormat:#"%d",[delegate.selectedChapter intValue] + 1];
[delegate reloadVerses];
[self resetReadViewToVerse:1];
// Show the header
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
self.table.contentInset = UIEdgeInsetsMake(REFRESH_HEADER_HEIGHT, 0, 0, 0);
refreshLabel.text = #"Loading...";
refreshArrow.hidden = YES;
[refreshSpinner startAnimating];
[UIView commitAnimations];
// Refresh action!
[self refresh];
}
- (void)stopLoading {
isLoading = NO;
// Hide the header
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDidStopSelector:#selector(stopLoadingComplete:finished:context:)];
self.table.contentInset = UIEdgeInsetsZero;
[refreshArrow layer].transform = CATransform3DMakeRotation(M_PI * 2, 0, 0, 1);
[UIView commitAnimations];
}
- (void)stopLoadingComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
// Reset the header
refreshLabel.text =#"Pull down to previous chapter..";
refreshArrow.hidden = NO;
[refreshSpinner stopAnimating];
}
- (void)refresh {
// This is just a demo. Override this method with your custom reload action.
// Don't forget to call stopLoading at the end.
[self performSelector:#selector(stopLoading) withObject:nil afterDelay:2.0];
}
I dont know exactly about your task. But try out following code which identifies the scrollPosition of UITableView :
NSIndexPath* ipath = [NSIndexPath indexPathForRow: cells_count-1 inSection: sections_count-1];
[tableView scrollToRowAtIndexPath: ipath atScrollPosition: UITableViewScrollPositionTop animated: YES]
For more reference go to Link