Scroll Views in storyboarding iphone - iphone

I'm trying to set up a scrollView in an app using storyboarding. I have done everything correctly but the scrollview won't scroll in simulator or on iPhone.
MoreViewController.h
#property(nonatomic, retain) IBOutlet UIScrollView *moreScroll;
MoreViewController.m
-(void)viewDidLoad{
[moreScroll setScrollEnabled:YES];
[moreScroll setContentSize:CGSizeMake(1220, 354)];
}
I have connected the scrollView to the files owner, can someone help please
Thanks in Advance

With autolayout is there a new method - (void)viewDidLayoutSubviews
Here is a quick info:
Notifies the view controller that its view just laid out its subviews.
When a view’s bounds change, the view adjusts the position of its subviews. Your view controller can override this method to make changes after the view lays out its subviews. The default implementation of this method does nothing.
You should be fine if you add this:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubViews];
[moreScroll setContentSize:CGSizeMake(1220, 354)];
}

Setting an scroll view’s scroller style sets the style of both the horizontal and vertical scrollers. If the scroll view subsequently creates or is assigned a new horizontal or vertical scroller, they will be assigned the same scroller style that was assigned to the scroll view..
You should be if you add this lines in your code:
This line in .h file
#interface Shout_RouteView : UIViewController<UIScrollViewDelegate>
{
}
#property (retain, nonatomic) IBOutlet UIScrollView *scrollViewMain;
This lines copy in .m file
-(void)viewWillAppear:(BOOL)animated {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
scrollViewMain.frame = CGRectMake(0, 0, 768, 815);
[scrollViewMain setContentSize:CGSizeMake(768, 1040)];
}else {
scrollViewMain.frame = CGRectMake(0, 0, 320, 370);
[scrollViewMain setContentSize:CGSizeMake(320, 510)];
}
}

I suggest that you try to pust the content setting code into the viewWillAppear or viewDidAppear method. Its always best not attempt changing UI features before it is ready for display.

Related

iOS 7 Table view fail to auto adjust content inset

I am transiting my project to iOS7. I am facing a strange problem related to the translucent navigation bar.
I have a view controller and it has a tableview as subview (let's call it ControllerA) . I init a new uinavigationcontroller with the controllerA and present it modally using presentviewcontroller. The presented view controller's table view is blocked by the navigation bar. I set the automaticallyAdjustsScrollViewInsets to YES but the result did not change.
I knew I can set the edgesForExtendedLayout to UIRectEdgeNone, but it will make the navigation bar no more translucent.
After that, I tried to create a new view controller for testing. It contains almost the same elements. But the result is much different. The table view content does not get blocked.
Conclusion
Two View Controllers' automaticallyAdjustsScrollViewInsets set to YES
The project is not using storyboard
The first one is created at Xcode 4.6, The second one is newly created on Xcode 5
I have compared two classes xib and code, not much different
I have found the answer on apple developer forum.
There are two different case.
The first one, the view controller added is a UITableViewController.
And the issue should not be appeared since apple will auto padding it.
The second one, the view controller is NOT a UITableViewController.
And in the view hierarchy, it contains a UITableView. In this case, if the UITableview(or ScrollView) is the viewController's mainview or the first subview of the mainview, it will work. Otherwise, the view controller doesn't know which scroll view to padding and it will happen the issue.
In my case, the view controller is the second one. And there is a background image view as the first subview of the main view. So, it fails.
Here is the Apple developer forum link (need developer account to access):
https://devforums.apple.com/message/900138#900138
If you want the view to underlap the navigation bar, but also want it positioned so the top of the scrollview's content is positioned below the navigation bar by default, you can add a top inset manually once the view is laid out. This is essentially what the view layout system does when the top-level view is a scroll view.
-(void)viewDidLayoutSubviews {
if ([self respondsToSelector:#selector(topLayoutGuide)]) {
UIEdgeInsets currentInsets = self.scrollView.contentInset;
self.scrollView.contentInset = (UIEdgeInsets){
.top = self.topLayoutGuide.length,
.bottom = currentInsets.bottom,
.left = currentInsets.left,
.right = currentInsets.right
};
}
}
Based on Tony's answer I was able to get around this problem programatically with temporarily sending the table view to the back, let the adjustments be made and then send the background view back to the back. In my case there is no flickering to this approach.
In the View Controller:
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[self.view sendSubviewToBack:self.tableView];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.view sendSubviewToBack:self.backgroundView];
}
Obviously if there are other subviews on self.view you may need to re-order those too.
There's probably too many answers on this already, but I had to take Christopher's solution and modify it slightly to support view resizing and allowing the content inset to be changed in a subclass of the UIViewController.
#interface MyViewController ()
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset;
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setScrollViewInitialContentInset:UIEdgeInsetsZero];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) {
[self setScrollViewInitialContentInset:[self.scrollView contentInset]];
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset];
if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) {
if ([self respondsToSelector:#selector(topLayoutGuide)]) {
scrollViewInset.top = [self.topLayoutGuide length];
}
if ([self respondsToSelector:#selector(bottomLayoutGuide)]) {
scrollViewInset.bottom = [self.bottomLayoutGuide length];
}
[self.scrollView setContentInset:scrollViewInset];
}
}
#end
To explain the point:
Any subclass of MyViewController can now modify the contentInset of scrollView in viewDidLoad and it will be respected. However, if the contentInset of scrollView is UIEdgeInsetsZero: it will be expanded to topLayoutGuide and bottomLayoutGuide.
#Christopher Pickslay solution in Swift 2:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let topInset = topLayoutGuide.length
inTableView.contentInset.top = topInset
inTableView.contentOffset.y = -topInset
inTableView.scrollIndicatorInsets.top = topInset
}
Yeah - a bit annoying.
I have a nib with a single tableview within the main view, not using autolayout. There is a tabbar, navigationbar and a statusbar and the app needs to work back to 5.0. In Interface builder that neat 'see it in iOS7 and iOS6.1 side-by-side' thing works, showing the tables neatly fitting (once the iOS6/7 deltas were set properly).
However running on a device or simulator there was a large gap at the top of the table, which was as a result of a content inset (which pretty much matched by iOS6/7 vertical delta) that was set to zero in the nib.
Only solution I got was in viewWillAppear to put in [_tableView setContentInset:UIEdgeInsetsZero].
Another ugly hack with a pretty on-screen result.....
[self.navigationController setNavigationBarHidden:YES animated:YES];
in:
- (void)viewDidLoad

How to build a long interface using interface builder

I build an UIViewController, that higher than iPhone screen ( the height is 900px ), i build it using UIScrollView.
In the Interface Builder, how to put an View in the bottom part of the UIScrollview ? i've tried using freeform in the inspector -> Simulated Metrics, but every time i move back to the ipad/iphone screensize, the views are mess. And when i ran it in the simulator, the view still a mess
I'd add a view programmatically and make it subview for the scrollview, i don't know how to do it using IB.
If you want to try programmatically can try something like:
UIView*myView=[[UIView alloc ] initWithFrame:CGRectMake(0, 480, 320, 200)];
[myView setBackgroundColor:[UIColor redColor]]; // Just for testing purpose
[scrollView addSubview:myView];
You have to do a bit of it programatically I'm afraid but you can do most of it in a xib.
Your xib would contain a UIView that's your normal view, containing your scrollview.
It would also contain another UIView; this will be as long as you want and will be your scrollview's contents.
In your .h file, have a property like this and attach it to the second UIView in your xib
#property (nonatomic, retain) IBOutlet UIView *scrollingContents;
and in your viewDidLoad, that's where you attach the contents inside the scroll view
- (void)viewDidLoad {
[super viewDidLoad];
[self.scrollView addSubview:scrollingContents];
self.scrollView.contentSize = scrollingContents.bounds.size;
}

UIView loaded with Nib autoresizing issue

I have a UIView subclass -
#interface DatePickerPopup : UIView
UIToolbar *toolbar;
UIDatePicker *datePicker;
#end
#implementation
- (id)initWithFrame:(CGRect)frame
{
NSArray *xib =
[[NSBundle mainBundle]
loadNibNamed:#"DatePickerPopup"
owner:self
options:nil];
self = [xib objectAtIndex:0];
if (self) {
}
return self;
}
#end
and the nib looks like -
In my UIViewController containing the DatePickerPopup (datePopup):
- (void)viewDidLoad
{
datePopup = [[DatePickerPopup alloc] initWithRect:CGRectZero];
CGRect newFrame = datePopup.frame;
newFrame.y = 200.0f; //lets say this aligns it to the bottom in portrait
datePopup.frame = newFrame;
// Normally happens when accessory button pressed but for brevity...
[self.view.superview addSubview:datePopup];
}
- (void)willAnimateRotationToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
CGRect screen = [[UIScreen mainScreen] bounds];
if (toInterfaceOrientation == UIInterfaceOrientationPortrait ||
toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
self.datePopup.frame =
CGRectMake(0.0f, newHeightPortrait, screen.size.width, 260.0f);
}
else
{
self.datePopup.frame =
CGRectMake(0.0f, newHeightLandscape, screen.size.width, 260.0f);
}
}
However, this gets stretched out for some reason when the orientation changes the view gets stretched to the height of the screen bounds - the navigation bar...
after viewDidLoad
after willAutorotate...
Since your view controller appears to be managed by a navigation controller, calling [self.view.superview addSubview:datePopup]; adds your popup as a subview of a UIViewControllerWrapperView, which is one of the private classes UIKit uses to implement the functionality of UINavigationController. Messing with UIKit's private view hierarchy is always risky. In this case, based on the behavior you're seeing, it seems likely that UIKit expects any subview of UIViewControllerWrapperView to be a view controller's view, so it resizes your popup accordingly.
I think the safest way to resolve this is to have your view controller's view be a wrapper that contains your tableView and, when necessary, your popup view. Unfortunately using a wrapper view means that the view controller can't be a UITableViewController. You'll have to change the superclass to UIViewController, set a custom tableView property, and manually adopt the UITableViewDataSource and UITableViewDelegate protocols.
Note: You might be tempted to add your popover as a subview of your window, but I'm not recommending that because UIWindow only autorotates its topmost subview corresponding to a view controller. This means that if you add your popover to your window, it won't autorotate.
EDIT: BTW, by reassigning self = [xib objectAtIndex:0]; in initWithFrame:, you're leaking the object that was originally alloc'd. If you're going to reassign self in this way, you should release the existing object first.
Add the
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
method in the viewController class and return YES. If this method returns YES, only then will the device support landscape orientation. Try out this extra code and see if it helps...
You can set the frame size for landscape in this method itself instead of the current method. PS: I just saw you've used a UIView instead of controller...you might want to change to controller.

scrollViewWillBeginDragging not responding on a second UIScrollView

I have a probably nub question but i just can't get around this.
I have a UIScrollview on the top of the screen, below it there is a UITableView.
both are on my InterfaceBuilder, not done programmatically
and declared on my .h as:
#interface RootViewController : UIViewController <UIScrollViewDelegate, IconDownloaderDelegate>
{
IBOutlet UIScrollView *scrollview;
}
etc.
Inside the UIScrollView i have a long tabbar also in IB mi code is as follows for this:
[scrollview setScrollEnabled:YES];
[scrollview setContentSize:CGSizeMake(1100, 29)];
Everithing works perfectly the tabbar works and moves etc.
the problem is that when implementing scrollViewWillBeginDragging
it only registers the scrolling on my UITableView and not on the scrollview.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
NSLog(#"done");
}
What am i doing wrong??
Thanks in advance!
You have to set the delegate to the class where you implement the delegate methods.
scrollview.delegate = self;
add [scrollview SetDelegate:self]; in the place you add scrollview

UIScrollView not showing

I have a simple ViewController that looks like this:
#interface MyViewController : UIViewController<UIScrollViewDelegate> {
UIScrollView *scrollView;
UILabel *label;
}
...
#property stuff
...
Now, what I'm trying to do with this Controller is have a ScrollView handle a really large label of text that I have. So in the viewDidLoad method of MyViewController.m I have:
scrollView.contentSize = CGSizeMake(1000,1000);
scrollView.delegate = self;
scrollView.clipsToBounds = YES;
[self.view addSubview:scrollView];
And I get a blank screen that I cannot scroll around on. It's just a white screen. Before adding the label part, I thought I would try to set up the scroll view first, and this is not even working. Shouldn't I see some scroll bars when I move my fingers around? How do I set up the scroll view so that it contains a label?
Thanks!
The scrollView wont be scrollable until you actually place content inside it which exceeds its frame. So, add your label to the scrollview and it should become scrollable.