So basically I have this project, where I have 4 different tab bar pages. 2 of them uses navigation controller & tab bar, and 2 are just view controllers. Now there is this one viewcontroller, which I need to add a scroll view to. So basically, I click on the item in the tab bar, it takes me to a view controller, where I can scroll down and up. I have been following Youtube Video Link, but I do not get it to work. The problem is that I use the exact code, and I change the ViewController class to the .h and .m name (ScrollViewViewController), and I put in a scroll view that has 320 x 1000, and a button at the top, but it doesn't scroll! How can I solve this problem?
Note: That if you don't know my problem, but could very detailed walk me through on how to add a scroll view to storyboards in xcode 4.2, then that would be amazing :)!
scrollerViewController.m:
- (void)viewDidLoad {
[scroller setScrollEnabled:YES];
[scroller setContentSize:CGSizeMake(320, 1000)];
[super viewDidLoad];
}
scrollerViewController.h
#interface scrollerViewController : UIViewController {
IBOutlet UIScrollView *scroller;
}
#end
And here comes a picture of the storyboard.
I need some of the code in order to really know your problem, but let me throw in my guess. You may be setting the size 320x1000 to the frame size of the scrollview by any chance? The frame size of the scrollview has to stay 320x480, and the contentSize should be 320x1000. Sorry if it was a wrong guess, but shouldn't do any harm :)
Something like this in your ViewController of the scrollView...
- (void) viewDidLoad {
[super viewDidLoad];
UIScrollView * scrollView = self.view;
scrollView.frame = (CGRect){scrollView.frame.origin, CGSizeMake(320, 480)};
scrollView.contentSize = CGSizeMake(320, 1000);
scrollView.backgroundColor = [UIColor whiteColor]; // I am setting the white background, so that the scroll indicator is visible
}
I am assuming you are setting ScrollView as the top view of the ViewController in your Storyboard as in the attached image.
I followed the exact same movie and it did not work for me either. But this movie did: http://www.youtube.com/watch?v=YBlwepYK7Zs
I followed that one and now i got it to work.
A bit late but might be more people looking for a solution to this.
Related
I am using auto layout with Storyboard. I present a popoverPresentationController from a cell rect:
NumberController * viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"NumberController"];
UIPopoverPresentationController *pc = [viewController popoverPresentationController];
pc.delegate = self;
pc.permittedArrowDirections = UIPopoverArrowDirectionAny;
pc.sourceView = tableView;
pc.sourceRect = [tableView rectForRowAtIndexPath:indexPath];
[self.navigationController presentViewController:viewController animated:animated completion:nil];
The popover presents on an iPad in portrait mode with the arrow up.
I rotate the iPad to landscape mode. The popoverPresentationController keeps the same sourceView/sourceRect and properly points to the cell. It also keeps the up arrow.
But it is now at the bottom of the view, so the popover resizes to a shorter height. This is not desired behavior.
If the popover were simply to move to a new position and change the arrow direction, it would not need to resize at all. This is the desired behavior.
I thought the following method might permit me to make changes, but it is not called since the sourceView rect does not change:
- (void)popoverController:(UIPopoverController *)popoverController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView **)view {
}
I have tried to reset the permittedArrowDirections (in preferredContentSize, because this seemed like the most logical place). This does not work (the popover still resizes):
- (CGSize) preferredContentSize {
[super preferredContentSize];
self.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionUnknown;
return CGSizeMake(DEFAULT_POPOVER_WIDTH,DEFAULT_POPOVER_HEIGHT);
}
I simply cannot find a way to force the popoverPresentationController to change arrow direction and reposition the popover instead of resizing the popover. I am beginning to think it is not even possible - but I still hold out hope that I am just missing something.
EDIT: In the meantime, it has occurred to me that maybe a popover is not the best way to present this view if I don't want it resized in iPad. I am going to try it with UIModalPresentationFormSheet presentation. But I would still like to find an answer to this question.
I just ran into the problem where
- (void)popoverController:(UIPopoverController *)popoverController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView **)view {
was not being called because my view controller was detached. There may be a view in your view hierarchy whose view controller has not been added as a child view controller.
I thought the following method might permit me to make changes, but it is not called since the sourceView rect does not change
The sourceView rect does not have to change, just the interface orientation. From the UIPopoverControllerDelegate documentation:
For popovers that were presented using the presentPopoverFromRect:inView:permittedArrowDirections:animated: method, the popover controller calls this method when the interface orientation changes.
I just have one question related to presenting a from sheet view controller in iOS 8. In iOS 7 I was able to change the height of the view controller using the last line of code in the function below:
SendRemainingEvaluationsViewController *sendRemainingEvaluationViewController = [[[SendRemainingEvaluationsViewController alloc] initWithNibName:#"SendRemainingEvaluationsViewController" bundle:nil]autorelease];
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:sendRemainingEvaluationViewController] autorelease];
navigationController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navigationController animated:YES completion:nil];
//To Change the default size of the viewController which is presented in UIModalPresentationFormSheet presentation style
navigationController.view.superview.frame = CGRectMake(navigationController.view.superview.frame.origin.x, navigationController.view.superview.frame.origin.y, navigationController.view.superview.frame.size.width, 230);
But this does not work on iOS 8, not sure why? Does anyone knows what is the problem? any idea will be appreciated.
Thanks in advance.
After checking it, I could figure out the problem. After initializing the view navigation controller, its superview is nil and you can't access it right after presenting it. As a workaround, you can change the frame of its superview in the viewwillAppear of the view controller you're trying to present as you can see below:
- (void) viewWillAppear:(BOOL)animated
{
self.parentViewController.view.superview.frame = CGRectMake(self.parentViewController.view.superview.frame.origin.x, self.parentViewController.view.superview.frame.origin.y, self.parentViewController.view.superview.frame.size.width, 230);
}
This should work.
In trying to attempt to use Apple's UIViewController containment I have encountered a problem with animating the transition between two UIViewControllers.
Here is the set up... I have created a UITabBarController and within one of the tabs I have created a UIViewController as a container. This ViewController manages the transition between a UIViewController and a UINavigationController. The before view is:
When the Next button is tapped the view begins it's transition with a flipFromRight transition. During the transition, the Navigation bar is in "to" view but is located 20pixels down from the top edge of the view. Picture below:
The green is the background color of the container view. Once the new view completes the transition, the Navigation bar snaps up to the top of the view and the final result is:
The time to snap in place is independent of the duration of the animation. I achieve the final state that I want, but the transition is a problem.
I have instrumented the viewController lifecycle and the frames of the Navigation bar and the UITableView are as specified in the XIB. The xib looks like this:
Here is the code:
In -viewDidLoad -
_fromVC = [[FromVC alloc] initWithNibName:#"FromVC" bundle:nil delegate:self];
[self addChildViewController:_fromVC];
[self.view addSubview:_fromVC.view];
[_fromVC didMoveToParentViewController:self];
In my button handler -
- (void)buttonSelected
{
//
// Create the "to" View controller
//
ToVC *toVC = [[ToVC alloc] initWithNibName:#"ToVC" bundle:nil];
//
// Create the navigation controller for the study activity
//
_toNavCon = [[UINavigationController alloc] initWithRootViewController:toVC];
[self addChildViewController:_toNavCon];
[_fromVC willMoveToParentViewController:nil];
[self transitionFromViewController:_fromVC
toViewController:_toNavCon
duration:0.7
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:^(BOOL finished) {
[_fromVC removeFromParentViewController];
[_toNavCon didMoveToParentViewController:self];
}];
}
There is no code in "to" view controller that changes the appearance of the view controller.
Another bit of information... When I "toggle In-Call status bar" in the simulator the gap at the top of the navigation bar is the height of the In-Call status bar.
I have looked at everything on the web and there is nothing that helps. Has anyone seen this and has anyone fixed it?
I did find an answer!! Subclass UINavigationController and override
- (BOOL)wantsFullScreenLayout{
return NO;
}
Apparently, UINavigationController and UITabController always want the full screen (default YES) - adjusting for the status bar - and you can not set this property any other way. It has been working for me.
[self.scrollView scrollRectToVisible:textField.bounds animated:YES];
I can't seem to get my UIScrollView to scroll at all so that it doesn't obscure my UITextField. I thought that scrollRectToVisible would be my savior but it looks like a no go. Maybe I'm missing something like translating the coordinates of my textField to my scrollView. Either way check out my sample project.
https://github.com/stevemoser/Programming-iOS-Book-Examples/tree/master/ch20p573scrollViewAutoLayout2
Oh, and this project might be missing the delegate connection but I checked that and it still doesn't scroll.
I've seen other questions similar to this but none that mention Autolayout.
I was having issues with scrollRectToVisible:: as well after converting to Auto Layout. I just changed it to a direct call to setContentOffset:: and it started working again.
I had the same problem, I wanted to scroll an autolayouted UITextEdit into view without making it the first responder.
For me the issue was that the bounds of the UITextField were set later on during the auto layout pass, so if you do it immediately after setting up the layout the bounds are not valid yet.
To workaround I did create a descendant of UITextField, did overwrite setBounds: and added a 0 timer to scroll into view "later on" (You can't scroll in that moment because the auto layout pass of the system might no be finished at that point)
#interface MyTextField: UITextField
{
bool _scrollIntoView;
}
..
#end
#implementation MyTextField
-(void)setBounds:(CGRect)bounds
{
bool empty=CGRectIsEmpty(self.bounds);
bool isFirstResponder=self.isFirstResponder;
[super setBounds:bounds];
if (empty && !isFirstResponder && _scrollIntoView)
[self performSelector:#selector(scrollIntoViewLater) withObject:nil afterDelay:0];
else if (empty && isFirstResponder)
[self performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0];
}
-(void)scrollIntoViewLater
{
CGRect r=[scrollView convertRect:self.bounds fromView:self];
[scrollView scrollRectToVisible:r animated:TRUE];
}
#end
If the field should be additionally editable with the on screen keyboard, simply call becomeFirstResponder later on: it scrolls automagically into view above the keyboard using the private scrollTextFieldToVisible API which in turn calls scrollRectToVisible:animated: of the scrollview.
Your sample link is broken btw...
I have a UINavigationController which contains several UIViewControllers. I would like to create a shared "panel" that is displayed at the top of each view. In addition, I would like to make that panel expand and collapse, overlaying the view, when tapped.
View1
-Top Panel (collapsible)
-Main Panel
View2
-Top Panel (collapsible)
-Main Panel
This would be similar to the way the toolbar or navigation panel hide/show for the camera controller, but it would be a custom view. This is an iPhone app.
As a new XCode developer I would appreciate insights as to how this should be approached from an architectural standpoint.
Create a UIViewController subclass, say called PanelStyleUIViewController,
which would be a superclass for all the views that will have the panel. The superclass implements the panel's controller logic, and the view expansion and contraction, which always happens above the children controller's regular view logic.
This is going to be a modestly difficult project for a new iOS/cocoa developer, because:
You probably will end up having to write a lot of the folding panel's view code programmatically. It is possible to design it in interface builder using more advanced techniques but IB's basic usage is to design one view controller at a time. You need to design a partial, parent view controller that then is inherited to a number of different ones.
You need to make sure that the folding view is always above (z-index wise) the regular view content of the lower level view controller classes. This is something that is probably solved by doing a bringSubviewToFront call on the panel view on, say, the viewDidAppear method.
You are going "off road" from how standard iPhone apps behave. Whenever you do this, you make headaches for yourself and might find yourself at a dead end. My recommendation would be to stay "inside the lines" for a while until you are pretty confident with objective C, cocoa touch, etc.
That said, here's some untested code I wrote here in the stack overflow editor which should give you an idea of what I mean for this superclass design:
// PanelStyleUIViewController.h
#interface PanelStyleUIViewController : UIViewController {
UIView *panelView;
}
#property (nonatomic, retain) UIView *panelView;
// PanelStyleUIViewController.m
#implementation PanelStyleUIViewController
#synthesize panelView;
- (void)viewDidLoad {
[super viewDidLoad];
// setup geometry, contents, etc of panelView programmatically...
self.panelView = [[[UIView alloc] init] autorelease];
panelView.frame = CGRectMake(0,0,320,200);
// set resizing mask appropriately for landscape support
panelView.autoresizingMask = UIViewAutoresizingMaskFlexibleWidth | UIViewAutoresizingMaskFlexibleBottomMargin;
// put a button on the panel view so it can be tapped to slide down
UIButton *slidePanelButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
slidePanelButton.frame = CGRectMake(0,160,320,40);
[slidePanelButton addTarget:self action:#selector(slidePanel) forControlEvents:UIControlEventTouchUpInside];
[panelView addSubview:slidePanelButton];
// set panelView with a transform offset to slide it up under the top of the screen
panelView.transform = CGAffineTransformMakeTranslation(0, -160);
// add panelView to regular view controller's view
[self.view addSubview:panelView];
}
- (void)viewWillAppear {
// make sure the panel shows up on top, z-index wise, since subclasses might have created views that overlap it.
[self.view bringSubviewToFront:panelView];
}
- (void)slidePanel {
// remove the panel transform in an animated fashion (slide down).
// TODO: some button or action needs to slide the panel back up...
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[panelView setTransform:CGAffineTransformMakeTranslation(0,0)];
[UIView commitAnimations];
}
- (void)viewDidUnload {
[super viewDidUnload];
// always make sure you clean up progammatically-retained views here
self.panelView = nil;
}
- (void)dealloc {
// and here too
self.panelView = nil;
[super dealloc];
}