I have a custom split view controller, designed to work as much like apple's as possible.
I use this split view in three different places. Two of these places, the master is a view simply a UIViewController with a UIView attached, and created programmatically.
The third example however is a UIViewController with a XIB.
The problem is that the first two split views adjust their widths correctly. However the screen with the XIB does not. I'm not doing anything fancy, just trying to set the content view of my master with a view that is passed in to it. And setting the autoresizing masks as such:
// create container views
masterView = [[VS_MasterView alloc] init];
masterView.frame = CGRectMake(0, 0, masterViewWidth, self.view.frame.size.height);
masterView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:masterView];
// get the views
UIViewController *masterViewController = (UIViewController *)[_viewControllers objectAtIndex:0];
UIViewController *detailViewController = (UIViewController *)[_viewControllers objectAtIndex:1];
// set their bounds
[masterViewController willMoveToParentViewController:self];
[self addChildViewController:masterViewController];
[masterViewController didMoveToParentViewController:self];
masterViewController.view.frame = masterView.bounds;
masterViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[masterView addSubview:masterViewController.view];
is there some sort of special case with XIB files and resizing them in this situation? I don't feel like there should be.
thanks
Related
I wanted to post a gif but apparently I don't have enough reputation. Oh well, whatever; I was using UIPageViewController, but for some reason I decided to go with a more manual solution by using UIScrollView and adding the views of UITableViewControlllers to the corresponding offsets (pages). I have 4 UItableViewControllers on each page (the views of table view controllers) and all of these are added to the container view controller (which has the UIScrollView) as child view controllers.
The actual problem is when I made the switch, table views began refusing to go all the way down and part of the final table view cell stays trimmed by the end of the screen when the scrolling ends.
So, wanted to ask if anyone came across something like this before of know how to get rid of this. I know I could always use a library, but I want to learn. Here is some code:
_containerScrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
_containerScrollView.contentSize = CGSizeMake(_containerScrollView.frame.size.width * 4, 0.0f);
_containerScrollView.pagingEnabled = YES;
[self.view addSubview:_containerScrollView];
UITableViewController *vc1 = [[UIViewController alloc] init];
UITableViewController *vc2 = [self.storyboard instantiateViewControllerWithIdentifier:#"trendingViewController"];
UITableViewController *vc3 = [self.storyboard instantiateViewControllerWithIdentifier:#"placesViewController"];
UITableViewController *vc4 = [self.storyboard instantiateViewControllerWithIdentifier:#"favoritesViewController"];
self.rallyViewControllers = [NSArray vc1, vc2, vc3, vc4, nil];
[self addViewControllers];
Other methods;
- (void)addViewControllers{
if (self.rallyViewControllers == nil) {
return;
}
for (int i = 0; i < [self.rallyViewControllers count]; i++) {
UIViewController* viewController = [self.rallyViewControllers objectAtIndex:i];
[self addChildViewController:viewController];
[viewController didMoveToParentViewController:self];
[_containerScrollView addSubview:viewController.view];
}
}
This is called in viewDidLayoutSubviews
- (void)configureFrames{
if (self.rallyViewControllers == nil) {
return;
}
CGFloat width = _containerScrollView.frame.size.width;
CGFloat height = _containerScrollView.frame.size.height;
for (int i = 0; i < [self.rallyViewControllers count]; i++) {
UIViewController *viewController = [self.rallyViewControllers objectAtIndex:i];
viewController.view.frame = CGRectMake(i * width, 0.0f, width, height);
}
}
I should state upfront that I didnt completely understand your description of
"table views began refusing to go all the way down and part of the
final table view cell stays trimmed by the end of the screen when the
scrolling ends."
My answer is based on an issue I faced before. My setup is a uitableview in the storyboard container view ( without any parent scrollview)
I faced this issue where part of the tableview was cut off and I could not see about 5 bottom rows.
Turns out I did not have any constraints setup between the parent container view and the tableview.
To determine if your tableviews are rendering fine, get your project running in XCode and then press on the below button
This button will then pause your app and give you a visual stack of the the different views that are currently rendered in your app. You can then see if any of the children ( in your case tableviews) are rendered outside the frame of the parent view in which case that portion will not be visible. This indicates that you either dont have constraints (or) the current constraints you have are incorrect.
I got it. The problem was when I added the view controllers views to the scroll view, they returned dimensions as if there was no navigation bar. But they were still positioned under the navigation bar, which caused total view to have 64 pt more height than the screen could show. when I manually subtracted 64 pt from views, and it was fixed. But since that is a very crude way of doing this, I then tried to fix it by fiddling with auto-layout, which ended up fine.
I am looking at adding numerous TableViews to an existing UI View Controller.
I have seen https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html which seems to be the way I'm meant to go.
However, my question is can I embed more than one TableView to a single ContainerView?
My app does a variety of tests for which there are results. After each test completes I want to add a TableView so they appear underneath each other neatly.
Is this possible?
Yes you can. You can do two things:
ONE View Controller - MANY Table Views (as subview of the root view)
or
ONE Container Controller - MANY ChildViewControllers using VC containment (and each has one Table View )
This is what you could do in ViewDidLoad for a UIViewController subclass.
// Do any additional setup after loading the view, typically from a nib.
CGRect frame = self.view.frame;
// this container shall hold the two tables that I am going to add later
// container shall share the same size as view controller's "view"
UIView *container = [[UIView alloc] initWithFrame:frame];
frame.size.height = frame.size.height / 2; // I want to fit two table view vertically to cover the container view
UITableView *tableView1 = [[UITableView alloc] initWithFrame:frame];
tableView1.backgroundColor = [UIColor redColor];
// ...
// ...
// Assign more table view properties here
// ...
// ...
[container addSubview:tableView1];
frame.origin.y = frame.size.height; // update coordinates for the second table view
UITableView *tableView2 = [[UITableView alloc] initWithFrame:frame];
tableView2.backgroundColor = [UIColor greenColor];
// ...
// ...
// Assign more table view properties here
// ...
// ...
[container addSubview:tableView2];
[self.view addSubview:container];
you shall have to set Delegates for all tableviews to make them work properly, but this should give you something to get going. (I have added some different background colors to distinguish between both the tableviews)
I'm creating a landscape iPad app for iOS 5.1 that should have two table views embedded into a view controller of my storyboard. What I would like to be able to do, is drag a table view controller onto the view controller in my storyboard. But of course, Xcode does not allow this. I can drag a table view and get its data hooked up and it works properly, but then I cannot push a new view controller to replace that table when a row is selected.
I cannot use the 'Editor > embed in > navigation controller' trick, because then the entire storyboard view controller (which contains my two table views) is embedded. That is not what I want.
There must be a way to do this programmatically, but I can't seem to get the right combo of voodoo and science to make it work.
I have tried to create a custom container view to hold my tableViewController, but the table isn't showing up.
Any thoughts?
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame = CGRectMake(68, 187, 402, 474);
_containerView = [[UIView alloc] initWithFrame:frame];
_containerView.backgroundColor = [UIColor redColor];
[self.view addSubview:_containerView];
categoryController = [[UITableViewController alloc] init];
categoryTable = [[UITableView alloc] init];
categoryTable.delegate = self;
categoryTable.dataSource = self;
[categoryController.view addSubview:categoryTable];
[_containerView addSubview:categoryController.view];
}
What you need is Container Views
Here are some tutorials that can help you:
http://www.cocoanetics.com/2012/04/containing-viewcontrollers/
http://weblog.invasivecode.com/post/12383262201/container-view-controllers-part-i-one-of-the
https://developer.apple.com/videos/wwdc/2011/?id=102
Despite the number of similar posts on this, I still am having trouble making this work correctly.
I have a two UIViewControllers which I have designed in IB with UILabels and imageviews, etc.
I would like to add these to a scroll view so they can be paged between.
I have outlets defined connecting each of the scrollViewcontrollers with their elements in IB, however, the controllers themselves, I am programatically creating from within the master view controller in viewDidLoad. After creating them, I assign some values from the master view controller than add it as a subview to the scrollViewController. However nothing displays. From the debugging i have done, when I set a break point after assigning the values, I can see that the elements are nil. They should be loaded from the xib file, but it does not seem to be read. Even as a test, I tried initializing one of the elements (eg. UILabel) and setting it to that sub view controller, but it nothing would display. Here is some code to explain a bit better.
In the master view controller
detailControllerA *tempA = [[detailControllerA alloc] initWithNibName:#"detailOverviewA" bundle:nil];
self.overviewA = tempA;
[tempA release];
self.overviewA.someLabel.text = #"Some Text";
detailScrollView.contentSize = CGSizeMake(scrollWidth, scrollHeight);
detailScrollView.pagingEnabled = YES;
[detailScrollView addSubview:self.overviewA.view];
In the detailControllerA implementation I set the frame in loadView:
-(void)loadView {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 90)];
self.view = view;
[view release];
}
I also have the labels, etc defined with IBOutlets in detailControllerA.h and implemented to the elements in the xib file.
Any ideas why the xib is not loading correctly when created programatically?
Try in this way:
NSUInteger scrollContentCount = 0;
for (NSUInteger arrayIndex = 0;
arrayIndex < [contents count];
arrayIndex++) {
// set scorllview properties
CGRect frame;
frame.origin.x = self.mScrollView.frame.size.width * arrayIndex;
frame.origin.y = 0;
frame.size = self.mScrollView.frame.size;
myScrollView.autoresizingMask = YES;
// alloc - init PODetailsView Controller
myController = [[MyController alloc] initWithNibName:#"MyController" bundle:[NSBundle mainBundle]];
[myController.view setFrame:frame];
// add view in scroll view
[self.myScrollView addSubview:myController.view];
scrollContentCount = scrollContentCount + 1;
}
// set scroll content size
self.myScrollView.contentSize =
CGSizeMake(self.myScrollView.frame.size.width * scrollContentCount,
self.myScrollView.frame.size.height);
}
Don't release the content controller object which is in for-loop.
Set your scrollView contentSize according to your requirement.
Hope this would be helpful to you.
Interestingly enough, the -(void)loadView was the problem.
Since the view is being generated in interface builder (with the frame settings), when loadView fires, it was creating a new view, blowing away the one created in interface builder.
I have a UIPopoverController with two view controllers inside of it. I'm building it like so:
CommentsPopoverController *commentsPopoverController = [[CommentsPopoverController alloc] init];
self.delegate = commentsPopoverController;
commentsPopoverController.navigationItem.title = #"Comments";
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:commentsPopoverController];
popover = [[UIPopoverController alloc] initWithContentViewController:navController];
Inside my commentsPopoverController I have this:
commentsViewController = [[CommentsViewController alloc] init];
commentsViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
addCommentsViewController = [[AddCommentViewController alloc] init];
addCommentsViewController.view.frame = CGRectMake(0, commentsViewController.view.bounds.size.height - 200, 320, 346);
addCommentsViewController.view.backgroundColor = [UIColor darkGrayColor];
[self.view addSubview:addCommentsViewController.view];
[self.view addSubview:commentsViewController.view];
So when I first load the popover, the addCommentsViewController is hidden by the commentsViewController. When I reveal it, it looks like this:
So far so good. The problem I'm having is that from here, when the user rotates the device or shows the keyboard or shows the keyboard THEN rotates the device things start to get out of whack. The top view controller (commentsViewController) which is a UITableView always does the right thing no matter what the orientation is or whether or not the keyboard is showing. But the bottom view controller (addCommentsViewController) doesn't automatically change it's origin.y to stay directly under the top view controller.
So I've basically had to hack the crap out of my code to keep the addCommentsViewController directly under the commentsViewController by constantly calculating the height of the top view controller so that I could adjust the bottom view controller's origin.y. This involved dropping in NSNotifications for the keyboard's show/hide state and for the device's orientation and constantly recalculating. Very hackish and ugly.
So my question (finally) is: Is there an easier way of controlling these views or am I stuck hacking it the way I did?
To handle rotation, there are two appropriate techniques. One is that you make CommentsPopoverController's view a subclass of UIView that overrides layoutSubviews to lay out your two views properly. The other is that you define viewDidLayoutSubviews on CommentsPopoverController to lay out your views. If you lay out your views in either of these methods, you shouldn't have to subscribe to rotation notifications.
As for moving your view out from under the keyboard, that is discussed in the Text, Web, and Editing Programming Guide for iOS. Part of the technique involves subscribing to keyboard will show/did hide notifications.
I assume your CommentsViewController is a subclass of UITableViewController, because UITableViewController takes care of adjusting the table view when the keyboard is hidden or shown.