I have a UIPageViewController that has a vertical orientation when it scrolls but it will not scroll to the top when the status bar is pressed. There are no other scroll views on the page if that helps.
Is there a scrolltotop function for a page view controller?
For easier implementation you can use this code in your childVC. This setting will make only visible ChildVC to be scrollsToTop-able.
- (void)viewDidLoad
{
self.collectionView.scrollsToTop =NO;
}
-(void)viewDidAppear:(BOOL)animated
{ self.collectionView.scrollsToTop =YES;
}
-(void)viewWillDisappear:(BOOL)animated
{
self.collectionView.scrollsToTop =NO;
}
UIPageViewController as far as I know does not have any scrollToTop ability. To provide such a feature, I add an observer to listen status bar touch events. I use your appcoda link as reference project, so if you insert codes into related files, it'll work perfectly.
// AppDelegate.m
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[[NSNotificationCenter defaultCenter] postNotificationName:#"touchStatusBarClick" object:nil];
}
// ViewController.m
- (void)viewDidLoad
{
// add this line at the bottom of the function
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarTouched) name:#"touchStatusBarClick" object:nil];
}
// This function is called when status bar is touched
-(void) statusBarTouched
{
PageContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
}
I hope it helps.
Related
I tried to programmatically popViewcontroller
By doing this
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[[self navigationController] popViewControllerAnimated:YES];
}
The problem is I have textFields in this VC.If the textField is active and keyboard is displaying, and if I display the AlertView with use to command to resign keyboard ( [[self view] endEditing:YES] or [textField resignFirstResponder] ). And then call the command popViewControllerAnimated:YES . The current VC is dismissed but briefly after the parent VC is appear. There will be a keyboard shown for like 1 second and then disappear.
This behaviour is very annoying. Are there anyway to solve this ? I noticed that by using [[self navigationController] popViewControllerAnimated:NO] The keyboard won't appear . But I prefer to have animation in my app.
Please help.
Thanks in advance
I solved this problem my making the [[self navigationController] popViewControllerAnimated:YES]; delayed when called.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
[[self navigationController] popViewControllerAnimated:YES];
});
#KongHantrakool 's answer works but also has a shortage, you can add [[self view] endEditing:YES] or [textField resignFirstResponder] in - (void)willPresentAlertView:(UIAlertView *)alertView ,it will be better.
You can also try this code:
#pragma mark - UIAlertView Delegate
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self performSelector:#selector(popViewController) withObject:nil afterDelay:0.1];
}
- (void)popViewController {
[self.navigationController popViewControllerAnimated:YES];
}
Try this i think its may help you
- (void)viewWillAppear:(BOOL)animated
{
[textField resignFirstResponder];
}
I encountered this problem too, and I found out that the delay solution does not work at all. alertView will remember the status of the keyboard, so when the alertView is dismissed, it will restore the keyboard. So the issue comes out: the keyboard appears about 1 second after we pop the viewController.
Here is my solution:
We just need to ensure the keyboard's status is hidden, before we pop the viewcontroller.
First we add a property and register the keyboard notifications to monitor the keyboard's status:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
#property (nonatomic) BOOL keyboardDidShow;
Implement the funs:keyboardDidHide: and keyboardDidShow:
- (void)keyboardDidHide:(NSNotification *)notification {
self.keyboardDidShow = NO;
if (self.needDoBack) {
self.needDoBack = NO;
[self showBackAlertView];
}
}
- (void)keyboardDidShow:(NSNotification *)notification {
self.keyboardDidShow = YES;
}
Do your pop:
- (void)back {
if (self.keyboardDidShow) {
self.needDoBack = YES;
[self.view endEditing:YES];
} else {
[self showBackAlertView];
}
}
I have a question, I want to build popup view like the UIAlertView,
I create two UIViewController in the storyboard(note: there are not segue),and Root UIViewController will load the UIViewController view popup.
I create two UIViewController to edit the UIView, because I want to use the storybaord to edit my complex UIView in the feature.
Then I put the container view on the RootViewController and there are two button in the container view.(my structure as below:)
When I click the pop up green button(with button name popupGreenBtn), It can correct addSubview on the UIWindow.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"ContainerViewController view didload");
appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
secondGreenVC = (SecondGreenViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"SecondGreenViewController"];
thirdRedVC = (ThirdRedViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"ThirdRedViewController"];
}
- (IBAction)popupGreenBtnAction:(id)sender {
[appDelegate.window addSubview: secondGreenVC.view];
[appDelegate.window bringSubviewToFront:secondGreenVC.view];
}
- (IBAction)popupRedBtnAction:(id)sender {
[appDelegate.window addSubview: thirdRedVC.view];
[appDelegate.window bringSubviewToFront:thirdRedVC.view];
}
When I click the button , it can correct popup on the window:
But now , When I click the SecondGreenViewController and ThirdRedViewcontroller background view(just transparent dark black), I want to close the popon the view(secondGreenVC.view or thirdRedVC.view).
I had try to add the code in the SecondGreenViewController class below:
#implementation SecondGreenViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction:)];
[_secondBaseView addGestureRecognizer:tap];
}
-(void) tapAction:(UITapGestureRecognizer*) recognizer
{
[self removeFromParentViewController];
// [self dismissViewControllerAnimated:NO completion:nil];
NSLog(#"tap in SecondGreenViewController");
}
#end
There are not effect to close the UIViewController.
How can I close the Popup window(the UIViewController) when I click the dark black part?
(If you want to more info, please tell me or you can see my this simple project from github https://github.com/dickfalaDeveloper/PopUpViewDemo )
Thank you very much.
-(void) tapAction:(UITapGestureRecognizer*) recognizer
{
thirdViewcontroller.hidden=YES;
}
I resolve the problem. But I don't know have any best answer.
My method is in the popupGreenBtnAction actin.
change the code to:
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
secondGreenVC.modalPresentationStyle = UIModalPresentationCustom;
[appDelegate.window.rootViewController presentViewController:secondGreenVC animated:NO completion:nil];
Then in the SecondGreenViewController storyboard,
Drag an other UIView do base UIView and set the UIView IBOutlet(now I name with"secondBaseView").
at SecondGreenViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction:)];
[self.secondBaseView addGestureRecognizer:tap];
}
-(void) tapAction:(UITapGestureRecognizer*) recognizer
{
[self dismissViewControllerAnimated:NO completion:nil];
}
That is Ok to show the modal and dismiss the modal UIViewController.
I have main viewcontroller that opens via popover segue other view controller with buttons.
On button click what I wish to happen is function from first viewcontroller fire and the popover will close. How do I do so properly?
On settings button click the popover open. Then when user click Manual Content Update the the view will close and start function on Projects Main viewController.
You can use NSNotificationCenter.
In your main UIViewController add:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receivePopoverNotification:)
name:#"PopoverNotification"
object:nil];
}
-(void) dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void) receivePopoverNotification:(NSNotification *) notification
{
[self.popover dismissPopoverAnimated: YES];
self.popover = nil;
}
In your UIPopoverController add:
-(IBAction) pressButton: (id) sender {
[[NSNotificationCenter defaultCenter]
postNotificationName:#"PopoverNotification"
object:nil];
}
I have a UIViewController then when I longpress to self.view it will push a popup (MenuViewController). But when I try to remove popup by removeFromSuperview it still appears
You can see more detail of my problem with this http://www.youtube.com/watch?v=nVVgmeJEnnY
ViewController.m
#import "MenuViewController.h"
#interface ViewController () {
MenuViewController *menu;
}
....
- (void)viewDidLoad
{
....
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(albumButtonPressed : ) name:#"albumButtonPressed" object:nil];
....
}
....
-(void)albumButtonPressed : (NSNotification*) notification {
UIImagePickerController *photoPicker = [[UIImagePickerController alloc] init];
photoPicker.delegate = self;
photoPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:photoPicker animated:YES];
}
...
-(void)handleLongPress:(UILongPressGestureRecognizer*)recognizer {
menu = [[MenuViewController alloc] initWithNibName:#"MenuViewController" bundle:nil];
if (self.imageView.image != nil) {
menu.imageAdded = YES;
}
[self.view addSubview:menu.view];
}
MenuViewController.m
-(IBAction)albumButtonPressed:(id)sender {
[self.view removeFromSuperview];
[[NSNotificationCenter defaultCenter] postNotificationName:#"albumButtonPressed" object:nil];
}
Setting aside my reservations about not applying proper view controller containment, the problem is that your handleLongPress will be called multiple times with different recognizer.state values, once as UIGestureRecognizerStateBegan and again as UIGestureRecognizerStateEnded. You should be checking the state of the gesture, e.g.:
-(void)handleLongPress:(UILongPressGestureRecognizer*)recognizer {
if (recognizer.state == UIGestureRecognizerStateEnded) {
menu = [[MenuViewController alloc] initWithNibName:#"MenuViewController" bundle:nil];
if (self.imageView.image != nil) {
menu.imageAdded = YES;
}
[self.view addSubview:menu.view];
}
}
Original Answer:
I'd suggest putting a NSLog or breakpoint at your code with the removeFromSuperview and see if you're even getting to that piece of code.
There are some clear problems here. Specifically, you're not adding added the view associated MenuViewController in handleLongPress properly. If you want a subview with it's own controller, you have to use containment (and that only works with iOS 5 and later). And in containment, you have critical methods like addChildViewController, etc. See Creating Custom Container View Controllers in the View Controller Programming Guide or see WWDC 2011 - Implementing UIViewController Containment. And, as an aside, you're also maintaining a strong reference to MenuViewController, so even if you succeeded in removing it's view, you'd leak the controller.
Spend a little time going through the containment documentation/video, and I think you'll want to revisit how you're presenting your menu. This is dense reading, but worth really understanding. Containment is powerful, but has to be done right.
[self.view removeFromSuperview];
what do you mean by this?????? removing the main view!!!!
Instead of directly using
[self.view removeFromSuperview];
use
[[self.view.superview subviews] makeObjectsPerformSelector:#selector(removeFromSuperview) withObject:self.view];
I have UIViewController(1) without navigationBar, and I need to push anouther UIViewController(2) that have navigationBar, and when I click Back on it, navigationBar must hide on 1 controller. I have tried uiviewcontroller delegates.
But nothing is working..
Please help..
This will show the navbar on the second screen:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = NO;
}
You will also need to hide the navbar when you return to the first screen:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
self.navigationController.navigationBarHidden = YES;
}
I think you want the animated option. If you roll with the approaches above (self.navigationController.navigationBarHidden = value) you get some undesirable visual crumbs.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
This will push/pop smoothly with the navBar firmly attached to the appearing/disappearing view.
Place this code in first view controller
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = YES;
}
Answers from Alfie or Ader would be a disaster if you have many viewcontrollers' navigation bar hidden/show state to manage.
I just have posted code dedicated on UINavigationBar appearance management on github. check out RRViewControllerExtension, it will solve your problem gracefully.
With RRViewControllerExtension, you even don't have to #import the header file, all you have to do is just override any desired method below in your viewcontroller.
//override any of the methods below in your viewcontroller's .m file to make specific navigation bar appearance
-(BOOL)prefersNavigationBarHidden;
-(BOOL)prefersNavigationBarTransparent;
-(nullable UIColor *)preferredNavatationBarColor;
-(nullable UIColor *)preferredNavigationItemColor;
-(nullable UIImage *)preferredNavigationBarBackgroundImage;
-(nullable NSDictionary *)preferredNavigationTitleTextAttributes;