I am doing a PhoneGap iPad application. In this I had added a HybridPage (which contains webView) as a child view controller and then after that screen I am adding a New Controller (also removed the hybridPage from ParentViewController) which contains Native Controller and again same instance of HybridPage Controller (added two controllers as childs).
Here My Native Controller size is (320,704) and Hybrid Controller size is (702,704).
Now the problem is I am not able to interact with Half frame of Hybrid controller from right side (320 width from the end of contentoffset of the view).
I have given the two viewControllers frames even though I am not able to interact with some rect of Hybrid controller.
(void)setDashboardRootViewController:(UIViewController*)rootViewController
{
if ([[self childViewControllers] containsObject:[MCIPadRootViewController getIPadRootViewController].mcWebViewController])
{
[[MCIPadRootViewController getIPadRootViewController] removeMCWebViewController];
}
[self addChildViewController:self.dashboardViewController];
[self.dashboardContainerView addSubview:self.dashboardViewController.view];
if ([rootViewController isKindOfClass:[MCLoginFlowWebViewController class]])
{
[self addChildViewController:[MCIPadRootViewController getIPadRootViewController].mcWebViewController];
[MCIPadRootViewController getIPadRootViewController].mcWebViewController.view.frame = CGRectMake(0, 0, self.mcWebViewContainerView.frame.size.width, self.mcWebViewContainerView.frame.size.height);
[self.mcWebViewContainerView addSubview:[MCIPadRootViewController getIPadRootViewController].mcWebViewController.view];
}
}
Where can i set Child ViewController's Frame. Here i had set the viewcontroller's view frame but it is not effecting.
Could anybody help me to get out from this issue.
Please find the Screen shot for clarity.
You would typically set the frame of a child view controller's view in 2 places.
Right before you add it to the parent. Search for a call to addChildViewController: in the parent view controller. Set frame right before that call (there may be 2 calls to addChildViewController:).
If the size changes due to rotation you'll need to reset the frame of the child view controller's view in the parent view controller's viewWillLayoutSubviews: method.
Here's an example from a custom split view controller.
Notice the 2 places where where #1 is set.
- (void)setMasterViewController:(UIViewController *)controller
{
if (!_masterViewController) {
// Add the new controller
controller.view.frame = self.masterView.bounds;
[self addChildViewController:controller];
[self.masterView addSubview:controller.view];
[controller didMoveToParentViewController:self];
_masterViewController = controller;
}
else if (_masterViewController != controller) {
// Transition from the old to new controller
controller.view.frame = self.masterView.bounds;
[_masterViewController willMoveToParentViewController:nil];
[self addChildViewController:controller];
self.view.userInteractionEnabled = NO;
[self transitionFromViewController:_masterViewController
toViewController:controller
duration:0.0
options:UIViewAnimationOptionTransitionNone
animations:^{}
completion:^(BOOL finished) {
self.view.userInteractionEnabled = YES;
[_masterViewController removeFromParentViewController];
[controller didMoveToParentViewController:self];
_masterViewController = controller;
}
];
}
}
Here is where #2 is set:
- (void)viewWillLayoutSubviews
{
CGRect contentFrame = self.view.bounds;
float contentWidth = contentFrame.size.width;
CGRect masterRect = contentFrame;
CGRect detailRect = contentFrame;
CGRect dividerRect = contentFrame;
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
masterRect.size.width = DEFAULT_SPLIT_POSITION;
detailRect.origin.x = DEFAULT_SPLIT_POSITION + DEFAULT_DIVIDER_WIDTH;
detailRect.size.width = contentWidth - (DEFAULT_SPLIT_POSITION + DEFAULT_DIVIDER_WIDTH);
dividerRect.size.width = DEFAULT_DIVIDER_WIDTH;
dividerRect.origin.x = DEFAULT_SPLIT_POSITION;
}
else {
masterRect.size.width = contentWidth;
detailRect.origin.x = contentWidth;
dividerRect.origin.x = contentWidth;
}
self.masterView.frame = masterRect;
self.detailView.frame = detailRect;
self.dividerView.frame = dividerRect;
}
[Edited]
So can you update your code with the following so that you call all of the view container containment methods are used and called in the correct order.
[MCIPadRootViewController getIPadRootViewController].mcWebViewController.view.frame = CGRectMake(0, 0, self.mcWebViewContainerView.frame.size.width, self.mcWebViewContainerView.frame.size.height);
[self addChildViewController:[MCIPadRootViewController getIPadRootViewController].mcWebViewController];
[self.mcWebViewContainerView addSubview:[MCIPadRootViewController getIPadRootViewController].mcWebViewController.view];
[controller didMoveToParentViewController:self];
Also I don't think your CGRectMake is correct. You normally wouldn't reference the view's frame, you would reference the parent view's bounds. Try setting it like this and see if it helps. That will have it fill the parent view but you can also tweak it.
[MCIPadRootViewController getIPadRootViewController].mcWebViewController.view.frame = self.mcWebViewContainerView.bounds;
I came up with my Own solution.
The problem is my application opens in Landscape mode So i converted my view frame to bounds.
[[[self recurringListController] view] setFrame:[[self view] bounds]];
Using the above method I overcome my issue.
Related
I'm trying to create a UIScrollView with 3 UIViewController subviews. I'm done some research and it seems that the answer to this question provides a good solution Setting up UIScrollView to swipe between 3 view controllers, but I'm not sure. I downloaded the sample code which the answerer nicely posted https://github.com/gneil90/CustomContainerViewController and my question is as follows:
BViewController *bViewController = [[BViewController alloc]init];
[self addChildViewController:bViewController];
[self.scrollView addSubview:bViewController.view];
[bViewController didMoveToParentViewController:self];
CViewController *cViewController = [[CViewController alloc]init];
CGRect frame = cViewController.view.frame;
frame.origin.x = 320;
cViewController.view.frame = frame;
[self addChildViewController:cViewController];
[self.scrollView addSubview:cViewController.view];
[cViewController didMoveToParentViewController:self];
self.scrollView.contentSize = CGSizeMake(640, self.view.frame.size.height);
self.scrollView.pagingEnabled = YES;
The code in the sample project initializes both UIViewControllers at once. Is there any way to lazy load them/would this provide any kind of performance enhancements? If 2 of my viewcontrollers download data, I wouldn't want to download this data unless the user was actually viewing these screens, but with this kind of initialization it would seems as though the user quickly viewed both of them.
You can use UIScrollView delegate method, initialize only first view controller as you are doing.
For rest of your view controller you can create property. In UIScrollView delegate method scrollViewDidScroll do following-
// Check at what index, to second VC or third VC
if (some condition, you can define this based on scroll postion) {
// Check if second view controller
if (!self.cViewController) {
cViewController = [[CViewController alloc]init];
CGRect frame = cViewController.view.frame;
frame.origin.x = 320;
cViewController.view.frame = frame;
}
// similarly for third
}
Using this view controller are initialized as they are needed.
Im trying to implement my own CustomUIActionSheet.
I have it almost working, but I have no idea how does the showInView method works.
(void)showInView:(UIView *)view
giving a view, this method is capable of put its view in front of every single view (adding it to the windows maybe?) but its also capable of settings the rotation accordingly to the view in which is being added.
Ive tried adding it to the windows of the view that I recieve as a parameter.
CGFloat startPosition = view.window.bounds.origin.y + view.window.bounds.size.height;
self.frame = CGRectMake(0, startPosition, view.window.bounds.size.width, [self calculateSheetHeight]);
[view.window addSubview:self];
self.blackOutView = [self buildBlackOutViewWithFrame:view.window.bounds];
[view.window insertSubview:self.blackOutView belowSubview:self];
By doing this, all works, except that when I present the action sheet in landscape, the action sheet apears from the right (since the windows system reference its always the same)
I´ve also tried to add it to the rootViewController of the view windows like that:
UIView * view = view.window.rootViewController.view;
CGFloat startPosition = view.bounds.origin.y + view.bounds.size.height;
self.frame = CGRectMake(0, startPosition, view.bounds.size.width, [self calculateSheetHeight]);
[view addSubview:self];
self.blackOutView = [self buildBlackOutViewWithFrame:view.bounds];
[view insertSubview:self.blackOutView belowSubview:self];
but again, it fails in landscape, it doesnt add anything or at least, I can not see it
So, my question is, any clue of how can I add a view to the top of the hierarchy working in both orientations?
thanks a lot!
After reading some source code of custom alert views and other ui components that are dranw in the top of the hierarchy I found a working solution.
Adding the view in the first subview of the windows:
UIView * topView = [[view.window subviews] objectAtIndex:0];
So the final code is
UIView * topView = [[view.window subviews] objectAtIndex:0];
CGFloat startPosition = topView.bounds.origin.y + topView.bounds.size.height;
self.frame = CGRectMake(0, startPosition, topView.bounds.size.width, [self calculateSheetHeight]);
[topView addSubview:self];
self.blackOutView = [self buildBlackOutViewWithFrame:topView.bounds];
[topView insertSubview:self.blackOutView belowSubview:self];
I want to create a View outside of the visible screen and push in it (like the default pushViewController animation), but I cannot create the UIView outside. I was trying this code here, but it doesn't work. The View gets always created and displayed in the current UIScreen bounds. That means instead of both views, the one to get pushed out and the one to get pushed in, only the view that goes out "moves", the new view just sits at it's place.
In the the .m of the view to show:
- (void)viewDidLoad
{
[super viewDidLoad];
// set the views frame off the screen
self.view.frame = CGRectMake(320, 0, 320, 460);
}
In the method that actually does the transition:
-(void)showOverview:(UIViewController *)sender //sender = mapviewController
{
NSLog(#"overview");
// current view (frame) = mapviewCOntroller.view
CGRect outFrame = self.view.frame;
if (!self.overviewViewController) {
self.overviewViewController = [[UCOverviewViewController alloc] init];
self.overviewViewController.transitionDelegate = self;
// create a new View for the overview
[self.overviewViewController.view setCenter:self.view.center];
[self.view.window addSubview:self.overviewViewController.view];
[self.view.window bringSubviewToFront:self.mapViewController.view];
}
CGRect inFrame = self.overviewViewController.view.frame;
outFrame.origin.x = outFrame.origin.x-outFrame.size.width;
inFrame.origin.x = self.view.frame.origin.x;
[UIView animateWithDuration:0.5f animations: ^{
[self.view setFrame:outFrame];
}];
}
EDIT: this is my final code, at least the important part. Now, the view thats currently visible gets slider off screen at the same time the off-screen view gets slide in.
-(void)showOverview
{
if (!self.overviewViewController) {
NSLog(#"OverviewViewController created!");
self.overviewViewController = [[UCOverviewViewController alloc] init];
self.overviewViewController.transitionDelegate = self;
// add the subView
[self.view addSubview:self.overviewViewController.view];
[self.view sendSubviewToBack:self.overviewViewController.view];
}
CGRect outFrame = self.mapViewController.view.frame;
CGRect inFrame = self.overviewViewController.view.frame;
outFrame.origin.x -= outFrame.size.width;
inFrame.origin.x = self.view.frame.origin.x;
self.isOverviewViewVisible = YES;
[UIView animateWithDuration:0.5f animations: ^{
[self.mapViewController.view setFrame:outFrame];
[self.overviewViewController.view setFrame:inFrame];
}];
}
your problem is this line.
self.overviewView = self.overviewViewController.view;
You're overriding the view you created with the view you already have.
the following is not a great way to do it but it should work with what I think you have.
- (void)viewDidLoad {
self.overviewViewController.view.frame = CGRectMake(320, 0, 320, 460);
self.overviewViewController.view.backgroundColor = [UIColor blueColor];
}
Then you want another action to do the animations.
[UIView animateWithDuration:0.5f animations: ^{
self.overviewViewController.view.frame = CGRectMake(0,0,320,460);
}];
There are weird and incorrect things in your code that make it confusing to understand what is actually going on, but... forget about using the window anywhere. The only thing you need to worry about, is this. Say View A is your main view. View B is the view you want outside and to come in over A. Then, create B either from nib or manually, add it as a subview to view A, and before you enter the animation block to move it into place, make sure that the current frame is set to {ViewA.bounds.size.width, 0, ViewB.bounds.size.width, ViewB.bounds.size.height}. Assuming you want it to come in from the top right.
We have a UISplitViewController and under condition X, we need to display a UIPopover from one of the UIBarButtonItem of the Master view.
Supposedly, in order to have the frame/layout correct, we do this code from the Master view controller's viewDidLoad event. Somehow the first time the UISplitViewController is shown, the frame of the Master is 1024x724 whereas we'd expect it to be 320x724. As a result, the call to [UIPopover presentFromBarButtonItem:] uses a wrong referential and since it's a right BarButtonItem, the popover appears all the way to the right of the screen (at about x = 980px)
If we delay the displaying by a split second (via a Timer/delay, sooo dirty) then it's all fine.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect masterViewFrame = self.view.frame;
NSLog(#"Master View Frame: %#", NSStringFromCGRect(masterViewFrame));
if (someCondition) {
[self showPopover:self.theBarButton];
}
}
The NSLog here shows 1024x724 # 0x0
Thoughts?
You can do something like this:
//Check if you really are in a UISplitViewController
CGRect frame = self.view.frame; //this is the default value
if(self.splitViewController)
{
//you are trying to access the frame of this VC's view via the splitViewController
//this should return the correct size
frame = [[[self.splitViewController.viewControllers objectAtIndex:0] view] frame];
}
In the root view controller I add a subview:
d4sViewController = [[D4sViewController alloc] initWithNibName:#"D4sViewController" bundle:nil];
//----------------------------------------------------------------------
// Move your sub-view off the screen.
//----------------------------------------------------------------------
[self.view addSubview:d4sViewController.view];
CGRect rect = d4sViewController.view.frame;
CGPoint origin = CGPointMake(320, 0);
rect.origin = origin;
d4sViewController.view.frame = rect;
//----------------------------------------------------------------------
// Use a transform to slide it on.
//----------------------------------------------------------------------
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
d4sViewController.view.transform = CGAffineTransformMakeTranslation(-320, 0);
[UIView commitAnimations];
IN D4sViewController I add 2 subviews:
d4sMainList1ViewController = [[D4sMainList1ViewController alloc] initWithNibName:#"D4sMainList1ViewController" bundle:nil];
// Move your sub-view off the screen.
//----------------------------------------------------------------------
[self.view addSubview:d4sMainList1ViewController.view];
From this subview, d4sMainList1ViewController, I want to give a logout functionality and go back to root view controller by removing all subview.
-(IBAction)buttonLogoutClicked:(id)sender
{
//logout code i need to implement
}
Rootview => d4sViewController => d4sMainList1ViewController (from here i need to remove all subviews of root and go back to displaying just the root view.)
To remove any subview have the send the subview the removeFromSuperView message. See the UIView docs for details.
However, it looks like your stacking views when you don't need to. On a mobile screen a big pile of views is unusable. Look into using UINavigationController to managed a hierarchy of views/viewControllers for you.