I am adding a custom view (MainComponentView) to user controller. Now in MainComponentView I am also adding a custom view (FirstPartView) and FirstPartView's height should be less than MainComponentView's height. My problem is that when I give less height to MainComponentView than FirstPartView height, it is still showing me the whole view of FirstPartView.
// MainComponentView
self.aComponent = [[MainComponentView alloc] initWithFrame:CGRectMake(212, 0, 600, 550)
withStartDate:startDate
endDate:endDate];
[self.view addSubview:self.aComponent];
and to add the custom view to MainComponentView :
self.aFirPartView = [[FirPartView alloc] initWithFrame:CGRectMake(0, self.frame.origin.y, self.frame.size.width, HEIGHT_OF_COMPONENT1) withStartDate:startDate endDate:endDate];
[self addSubview:self.aFirPartView];`
Try:
self.aComponent.clipsToBounds = YES;
To tell the view that it should not draw any part of any subview which is outside of its frame.
Subview coordinates are relative to the superview, not to the window, so when you do this:
self.aFirPartView = [[FirPartView alloc] initWithFrame:CGRectMake(0, self.frame.origin.y, self.frame.size.width, HEIGHT_OF_COMPONENT1) withStartDate:startDate endDate:endDate];
[self addSubview:self.aFirPartView];`
the view you create is offset downwards by the distance of the MainComponentView from the top of the screen.
Try using this frame value instead:
CGRectMake(0, 0, self.bounds.size.width, HEIGHT_OF_COMPONENT1)
This will position the subview at the top left corner of your MainComponentView, with the specified width and height.
Related
I wrote a small sample program to better understand the meaning of UIViews property bounds. The program has one UIViewController. I put a custom view inside it's root view, and override drawRect: on that custom view. And I add a button to "Change Bounds". Here's the screenshot.
Here's drawRect:. It draws a green dot at (x=50,y=60), and a gray rectangle over self.bounds.
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(c, 0, 1, 0, 0.5); // green
CGContextFillRect(c, CGRectMake(50, 60, 10, 10));
CGContextSetRGBStrokeColor(c, 0, 0, 0, 0.5); // gray
CGContextSetLineWidth(c, 10.0);
CGContextStrokeRect(c, self.bounds);
Now I click the button which adds (20,40) to the bounds.origin of the custom view, like this:
CGRect bs = _testView1.bounds;
bs.origin.x += 20.0;
bs.origin.y += 40.0;
_testView1.bounds = bs;
[_testView1 setNeedsDisplay];
Now, here's what the screen looks like:
You see the view itself has not moved on screen, but the green dot has moved. I think to myself: I get it, the bounds changes the portion of the view`s world that is mapped to it's area of the screen.
Next expermient: I'll add a subview. In awakeFromNib I add a label, as a child of the custom view, like so:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 100, 100)];
label.text = #"Test";
[self addSubview:label];
At first, the screen is as expected:
But when I change the bounds, as before, things move differently.
It does not translate the view's coordinate system, like before. Why is that? Does adding to self.subviews change the meaning of self.bounds? If so, where is that documented?
I have a view containing a UITableView. On view did load, I set the table's tableFooterView to be a view I create by hand (a UIView containing a button). When the view appears, I adjust the frame of the tableFooterView:
CGRect tableFrame = self.myTableView.frame;
CGRect originalFrame = self.tableFooter.frame;
CGSize imageSize = CGSizeMake(40.0f, 40.0f);
CGRect footerFrame = CGRectMake(originalFrame.origin.x, originalFrame.origin.y, tableFrame.size.width, imageSize.height);
self.tableFooter.frame = footerFrame;
CGRect nextFrame = CGRectMake((footerFrame.size.width - imageSize.width) / 2.0f, 0.0f, imageSize.width, imageSize.height);
self.tableFooterButton.frame = nextFrame;
On iOS7, this works the way I want -- when I scroll to the bottom of the table, I see my footer view. On iOS6, when I scroll to the bottom of the table, the footer view is still offscreen (I can pull the scroll view and see it, but it resets offscreen when I release).
What should I do differently?
After change the frame of table footer, try this:
self.myTableView.tableFooterView = nil ;
self.myTableView.tableFooterView = self.tableFooter ;
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
I have created mainView objcet of UIView and added one subview on it. I applied transform on mainView for reducing frame size. But frame of subview of mainView was not reduced. How to reduce the size of this subview.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CGFloat widthM=1200.0;
CGFloat heightM=1800.0;
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, widthM, heightM)];
mainView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"te.png"]];
[self.view addSubview:mainView];
CGFloat yourDesiredWidth = 250.0;
CGFloat yourDesiredHeight = yourDesiredWidth *heightM/widthM;
CGAffineTransform scalingTransform;
scalingTransform = CGAffineTransformMakeScale(yourDesiredWidth/mainView.frame.size.width, yourDesiredHeight/mainView.frame.size.height);
mainView.transform = scalingTransform;
mainView.center = self.view.center;
NSLog(#"mainView:%#",mainView);
UIView *subMainView= [[UIView alloc] initWithFrame:CGRectMake(100, 100, 1000, 1200)];
subMainView.backgroundColor = [UIColor redColor];
[mainView addSubview:subMainView];
NSLog(#"subMainView:%#",subMainView);
}
NSlog of these views:
mainView:<UIView: 0x8878490; frame = (35 62.5; 250 375); transform = [0.208333, 0, 0, 0.208333, 0, 0]; layer = <CALayer: 0x8879140>>
subMainView:<UIView: 0x887b8c0; frame = (100 100; 1000 1200); layer = <CALayer: 0x887c160>>
Here the width of mainView is 250, the width of subview is 1000. but when i get the output in simulator, subview is occupied correctly, but it's not cross the mainView. How it is possible? How to get frame of subview with respect mainView frame after transformation?
What you're seeing is expected behavior. The frame of an UIView is relative to its parent, so it doesn't change when you apply a transformation to its superview. While the view will appear 'distorted' too, the frame won't reflect the changes since it's still at exact the same position relative to its parent.
However, I assume you would like to get the frame of the view relative to the topmost UIView. In that case UIKit offers these functions:
– [UIView convertPoint:toView:]
– [UIView convertPoint:fromView:]
– [UIView convertRect:toView:]
– [UIView convertRect:fromView:]
I applied these to your example:
CGRect frame = [[self view] convertRect:[subMainView frame] fromView:mainView];
NSLog(#"subMainView:%#", NSStringFromCGRect(frame));
And this is the output:
subMainView:{{55.8333, 83.3333}, {208.333, 250}}
In addition to s1m0n answer, the beautiful thing about applying a transform matrix to your view, is that you can keep reasoning in terms of its original coordinate system (in your case, you can handle subMainView using the non-transformed coordinate system, which is why, even though subMainView's frame is bigger than mainView's transformed frame, it still doesn't cross the parent view, as it gets automatically transformed). This means that when you have a transformed parent view (for example rotated and scaled) and you want to add a subview in a particular point relative to this parent view, you don't have to first keep track of the previous transformations in order to do so.
If you really are interested in knowing the subview's frame in terms of the transformed coordinate system, it will be enough to apply the same transformation to the subview's rectangle with:
CGRect transformedFrame = CGRectApplyAffineTransform(subMainView.frame, mainView.transform);
If you then NSLog this CGRect, you will obtain:
Transformed frame: {{20.8333, 20.8333}, {208.333, 250}}
Which, I believe, are the values that you were looking for. I hope this answers your question!
I am an iOS newbie, so please bear with me. I have a blank page with a button centered in it. I want to add another button to the view, just below the centered button. How would I do that? I have added the first button like this -
float x=60, y=200, dy=50;
CGRect frame = CGRectMake(x, y, 200, dy);
UIButton *inboxButton = [[[UIButton alloc] initWithFrame:frame]autorelease];
inboxButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
inboxButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
....
[theView addSubview:inboxButton];
Just calculate the second frame based on the first
CGRect secondFrame = CGRectMake(CGRectGetMinX(frame),
CGRectGetMaxY(frame) + 8.0, // some y padding
CGRectGetWidth(frame),
CGRectGetHeight(frame));
You are not saying if you need that second one centered by itself - I am assuming that you just want it below, left-aligned with the first one:
UIButton *outboxButton = [[[UIButton alloc] initWithFrame:CGRectMake(frame.x,
frame.y + dy + 10.0f,
frame.width,
frame.height)] autorelease];
[theView addSubview:outboxButton];
What I am doing here is simply reusing the horizontal coordinate from the first button. For the vertical coordinate, I am using the original coordinate and add the height and an offset (10.0f) to it. Both, the width and the height are taken from the first button, assuming that they should match in size.
As you will see, there is no way to have this calculation done implicitly, which I assume you actually wanted to find out - that is, by simply supplying some ordering arguments.