I have a button, which when is pressed, adds a new subview with other buttons on it. I have done like this.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget: #selector(newView)];
- (void)newView
{
UIView *newView = [[UIView alloc]initWithFrame:CGRectmake(0,0,100,100)];
[self.view addSubview:newView];
}
Now when the button is pressed the new view is just added. I want to animate the new view like I can do in the IB, with push segue modal style. How can I do that programmatically?
You can do that with performSegueWithIdentifier, here is the code
- (void)newView
{
//execute segue programmatically
[self performSegueWithIdentifier: #"MySegue" sender: self];
}
Try something like this.
- (void)newView
{
[self.view addSubview:newView]
newView.frame = // somewhere offscreen, in the direction you want it to appear from
[UIView animateWithDuration:10.0
animations:^{
newView.frame = // its final location
}];
}
You can present a new viewcontroller like this:
- (void)newView
{
//Embed your new View into a plain UIViewController
UIView *newView = [[UIView alloc]initWithFrame:CGRectmake(0,0,100,100)];
UIViewController *yourNewViewController= [[UIViewController alloc] init];
controller.view = newView;
//Present it animated
[self presentViewController:yourNewViewController animated:YES completion:nil];
}
Hope it helps! :)
Related
By "strange", I am noticing the following behavior:
background color set by the ChildViewController does not appear
despite adding a basic tap gesture recognizer to the ChildViewController, there is no tap recognition
adding a UIButton to the ChildViewController results in the UIButton shown, but there is no response when tapping on the UIButton part
In my ParentViewController, I present the ChildViewController very generically, like so:
UIViewController *viewController;
viewController = (ChildViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController"];
[self addChildViewController:viewController];
viewController.view.frame = self.view.bounds;
viewController.view.translatesAutoresizingMaskIntoConstraints = NO;
viewController.view.center = self.view.center;
[self.view addSubview:viewController.view];
[self.view bringSubviewToFront:viewController.view];
[viewController didMoveToParentViewController:self];
And here are some very basic things I do in ChildViewController's viewDidLoad:
self.view.backgroundColor = [UIColor yellowColor];
UIButton *tapButton = [UIButton buttonWithType:UIButtonTypeSystem];
[tapButton addTarget:self action:#selector(tappedOnTap) forControlEvents:UIControlEventTouchUpInside];
//button view customization code omitted for brevity
tapButton.userInteractionEnabled = YES;
tapButton.enabled = YES;
[self.view addSubview:tapButton];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tappedOnView)];
[self.view addGestureRecognizer:tapGesture];
[self.view setUserInteractionEnabled:YES];
[self.view addGestureRecognizer:tapGesture];
I ensured that everything is hooked up correctly - however, there is no acknowledgment in tappedOnView and tappedOnTap when I tap on it, in both simulator or device.
Am I missing something basic about presenting a ChildViewController?
Edit
For those curious, this very basic app is on Github.
The containment calls are fine. But if you use the view debugger (), you'll see the frame is not correct. This is because you've turned off translatesAutoresizingMaskIntoConstraints, but you don't have any constraints. You can either turn that back on (and set autoresizingMask accordingly):
viewController.view.translatesAutoresizingMaskIntoConstraints = true;
Or you can define constraints rather than setting the frame (and redundantly setting the center):
//viewController.view.frame = self.view.bounds;
viewController.view.translatesAutoresizingMaskIntoConstraints = false;
//viewController.view.center = self.view.center;
[self.view addSubview:viewController.view];
[NSLayoutConstraint activateConstraints:#[
[viewController.view.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[viewController.view.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[viewController.view.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[viewController.view.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor]
]];
Try this:
ChildViewController *viewController;
viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ChildViewController"];
viewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleheight;
[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self];
Usually you don't need to do anything when adding a ViewController to another except those basic methods. since the views will be adjusted automatically and you don't need to set all those properties like size and center etc...
I have added a UIView to my [UIApplication sharedApplication].keyWindow and it is working properly.
When a button on the UIView is tapped, I want to push a new UIViewController onto the underlying NavigationController
This all works, but how can I make the UIView animate off the screen, to the left, with the underlying UIViewController ?
You can animate your custom view and at the same time pass the control to the mail view controller to push the next view controller onto the navigation controller's stack... Below is the example code which I have simulated. The animation of your custom view should be in sync with the view controllers animation.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_v = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0, 0, 50, 30)];
[btn setTitle:#"Button" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[_v addSubview:btn];
_v.backgroundColor = [UIColor redColor];
[[[UIApplication sharedApplication] keyWindow] addSubview:_v];
}
- (void)btnClicked:(id)sender {
NSLog(#"Btn Clicked");
[UIView animateWithDuration:0.2
delay:0.1
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
_v.frame = CGRectMake(-_v.frame.size.width,
_v.frame.origin.y, _v.frame.size.width, _v.frame.size.height);
}
completion:^(BOOL finished)
{
}];
UIViewController *c = [self.storyboard instantiateViewControllerWithIdentifier:#"TestVC"];
[self.navigationController pushViewController:c animated:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
I create one UIScrollView with programmatically code and I have one button in my view (not exist in UIScrollView).
when I click on this button go to next page with modal transition. I create Cancel button in next page that when I click on it back to main page (this page have UIScrollView).
I want when click on Cancel button and return to main page call one method that is in main page and in this method change ContentOfSet my ScrollView... but not working!!!!
this is my code:
mainView.m
- (void)viewDidLoad{
UIScrollView *scrollbar = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,width, height)];
scrollbar.directionalLockEnabled = YES;
scrollbar.backgroundColor = [UIColor whiteColor];
scrollbar.maximumZoomScale = 1.0;
scrollbar.minimumZoomScale = 1.0;
scrollbar.clipsToBounds = YES;
scrollbar.showsHorizontalScrollIndicator = YES;
scrollbar.pagingEnabled = YES;
[scrollbar setContentSize:CGSizeMake(scrollbar.frame.size.width * 4,scrollbar.frame.size.height)];
scrollbar.contentOffset = CGPointMake(0, 0);
scrollbar.delegate = self;
[self.view addSubview:scrollbar];
[super viewDidLoad];
}
-(void)ChangeMainScrollContentOffset{
scrollbar.contentOffset = CGPointMake(scrollbar.frame.size.width * (3), 0);
}
this button is in root View :
- (IBAction)AddView:(id)sender{
AddStationController *add = [[AddStationController alloc]initWithNibName:#"AddStationController" bundle:nil];
[add setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self.view.window.rootViewController presentViewController:add animated:YES completion:nil];
}
this button is Cancel button for return in my mainView:
- (IBAction)BackView:(id)sender{
mainView *main = [[mainView alloc]init];
[main ChangeMainScrollContentOffset];
[self dismissViewControllerAnimated:YES completion:nil];
}
please guide me about that!!!
I so confused why not working ContentOffSet!!!
I think your problem is that you didn't add ChangeMainScrollContentOffset
method to your ViewController.h file.
Just add it in ViewController.h file and than call it.
You second viewController should have reference to previous view controller.
When you do this:
mainView *main = [[mainView alloc]init];
[main ChangeMainScrollContentOffset];
You create another instance of mainView which not on screen and change contentOffset on ANOTHER scrollView :)
You should add property delegate to your AddStationController
AddStationController.h
#property (nonatomic, weak) mainView* delegate;
mainView:
- (IBAction)AddView:(id)sender{
AddStationController *add = [[AddStationController alloc]initWithNibName:#"AddStationController" bundle:nil];
>> add.delegate = self; <<
[add setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self.view.window.rootViewController presentViewController:add animated:YES completion:nil];
}
Cancel button action
- (IBAction)BackView:(id)sender{
>> [self.delegate ChangeMainScrollContentOffset]; <<
[self dismissViewControllerAnimated:YES completion:nil];
}
I have one tableview in my viewcontroller and in that i have customTableViewCell.i have dynamic buttons which generated runtime in my customeview cell.and on that button's click i want to push my view controller which is holding my tableview controller with the customtableviewcell to another view controller so how can i do it ?
in my custometableviewcell.m file i have this button.
CommentButton = [[UIButton alloc]init];
CommentButton.frame = CGRectMake(CommentLabel.frame.origin.x+CommentLabel.frame.size.width+5, 5, 110, 35);
CommentButton.titleLabel.font = [UIFont systemFontOfSize:12];
[CommentButton setTitle:#"Add Comment" forState:UIControlStateNormal];
CommentButton.backgroundColor = [UIColor clearColor];
[CommentButton addTarget:self action:#selector(GoToComment:) forControlEvents:UIControlEventTouchUpInside];
folowing is my postnotification in customtableviewcell.m file which will called on comment button click
-(IBAction)GoToComment:(id)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"GoToComment" object:nil];
}
above is my button on this i have registered on NSNotification which is called the following method
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(GotoComents)
name:#"GoToComment" object:nil];
above line is in viewdidload of my viewcontroll in which i have tableview with that customtableviewcell.
and from customtableview cell i am posting the above notofication wich will push the new view controller
-(void)GotoComents
{
TableTextViewController *settingView=[[TableTextViewController alloc]initWithNibName:#"TableTextViewController" bundle:nil];
[self.navigationController pushViewController:settingView animated:YES];
}
right now i have just did it with the nsnotofication center which just call from my customTableViewcell and invoke the viewcontroller method.
but is it right way to do it?if its not then can anyone please help me how can i achieve this.?
remember that i have dynamic button which generated runtime.so please can any one guide me?
on click button event
-(void)buttonAction:(UIButton*)sender
{
YourViewControllerVC *yvc=[YourViewControllerVC alloc] init];
[self.yournavigatioonController pushViewController:yvc animated:YES];
}
You can declare your TableViewController subclass as custom cell delegate, create GoToComment method inside it, then, instead of
[CommentButton addTarget:self action:#selector(GoToComment:) forControlEvents:UIControlEventTouchUpInside];
do
[CommentButton addTarget:self.delegate action:#selector(GoToComment:) forControlEvents:UIControlEventTouchUpInside];
Add target-action for dynamically generated button:
[myButton addTarget:targetObject action:#selector(actionMethod) forControlEvents:UIControlEventTouchUpInside];
Then implement actionMethod for the targetObject and it will be called whenever button is touched. In this action method you need the following code:
UIViewController *viewController = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
you have not described your question correctly ..
you can do what you want this way:
LoginViewController * login_view = [[ LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
UINavigationController *Nav01 = [[UINavigationController alloc] initWithRootViewController:login_view];
Nav01.navigationBar.hidden = YES;
login_view.fromProfileView = FALSE;
[self presentModalViewController:Nav01 animated:YES];
I think what you need is
- (UIViewController *)viewController {
for (UIView* next = [self superview]; next; next = next.superview) {
UIResponder *nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)nextResponder;
}
}
return nil;
}
With above code, you can find your current view controller inside your custom cell.
You got to add your button in this way :
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchDown];
[view addSubview:button];
where aMethod is an IBAction returning method.
I have a rootViewController, in it's viewDidLoad method, I initialized another two ViewController2* object and their views as subview of rootViewController.view, then I set first ViewController2* controller.view.hidden = YES.
Then, on v1 has a button handler, when touch it, it present a UINavigationController, after that touch 'dismiss' button call dismissViewControllerAnimated on v1.
The question is: when dismiss complete, the two of ViewController2* fire viewWillAppear. How to make it only fire the viewWillAppear on the visible one, but not on the hidden one?
the rootViewController's implementation:
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.v1 = [[ViewController2 alloc] init];
self.v1.title = #"v1";
[self.view addSubview:self.v1.view];
self.v1.view.hidden = YES;
self.v2 = [[ViewController2 alloc] init];
self.v2.title = #"v2";
[self.view addSubview:self.v2.view];
UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:#"POP" forState:UIControlStateNormal];
[btn sizeToFit];
[btn addTarget:self action:#selector(touchHandler:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:btn];
}
- (void)touchHandler:(id)sender {
UINavigationController * nc= [[UINavigationController alloc] initWithRootViewController:[[UIViewController alloc] initWithNibName:nil bundle:nil]];
((UIViewController *)[nc.viewControllers objectAtIndex:0]).navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"dismiss" style:UIBarButtonItemStyleBordered target:self action:#selector(dismissHandler:)];
[self presentViewController:nc animated:YES completion:nil];
}
- (void) dismissHandler:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
ViewController2:
#implementation ViewController2
- (void)viewWillAppear:(BOOL)animated
{
NSLog(#"%#",self.title);
}
#end
viewWillAppear will fire on your UIViewController's, even if the view controllers view is set hidden=YES.
You can surely test if (self.view.hidden == YES) in your viewWillAppear delegate method if you want to prevent some expensive operation from occurring, but beware that if you later make that view un-hidden, that viewWillAppear won't fire then.
Simple, the reason why those methods are called is because the viewController's view is part of the main window's view hierarchy. This means that it has a superview that has a superview that has a superview and so on until that superview is the main window.
Instead of hiding and unhiding the viewController views, you should instead add and remove them from their superview. Also, to make sure that viewWillAppear and viewDidAppear are called correctly at the correct times, take a look at ViewController Containment:
http://www.cocoanetics.com/2012/04/containing-viewcontrollers/