My universal app uses NIBs for its settings screens. I'd like to use the same NIBs for both iPhone and iPad.
Thus on iPad, I use a UIPopoverController in the MainViewController and for settings, simply display the iPhone-sized NIBs, to show what is called the SettingsViewController. The popover is sized 320x460 points.
This causes a problem, because the iPhone version draws a number of things above the status bar programmatically, and for the iPad version this is not necessary. Current situation on iPad:
As you can see, there's a big empty space above the "Settings" title. Thus what I want, is to shift the view controller up about 20 points, inside the popover:
The popover is instantiated as follows in the MainViewController:
settingsPopoverController = [[UIPopoverController alloc] initWithContentViewController:popoverNavigationController];
settingsPopoverController.popoverContentSize = CGSizeMake(320, 460);
settingsPopoverController.delegate = self;
popoverNavigationController.navigationBarHidden = YES;
In the SettingsViewController, I set the frame as follows:
- (void)viewDidLoad
{
self.contentSizeForViewInPopover = CGSizeMake(320, 460);
}
And later in the SettingsViewController, I try to create an offset as follows:
- (void)viewWillLayoutSubviews
{
// shift it up
CGRect frame = self.view.frame;
frame.origin.y = -20;
[self.view setFrame:frame];
}
This does not shift the content up a bit. How to go about?
To clarify: I want to move down the "viewport" that the popover shows.
Try to:
myPopover.autoresizingMask=UIViewAutoresizingNone;
Or:
myPopover.autoresizingMask=UIViewAutoresizingFlexibleHeight || UIViewAutoresizingFlexibleWidth;
You can also try to put your code in -(void)viewDidLayoutSubviews method.
If this answers did not help, try set popoverLayoutMargins (property) instead of setFrame: for example:
popover.popoverLayoutMargins=UIEdgeInsetsMake (
CGFloat 50, //top
CGFloat 50,//left
CGFloat 50,//bottom
CGFloat 50//right
);
Related
https://github.com/EuanChan/XSlidableTabController
From there i download one demo sliding Tabbar but in this demo i want tabbar position little bit down because i want set one image, label and back button top of page but i can't able to find to set tabbar position ,
and i hide navigation bar its automatically on set top i want to little bit down
-(void)viewWillAppear:(BOOL)animated {
self.navigationController.navigationBarHidden = YES;
}
BUT i want to set image top of tabbar
please Help me , please share your valuable knowledge
Just change the baseY value in viewWillLayoutSubviews method in XSlidableTabController.m.
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
CGFloat baseY = 60.0f, width = self.view.frame.size.width;
CGRect rtTabMenu = CGRectMake(0, baseY, width, _tabHeight);
[_tabView setFrame:rtTabMenu];
baseY += rtTabMenu.size.height;
CGRect rtContent = CGRectMake(0, baseY, width, self.view.frame.size.height - baseY);
[_scrollView setFrame:rtContent];
CGSize szScrollContent = _scrollView.contentSize;
szScrollContent.height = rtContent.size.height;
[_scrollView setContentSize:szScrollContent];
}
Follow below steps.
open XSlidableTabController.m
go to - (void)viewWillLayoutSubviews method
add below code at last
// change 20 to any other what ever you want.
[_tabView setFrame:CGRectMake(0, 20, self.view.frame.size.width, _tabHeight)];
[self.view bringSubviewToFront:_tabView];
Maybe this will help you.
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.
I design the scrollview in interface builder like this
It looks good here. But unfortunately when I run it on emulator or device
it becomes
The content in scrollview is expand outside scrollview itself and even though outside UIView that contains this scrollView.
In my viewDidLoad (panel is the container of scrollView )
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat adjustPanelHeight = [PTTScreenScaleUtil getAdjustHeight:self.panel.frame.size.height];
CGRect panelRect = self.panel.frame;
panelRect.size.height = adjustPanelHeight;
self.panel.frame = panelRect;
UIImage *image = [UIImage imageNamed:#"panel-background"];
UIGraphicsBeginImageContext(self.panel.frame.size);
[image drawInRect:CGRectMake(0, 0, self.panel.frame.size.width, adjustPanelHeight)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.panel setBackgroundColor:[UIColor colorWithPatternImage:newImage]];
NSLog(#"scrollView Height : %f", self.scrollView.frame.size.height);
NSLog(#"scrollView contentSize Height : %f", self.scrollView.contentSize.height);
// CGRect scrollViewRect = self.scrollView.frame;
// CGRect scrollViewContentRect = self.scrollView.frame;
// NSLog(#"ScrollView Height Before : %f , After : %f", self.scrollView.frame.size.height, [PTTScreenScaleUtil getAdjustHeight:self.scrollView.frame.size.height]);
// scrollViewRect.size.width = 280;
// scrollViewRect.size.height = [PTTScreenScaleUtil getAdjustHeight:270];
// self.scrollView.frame = scrollViewRect;
// [self.detailsLabel sizeToFit];
UIView *view = [[self.scrollView subviews] objectAtIndex:0];
// [view sizeToFit];
// [self.scrollView setContentMode:UIViewContentModeScaleAspectFit];
// NSLog(#"ContentSize Height : %f", view.frame.size.height);
// scrollViewContentRect.size.height = view.frame.size.height;
NSLog(#"Bounds : %f", view.bounds.size.height);
self.scrollView.frame = CGRectMake(10, 10, 280, 270);
self.scrollView.contentSize = CGSizeMake(280, 500);
NSLog(#"Frame Height %f", self.scrollView.frame.size.height);
//[self.scrollView setContentSize: CGSizeMake(280, 1000)];
CGRect termBtnRect = self.termBtn.frame;
CGRect mailBtnRect = self.mailBtn.frame;
CGRect twitterBtnRect = self.twitterBtn.frame;
CGRect fbBtnRect = self.fbBtn.frame;
termBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
mailBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
twitterBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
fbBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
self.termBtn.frame = termBtnRect;
self.mailBtn.frame = mailBtnRect;
self.twitterBtn.frame = twitterBtnRect;
self.fbBtn.frame = fbBtnRect;
}
All the log return 270.0
PS. the scroll bar is correct even though the content goes outside but the scroll bar is working correctly (stay in the scrollview's frame as arrange in interface builder)
I have no idea how can I solve this.
Anyone help me please.
Thanks you.
Solve it by creating new view controller in interface builder and redo the same process with careful and bingo. It works.
When I compare both two view controller I realise that the wrong one UIScrollView Clip Subviews is unchecked. When check it the problem solve.
I just struggled with this for an hour and had a head smack moment.
In my case, I had a UIView on the scene in the Storyboard. At some point I decided I needed it to be a UIScrollView instead (as opposed to the original plan which was to embed the UIScrollView in a UIView)
I went ahead and changed the class on the UIView to UIScrollView. IB changed it to Scroll View in the Document Outline, I figure I'm good, right?
And then I see the behavior you describe.
At some point it hits me that this isn't sufficient. Apparently adding a UIScrollView via IB does some things differently than adding a UIView and just changing class isn't enough. And this is probably the reason re-doing it from scratch fixed it for you.
So for anyone who runs into this in the future, make sure you added the UIScrollView via IB instead of a UIView
I was having the same problem as described in this post. I tried multiple combinations of solutions that did not work, including:
putting the scroll view inside a view with Clip To Bounds = YES
putting a view inside the scroll view with Clip To Bounds = YES, that then contained my child view
putting a Container View inside the scroll view, and then embedding my subview
rebuilding the Interface Builder files completely
every combination of autosizing mask options systematcially for both the scroll view and container view
clip to bounds enabled or disabled for every single element systematically
The child view in question had previously worked inside a scroll view, but wouldn't in this one case where the content blew outside the bounds of the scroll view.
In the end, I implemented the solution in code as I could find no way to get Interface Builder to co-operate:
// There are two scroll areas on the screen, the left view and the right view.
// We want the right view to contain a scrollable area with another child view controller
// we designed in Interface Builder.
// create a scroll view to fill the right view with a scrollable area
CGSize rightFrameSize = self.rightView.bounds.size;
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake (0, 0, rightFrameSize.width, rightFrameSize.height)];
scrollView.contentSize = CGSizeMake(640, 1352);
[self.rightView addSubview:scrollView];
// now create our child view controller from Interface Builder and add it to the scroll view
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"CustomerAddress" bundle:[NSBundle mainBundle]];
detailsView = [sb instantiateViewControllerWithIdentifier:#"CustomerDetailsView"];
detailsView.delegate = self;
detailsView.customer = _customer;
[scrollView addSubview:detailsView.view];
You could of course get the scrollView.contentSize from the child view controller you constructed in Interface Builder using scrollView.contentSize = detailsView.view.frame.size.
I have a love/hate relationship with Interface Builder... most days I love it, but some days we argue and I wish we'd never met... :)
only make cliptobound=YES in storyboard if you changed UIView to UIScrollView
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 am writing an iPad app that needs to know the usable area of the view for drawing purposes. The view is added into a Navigation controller, so I have the status bar plus the navigation controller both taking up a certain number of pixels. My app happens to be in landscape mode, although I don't think that's relevant.
I am able to get the correct view size AFTER rotation using didRotateFromInterfaceOrientation. But I can't figure out how to do it without the screen being rotated.
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[self.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
NSLog(#"drfi %d %d", (int)self.view.frame.size.width, (int)self.view.frame.size.height);
}
^^ that works after rotation. Not before. Can't figure out how to get accurate numbers. And I REALLY don't want to hard wire this.
I will also need this function to be device independent -- it should work on the NEW iPad as well as the older iPad resolutions. I can handle the scaling issues once I know the exact usable area. Why is this so hard? Help!!
I don't think you need to specify your frame's view within the didRotateFromInterfaceOrientation what i will suggest instead is setting some properties to your view autoresizing mask so that it automatically resize itself according to your view orientation.
By setting this for example to your view when your view is loaded (viewDidLoad method):
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
you specify that your view will change its width and height automatically and can get the right values you need to get from there.
You should read this: http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1
for a better understanding of views in iOS
EDIT
Also you probably want to spot what is the orientation of your device which can be accomplish with [[UIApplication sharedApplication] statusBarOrientation];
Your application looks like: there is a start up view, then in this view you will load and add a main view into window, right? Then you should do as below in your main view:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
CGRect frame = self.view.frame;
frame.origin.y = frame.origin.y + 20.0;
self.view.frame = frame;
}
return self;
}
Try this.
CGRect frame = [UIScreen mainScreen].bounds;
CGRect navFrame = [[self.navigationController navigationBar] frame];
/* navFrame.origin.y is the status bar's height and navFrame.size.height is navigation bar's height.
So you can get usable view frame like this */
frame.size.height -= navFrame.origin.y + navFrame.size.height;
You can get this dynamically by combining an instance method with a category method:
Instance method:
This assumes that your view controller (self) is embedded within a navigation controller.
-(int)getUsableFrameHeight {
// get the current frame height not including the navigationBar or statusBar
return [MenuViewController screenHeight] - [self.navigationController navigationBar].frame.size.height;
}
Class category method:
+(CGFloat)screenHeight {
CGFloat screenHeight;
// it is important to do this after presentModalViewController:animated:
if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait ||
[[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown){
screenHeight = [UIScreen mainScreen].applicationFrame.size.height;
} else {
screenHeight = [UIScreen mainScreen].applicationFrame.size.width;
}
return screenHeight;
}
The above will consistently give you the usable frame height after the status bar and navigation bar have been removed, in both portrait and landscape.
Note: the class method will automatically deduct the 20 pt for the status bar - then we just subtract the navigation header variable height (32 pt for landscape, 44 pt for portrait).