Hi I have an simple application where I am supposed to change the frame of a UIButton based on its super view and based on its frame the title size should get change.
I am using Autolayout to change the frame of that UIButton. But not getting any idea how to change the font size of that UIButton.
Here is the code I have tried so far.
1. [self.cButton sizeToFit] ;
2. [self.cButton.titleLabel sizeToFit] ;
3. self.cButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter ;
4. self.cButton.titleLabel.adjustsFontSizeToFitWidth = YES;
5. self.cButton.titleLabel.textAlignment = NSTextAlignmentCenter ;
6. self.cButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
Like I have tried many things.
Can anyone tell me if I am missing something here and I am doing something wrong.
I was having this issue and it turned out that I was overriding layoutSubviews and had forgotten to call [super layoutSubviews].
Related
I just updated my Xcode ver from 7.3 to 8.0 and some buttons borders disappeared.
The code looks fine, so I really don't know what happened to the layers.
btw - in some other controllers I can see the layers borders.
self.button.layer.borderColor = borderColor.CGColor;
self.button.layer.borderWidth = 2;
self.button.layer.cornerRadius = CGRectGetHeight(self.button.frame) / 2;
before: (The image is only for example - the borders looks different at real time)
now:
The reason is that XCode 8 introduces a new way to zoom in Storyboards.
Before XCode 8, in the view controller life cycle, frames were not known in viewDidLoad (or in properties didSet). You had to wait until viewDidLayoutSubviews (which is when Autolayout had finished applying the constraints to determine the frames of every subview in the main view.
But bounds were accessible before that: they were just set to the size of the IBOutlet in the storyboard.
In XCode 8, things are different : due to their new zooming system, even the boundsare not correct before ViewDidLayoutSubviews (they may exist but with dummy values like 1000 x 1000).
In conclusion :
you can use such things as cornerRadius in viewDidLoad or in the IBOutlet
didSet, as long as you use a fixed value
if you need to define your cornerRadius based on bounds, then do so in viewDidLayoutSubviews, or use NSLayoutConstraints (their value is fixed and known from Autolayout)
if you need to use cornerRadius in views (like UITableViewCell or UICollectionViewCell subclasses), then you can either do so in layoutSubviews (but then you need to give either a fixed value or a NSLayoutConstraint constant to cornerRadius), or in awakeFromNib(in that case, just add self.layoutIfNeeded before doing anything frame- or boounds-related, in order to force the cell to recalculate its subviews' frame).
I think problem in it:
CGRectGetHeight(self.button.frame) / 2;
When you set corner i think height button don't have value or value to larger border will don't show. You can try change it to
self.button.layer.cornerRadius = 15;
If work, I think you can check your logic and set it when height button get right value.
Try this and check:
#import <QuartzCore/QuartzCore.h>
self.button.layer.borderColor = [UIColor whiteColor].CGColor;
self.button.layer.borderWidth = 2;
self.button.layer.cornerRadius = 5; // Change this value on your requirement
self.button.clipsToBounds = YES;
To force view frame to be calculated, you can try with layoutIfNeeded.
For example for a label in a UITableViewCell :
override func awakeFromNib() {
super.awakeFromNib()
self.layoutIfNeeded()
self.qualityIndexLabel.makeRound()
}
use dispatch_after
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.button.layer.borderColor = borderColor.CGColor;
self.button.layer.borderWidth = 2;
self.button.layer.cornerRadius = CGRectGetHeight(self.button.frame) / 2; });
the RoundedRect is deprecated use UIButtonTypeSystem instead.
see https://developer.apple.com/reference/uikit/uibutton?language=objc for more information.
I have been using a method of resizing my UIButtons that is depreciated, and not very robust. For that and also other reasons, I want to get sizeThatFits to work for UIButtons. From what I've read online, I'm not sure if it should work (seems like it is working for some, but not others, the difference maybe between the style, I'm using custom).
Here is my simple test code to recreate the issue (I just put this in viewDidLoad to test, but shouldn't matter, and my real code is part of a large project):
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:#"This is a test with a long title that will need to word wrap to more than a single line when displayed on my tiny iPod in portrait view." forState:UIControlStateNormal];
btn.titleLabel.lineBreakMode = UILineBreakModeWordWrap; // depreciated - but nothing to replace it?
CGRect r = btn.frame;
r.origin.x = 0;
r.origin.y = 0;
r.size.width = 320;
r.size.height = [btn.titleLabel.text sizeWithFont:btn.titleLabel.font constrainedToSize:CGSizeMake(r.size.width,100000) lineBreakMode:btn.titleLabel.lineBreakMode].height; // Returns approx 86 and changes correctly if I change the title text
r.size.height = [btn sizeThatFits:CGSizeMake(r.size.width,CGFLOAT_MAX)].height; // returns 34 no matter what
btn.frame = r;
The sizeWithFont line is what I have been doing, and it works, but it isn't asking the actual control for the size, so not really safe and has been depreciated also. The sizeThatFits line is what I would like to get working, but it always returns 34 no matter what (probably the recommended/default height of a button).
I've been using the same sizeWithFont to resize UILabels and some other controls as well. I've updated them to use sizeThatFits and they work great, just UIButton isn't working the same as the others. I'm hoping there is a simple fix, like setting a property of the UIButton, to get this working?
My app only needs to support iOS 8+, not older versions.
Update: Based on the comments here How do I resize a UIButton to fit the text without it going wider than the screen? and the accepted answer, it seems like we might be stuck with sizeWithFont or other sub-par solutions... dang.
I fixed it using UIButton titleLabel instead of UIButton.
button.titleLabel?.sizeThatFits(labelFitSize)
Instead of
button.sizeThatFits(labelFitSize)
Good news is that it works, bad news you will need to handle yourself if the button as contentInsets or images...
I have an app where I am simultaneously animating the position and size of a UIView with an image by calling setFrame inside a animateWithDuration, thusly:
UIImage *image = [UIImage imageNamed: imageName];
[_faceView setImage: image];
[_faceView setFrame: CGRectMake(-40.0, 0.0, 40.0, 40.0)];
[UIView animateWithDuration:0.5 animations:^{
[_faceView setFrame: CGRectMake(80.0, 140.0, 160, 160)];
}
completion:^(BOOL finished) {}
When compiled in Xcode 5, and running in either iOS 7 or iOS 8, I have obtained the correct behaviour using the above methodology.
Now, compiling in Xcode 6 (and hence against SDK 8.0, which I assume is the defining difference?), and running in either iOS 7 or iOS 8, this code does not achieve the correct result: what appears to happen is that the image is animated to its "natural" size rather than to that specified in the CGRect.
So: (a) does anyone know why this might be? and (b) either way, is the basic problem that I'm doing something wrong? -- is there a more "correct" way to achieve an animation of position/size of an image in a UIView that will achieve the desired result?
By default in Xcode6 even if you don't have any constraints associated with a view - IB will create default ones. That's why after setting the frame view is getting repositioned to the original frame.
You can add line
_faceView.translatesAutoresizingMaskIntoConstraints = YES;
And this essentially will break existing constraints, but you will get proper animation.
However I would suggest to re-do this animation to use auto-layout constraints and not use strict frame setting.
I think you can try to begin to use Autolayout to make animation. As I remembered, it has been recommended in the WWDC session.
As a simplest example, if you want to move a view right 40 point in animation , you can add a constraint to the left, use Interface Builder to link it to a IBOutlet like
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftConstraint;
And the animation code like follow:
- (IBAction)animatinoButtonPressed:(id)sender {
self.leftConstraint.constant = self. leftConstraint.constant + 40.f;
[UIView animateWithDuration:3.f animations:^{
[self.view layoutIfNeeded];
}];
}
The method layoutIfNeeded will force the view to rearrange the subviews immediately, which move the target view and make animation.
I think you can create suitable constraints in your case and make correct animation as well.
In iOS 6 and earlier a uitableviewcell's imageView was positioned all the way over to the left with a 0 offset. In iOS 7 though this has been changed and there is now a 15 point space now. I would like to position the imageView like it is in iOS 6. I'm already subclassing the uitableviewcell with AKHighlightableAttributedCell to deal with attributed text not being highlighted. So based on some searching I added:
- (void) layoutSubviews
{
[super layoutSubviews];
// Makes imageView get placed in the corner
self.imageView.frame = CGRectMake( 0, 0, 80, 80 );
}
The issue is everything else still doesn't get repositioned and so I'm thinking there must be a better way to do this. I'd read some people mentioning using a negative offset to move everything over but I wasn't sure how this would work with constraints as it needs to scale properly for each orientation. Is there an easier solution to this that I'm missing? Thank you.
It appears I was doing it the correct way. The missing piece regarding the divider between fields was setting the inset on iOS 7. You can do this in the viewdidload or viewwillload and set self.tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
You will need to add a check if running iOS 7 or newer as this is a new property I believe. A better option might be setting it in the storyboard by selecting the table view and then setting separator insets from default to custom.
Here is the layoutSubviews method that repositions imageView and textLabel. If you have a description add that as well.
- (void) layoutSubviews
{
[super layoutSubviews];
// Makes imageView get placed in the corner
self.imageView.frame = CGRectMake( 0, 0, 80, 80 );
// Get textlabel frame
//self.textLabel.backgroundColor = [UIColor blackColor];
CGRect textlabelFrame = self.textLabel.frame;
// Figure out new width
textlabelFrame.size.width = textlabelFrame.size.width + textlabelFrame.origin.x - 90;
// Change origin to what we want
textlabelFrame.origin.x = 90;
// Assign the the new frame to textLabel
self.textLabel.frame = textlabelFrame;
}
I must do something wrong, but dont know what..
I try to add a subView with this code:
subMenuView = [[UISubMenuViewMainController alloc] init];
[subMenuView.view setFrame:CGRectMake(10,0,990,100)];
subMenuView.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:subMenuView.view];
I want my view to be at (10,0) and have 990/100 in width/height
but i dont get the expected result
Let me if I m wrong, If I want a 10x10 square view at the center i have to add the following line:
[subMenuView.view setFrame:CGRectMake(512,384,10,10)];
That s not what I get, the position is correct, but the width/height are wrong, any ideas?
if you use autolayout,the call setFrame have no use,try call setTranslatesAutoresizingMaskIntoConstraints before setFrame
problem fixed by setting
self.view.autoresizesSubviews = NO;
The code is a little unconventional, but I'll hazard a guess it's because you are setting the view's frame before you add it as a subview. Hence the subview's position probably gets changed by layoutSubviews before you see it.
So try putting the second line of code last and see if that does the trick.
Try using floats instead of ints:
[subMenuView.view setFrame:CGRectMake(10,0,990,100)];
to:
[subMenuView.view setFrame:CGRectMake(10.0f,0.0f,990.0f,100.0f)];