I am calling turnView method who must get dissapear menuView (current) and may display adjustView. When method is called, it is executed with no errors but it does not switch views, menuView keeps and it returns to following line of method call. How to solve it? Thanks
call from menuView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
aboutTabController * myObject = [[aboutTabController alloc] init];
if (indexPath.section == 1) {
switch (indexPath.row) {
case 0:
[myObject turnView];
break;
case 1:
//
break;
default:
break;}
}
}
method implemented on controller, menuController was defined for menuView class:
- (void) turnView
{
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
if (self.adjustController == nil)
{
adjustView *aController = [[adjustView alloc] initWithNibName:#"adjustView" bundle:nil];
self.adjustController = aController;
[aController release];
}
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[self.menuController viewWillDisappear:YES];
[self.adjustController viewWillAppear:YES];
[self.menuController.view removeFromSuperview];
[self.view insertSubview:adjustController.view atIndex:0];
[self.menuController viewDidDisappear:YES];
[self.adjustController viewDidAppear:YES];
[UIView commitAnimations];
}
There are some major conceptual problems in your code, let me try to address them one by one:
Logic in didSelectRowAtIndexPath:
You are creating a new view controller no matter which row is being selected. You should only create it when you need it. Also you if and switch statements are very convoluted and difficult to read.
Calling delegate methods
The methods viewWillAppear: viewDidDisappear: etc. are there for you to catch these events, not to call them yourself. This might make sense in some cases, but they will have absolutely no effect in your animation block.
Animation with blocks, or using built-in animations
You should do your animation with the new block syntax. However, for just flipping to the next view, you can use an official API from Apple without having to program your own animation.
Thus,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section==1 && indexPath.row==0) {
adjustView *aController = [[adjustView alloc] initWithNibName:#"adjustView" bundle:nil];
aController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:aController animated:YES];
[aController release];
}
}
You can get rid of the controller by calling [self dismissModalViewControllerAnimated:YES] and the animation will automatically be in the other direction.
Related
I have one table view and one imageview, each one takes half of the screen.
I am trying to animate an image view when the user swipes on the imageview and when table cell is selected.
I use this code:
#interface X()
#property (strong, nonatomic) IBOutlet UIImageView *ImagePreview;
#property (strong, nonatomic) IBOutlet UITableView *table;
#end
#implementation X
- (void)handleGestureRight:(UISwipeGestureRecognizer *)sender {
[self ShowAnimation:_ImageGalaryPreview];
}
-(void)ShowAnimation:(UIImageView *)view{
[UIView beginAnimations: #"Slide Image" context: NULL];
[UIView setAnimationDuration: 1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:view cache:NO];
[UIView commitAnimations];
}
#end
It works perfect when I call it after the swipe but when I call it from UITableView class instance it does not work!
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self ShowAnimation:_ImageGalaryPreview];
}
Can anyone tell me why ?!
Use your calling method as given below,It will definitely work.
-(void)stuff
{
[UIView beginAnimations: #"Slide Image" context: NULL];
[UIView setAnimationDuration: 1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:Ù€ImagePreview cache:NO];
[UIView commitAnimations];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSelectorOnMainThread:#selector(stuff) withObject:nil waitUntilDone:NO];
}
you just need to pass the view of tableview in place of imageView....check it works.. Enjoy
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView beginAnimations: #"Slide Image" context: NULL];
[UIView setAnimationDuration: 1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView: tableView cache:NO];
[UIView commitAnimations];
}
Nothing happens when the user taps a table row because none of the lines in the didSelectRowAtIndexPath method includes anything that is related to indexPath.row. Maybe, try something like the following.
#interface ViewController () {
NSInteger selectedrow;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *selectedIndexPath = [table indexPathForSelectedRow];
selectedrow = indexPath.row;
if (indexPath.row >= 0) {
[UIView beginAnimations: #"Slide Image" context: NULL];
[UIView setAnimationDuration: 1];
...
...
ImagePreview = ... [array objectAtIndex:selectedrow]...
}
}
- (void)viewDidLoad {
selectedrow = -1;
}
Still, I don't know how your code has anything to do with UIImageView.
thanks for your response also I solve it with this code
[self performSelectorOnMainThread:#selector(stuff) withObject:nil waitUntilDone:NO];
thanks to #Hercules :)
My first view contains a button and after pressing a button, i will end up with the second view. what I have done is
FirstViewController.m
- (void)pushToWishList {
SecondViewController *controller = [[SecondViewController alloc] initWithNibName:#"SecondView" bundle:nil ];
[UIView beginAnimations:#"flipping view" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self.view addSubview:controller.view];
[UIView commitAnimations];
}
SecondViewController is an UIViewController such that :
SecondViewController.h :
#interface SecondViewController :
UIViewController
SecondViewController.m
self.navigationController.navigationBarHidden = NO;
self.navigationItem.hidesBackButton = NO;
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
What is happening is the top navigation is disppearing and the UITableView in my second view can not be scrolled up and down. My program is crashed whenever I try to do this.
Please advice me on this issue. Any comments are welcomed here.
First off its easier to not addSubview: just use this code to turn your page:
- (IBAction)myCart:(id)sender; {
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
}
This will allow your tableView to scroll! Also, your method return type is void, if you are using a button to call this method, you need to change the return type to IBAction which works for buttons.
I'm working on an iPhone/iPad application and trying to switch views through a function call, not by a button. I've seen lots of sources switching views triggered by a button, but there's nothing that explains how to switch views triggered by a function. I tried to do this on my own, but it failed. Here's the code that I tried:
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.webview == nil) {
self.webview = [[MainViewController alloc] init];
/* webview initialized with storyboard */
if (self.view.superview == nil) {
[self.view insertSubview:self.webview.view atIndex:0];
}
[storyboard release];
}
}
This is viewDidLoad of the viewController.m. First, it shows WebView.
- (void)changeView {
self.normview = [[AlternateViewController alloc] init];
/* normview initialized with storyboard */
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[self.webview viewWillDisappear:YES];
[self.webview viewDidDisappear:YES];
[self.webview.view removeFromSuperview];
[self.view insertSubview:self.normview.view atIndex:0];
[self.normview viewWillAppear:YES];
[self.normview viewDidAppear:YES];
[UIView commitAnimations];
}
And when this changeView function (in a viewController.m) is called, It should change the view from webview to normview (actually, it works fine when the same code is triggered by a button). But when I call this function in other file (not viewController.m), such as
ViewController *viewcontroller = [[ViewController alloc] init];
[viewcontroller changeView];
It doesn't work. Anyone can give a clue to solve this or an alternative way? (ps. I'm testing on iPad.)
You can switch views with this function:
YourView *screen = [[YourView alloc] initWithNibName:nil bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:screen animated:YES];
[screen release];
You can set the modaltransitionstyle to your willings.
Don't forget to import your headerfile at the top of your class.
#import "YourView.h"
I am calling a method contained on a controller class that have to change views. It generates an error on insertsubview.view. How to solve it? Thank you
call from current menuViewController class:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
aboutTabController * myObject = [[aboutTabController alloc] init];
if (indexPath.section == 1) {
switch (indexPath.row) {
case 0:
[myObject turnIdioma];
break;
case 1:
//
break;
default:
break;}
}
}
//method implememented in controller class:
- (void) turnIdioma
{
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
if (self.controladorAjustes == nil)
{
settingsViewController *aController = [[settingsViewController alloc] initWithNibName:#"mailViewController" bundle:nil];
self.controladorAjustes = aController;
[aController release];
}
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[self.controladorMenu viewWillDisappear:YES];
[self.controladorAjustes viewWillAppear:YES];
[self.controladorMenu.view removeFromSuperview];
[self.view insertSubview:controladorAjustes.view atIndex:0];
[self.controladorMenu viewDidDisappear:YES];
[self.controladorAjustes viewDidAppear:YES];
[UIView commitAnimations];
}
You cannot insert a nil valued object as a subview. Typically the view controller will make sure it is created when you try to get its view property, using the appropriate method depending on whether it is a view defined by a NIB file or not.
IF you are doing something to explicitly set the view to nil then you are probably not taking the right approach. I suspect you are doing something fishy inside your call to:
[self.controladorAjustes viewWillAppear:YES];
I must be missing something fundamental here. I have a UITableView inside of a NavigationViewController. When a table row is selected in the UITableView (using tableView:didSelectRowAtIndexPath:) I call pushViewController to display a different view controller. The new view controller appears correctly, but when I pop that view controller and return the UITableView is resized as if the keyboard was being displayed. I need to find a way to have the keyboard hide before I push the view controller so that the frame is restored correctly. If I comment out the code to push the view controller then the keyboard hides correctly and the frame resizes correctly.
The code I use to show the keyboard is as follows:
- (void) keyboardDidShowNotification:(NSNotification *)inNotification {
NSLog(#"Keyboard Show");
if (keyboardVisible) return;
// We now resize the view accordingly to accomodate the keyboard being visible
keyboardVisible = YES;
CGRect bounds = [[[inNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
bounds = [self.view convertRect:bounds fromView:nil];
CGRect tableFrame = tableViewNewEntry.frame;
tableFrame.size.height -= bounds.size.height; // subtract the keyboard height
if (self.tabBarController != nil) {
tableFrame.size.height += 48; // add the tab bar height
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(shrinkDidEnd:finished:contextInfo:)];
tableViewNewEntry.frame = tableFrame;
[UIView commitAnimations];
}
The keyboard is hidden using:
- (void) keyboardWillHideNotification:(NSNotification *)inNotification {
if (!keyboardVisible) return;
NSLog(#"Keyboard Hide");
keyboardVisible = FALSE;
CGRect bounds = [[[inNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
bounds = [self.view convertRect:bounds fromView:nil];
CGRect tableFrame = tableViewNewEntry.frame;
tableFrame.size.height += bounds.size.height; // add the keyboard height
if (self.tabBarController != nil) {
tableFrame.size.height -= 48; // subtract the tab bar height
}
tableViewNewEntry.frame = tableFrame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(_shrinkDidEnd:finished:contextInfo:)];
tableViewNewEntry.frame = tableFrame;
[UIView commitAnimations];
[tableViewNewEntry scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionMiddle animated:YES];
NSLog(#"Keyboard Hide Finished");
}
I trigger the keyboard being hidden by resigning first responser for any control that is the first responder in ViewWillDisappear. I have added NSLog statements and see things happening in the log file as follows:
Show Keyboard
ViewWillDisappear: Hiding Keyboard
Hide Keyboard
Keyboard Hide Finished
PushViewController (an NSLog entry at the point I push the new view controller)
From this trace, I can see things happening in the right order, but It seems like when the view controller is pushed that the keyboard hide code does not execute properly.
Any ideas would be really appreciated. I have been banging my head against the keyboard for a while trying to find out what I am doing wrong.
-- Added didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case 0: // Required Info
// removed to simplify
case 1: // Optional Info
switch (indexPath.row) {
case 0:
[self showTextDetailPicker: #"Enter a description"
tag: tDescriptionPicker
sourceTarget: self.newRecord
fieldSource: #selector(description)];
break;
default:
break;
}
break;
default:
break;
}
}
- (void) showTextDetailPicker: (NSString*) titleText tag:(int)tagID sourceTarget:(NSObject*)target fieldSource:(SEL)selector{
FieldEditorViewController *fe = [[FieldEditorViewController alloc] init];
fe.titleText = titleText;
fe.fieldText = [target performSelector: selector];
fe.tag = tagID;
// Replace default back button with one that just says 'Back'
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc]
initWithTitle:#"Back"
style:UIButtonTypeInfoLight
target:nil action:nil];
[[self navigationItem] setBackBarButtonItem: newBackButton];
[newBackButton release];
[fe setDelegate: self];
[self.navigationController pushViewController:fe animated:YES];
[fe release];
}
Right before you push your view controller, find the first responder and call resign. Use the category from this SO post to see how to find the first responder recursively (not sure if you're already doing this).
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIView *fp = [[self view] findFirstResponder];
[fp resignFirstResponder];
// Push new view controller here.
NextViewController *controller = [[NextViewController alloc] init];
[[self navigationController] pushViewController:controller animated:YES];
[controller release], controller = nil;
}
The other thing to keep in mind is that your table view is getting resized automatically because your root view controller is derived from UITableViewController (or so it seems). If you make your root view controller a regular UIViewController that contains a UITableView, you can manipulate the frame of the table view manually more easily--at least that's been my experience.