Here's the situation: I have a VC that has a Custom UIView inside it. This Custom UIView has an .xib file, which contains 2 UIImageViews. I'm trying to get those 2 UIImageViews to scale to same size across different screen size by using AutoLayout. However, when I launch my app the images in my Custom UIView go out of bounds of the Custom UIView's super View (which is the VC) container size. Please, help. Here are some pictures to explain the issue in better detail.
My code in Custom UIView:
#implementation CustomTwoImagesSelectedUIView
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self load];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self load];
}
return self;
}
- (void)load {
[[NSBundle mainBundle] loadNibNamed:#"CustomTwoImagesSelectedUIView" owner:self options:nil];
self.lastImageView.layer.cornerRadius = 5.0f;
self.lastImageView.clipsToBounds = YES;
self.secondToLastImageView.layer.cornerRadius = 5.0f;
self.secondToLastImageView.clipsToBounds = YES;
[self addSubview:self.twoImagesSelectedView];
}
You have set the cliptobounds property of the imageviews but the bound of imageviews itself is not set properly I guess. You need to carefully set layout constraints in the .xib file for imageviews. Also. When you add the customImageViews to some view controller, or superview. You also need to set the layout constraints for customImageViews with respect to its superview.
I have try AutoLayout in the custom UIView, but it can not work too. I think it is a bug from Xcode, and I finally found this article:Create an IBDesignable UIView subclass with code from an XIB file in Xcode 6
In the article, I found it use autoresizingMask instead of AutoLayout. It is a good way to fix the UI display problem. I hope it can helps you.
- (void)load {
[[NSBundle mainBundle] loadNibNamed:#"CustomTwoImagesSelectedUIView" owner:self options:nil];
self.lastImageView.layer.cornerRadius = 5.0f;
self.lastImageView.clipsToBounds = YES;
self.secondToLastImageView.layer.cornerRadius = 5.0f;
self.secondToLastImageView.clipsToBounds = YES;
[self addSubview:self.twoImagesSelectedView];
self.twoImagesSelectedView.frame = self.bounds;
self.twoImagesSelectedView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
Related
I have a custom UIView that has 2 UILabel's which I have designed in the XIB. Have set the correct constraints to the sub items making them right aligned etc. In the XIB, my desgin was based on the assumption that screen width is 200 and constraints of the 2 labels are set to their superview accordingly.
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"MyCustomView" owner:self options:nil];
[self addSubview:self.view];
//_intrinsicContentSize = self.bounds.size; // tried to return this as well
}
return self;
}
Now I programmatically alloc this view and and add it as subview to my view controller. If I change the frame of the view to say 300, the sub view frame gets changed to 300 but the 2 labels which have constraints follow a width of 200 only.
vewOneTouch = [[OneTouchView alloc] initWithFrame:CGRectMake(0, CGRectGetMinY(vewBottom.frame)-50, CGRectGetWidth(scwBaseView.frame), 50)];
[scwBaseView addSubview:vewOneTouch];
When the custom view frame is changed, why are the constraints not kicking in and changing the layout of all the items in the subview?
The white area is the yellow view in the Xib, have changed the color programmatically.
I created a UIView in a separate subclass of UIView and with an xib.
I have a UIViewController with a UIView in storyboard and I want to set custom UIView to this UIView.
I modified class name in storyboard UIView to the class name of custom UIView. I am getting the UIView on the result but with the frame size of custom UIView. I added correct constraints in the custom xib. and some touch gestures not working as desired because of the wrong frame etc.
Please suggest me if anything wrong I did.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Load the UIView from Interface Builder
[[NSBundle mainBundle] loadNibNamed:#"TMPhotoEdit" owner:self options:nil];
// Add UIView to current UIView object.
[self addSubview:self.view];
}
return self;
}
self.view is the same view object I created a variable for it.
I want the frame to set as same as the one i am using in storyboard.
Solution to get it work using code also helps me a lot. I mean, without IBOutlet in storyboard, just adding this UIView with some frame set to it.
If I call initWithFrame, I can't set the xib like what I am doing with initWithCoder above and initWithCoder is not being called if I use initWithFrame in code.
Assuming you have an instance of the view you want to resemble in size
self.view.frame = CGRectMake(otherView.frame.x, otherView.frame.y, otherView.frame.width, otherView.frame.height);
Actually what you are doing is not correct but anyway you should load the custom view nib like this
self.view = [[NSBundle mainBundle] loadNibNamed:#"TMPhotoEdit" owner:self options:nil][0];
Again this is not correct, why do you need it anyway? but it shall solve your nib loading issue.
I've created a custom UITableViewCell class where I've created a label and imageview, and connected them via storyboard. What's the best place to apply corner radius, border width, etc. to the imageView?
I tried the following in the custom class' init method but it didn't quite work:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
productImageView.layer.borderColor = (__bridge CGColorRef)([UIColor whiteColor]);
productImageView.layer.borderWidth = 3.0f;
productImageView.layer.cornerRadius = 36.0f;
}
return self;
}
What's wrong here?
Are you doing in this in the UITableViewCell subclass? If so you need add this in awakeFromNib or prepareForReuse. When init is called the image view doesn't exist yet. Also do self.productImageView.clipsToBounds = YES;
I've defined a custom view in a NIB file and would like to instantiate a copy in a StoryBoard but I'm having issues with autolayout.
In a simple example, the custom view has single label with a fixed size and centered both vertically and horizontally, all using autolayout.
The file owner is set to my class, it has an outlet to the top view. In the custom view implementation I do:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self)
{
[[NSBundle mainBundle] loadNibNamed:#"FMCompassView" owner:self options:nil];
[self addSubview:self.topView];
}
return self;
}
Now, in my storyboard, I add a UIView, set it's class to my custom class and layout it out sized and centered on my page, again using autolayout.
And my widget is positioned and size properly but it's content is not resized as illustrated below:
I tried adding more constraints after loading from the NIB, something along the lines of:
UIView* subV = self.topView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(subV);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[subV]|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:viewsDictionary]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[subV]|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:viewsDictionary]];
But this causes invalid layout constraints.
Any ideas on how to get this to work?
Cheers!
The view created from loading the NIB needs to be told not to convert auto resizing mask to constraints, EVEN if the content of the NIB is actually created with autolayout enabled.
So after loading the NIB and before adding it's top view to the custom view, I need to call:
[self.topView setTranslatesAutoresizingMaskIntoConstraints:NO];
In addition to what mkrus suggests above, this is what my initWithCoder: looks like for the custom class nib:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
NSString *className = NSStringFromClass([self class]);
self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.view];
[self.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
}
return self;
}
The reason for this initWithCoder: approach is explained here.
I've added the Masonry auto layout constraints so that it works with the constraints defined in interface builder.
Disabling "Use Size Classes" worked for me. I didn't have to do what mkrus has mentioned.
I don't know if this is specific to UITableViewCells but rather general for UIViews (as i believe) but i noticed the problem with a cell.
As mentioned, I have a custom UITableViewCell subclass which loads itself from a xib when it gets initialized with an designated init:
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:nil options:nil];
self = nib[0];
if (self) {
// Initialization code
_reuseIdentifier = reuseIdentifier;
}
return self;
}
It has a UILabel as an outlet and I set some properties of it in the awakeFromNib method:
- (void)awakeFromNib{
[super awakeFromNib];
self.labelLeft.textColor = [UIColor grayColor];
self.labelLeft.font = [UIFont boldSystemFontOfSize:15.0f];
}
The point is, that the label doesn't keep the textColor nor the font and I don't understand why.
awakeFromNib gets called and the outlet is connected right, since i can set the text.
I can make it work by settings those properties after I set his text in the UITableViewDataSource but I don't feel it's the right way and I want to understand why this doesn't work.
Question:
Why doesn't it keep the Font and Textcolor and what can I do to make it work the right way?
I have the same issue with all my labels loaded from .Nib's. Then I found that the problem was in UIAppearance. I have the following line in my AppDelegate:
+ (void)styleApplication {
[[UILabel appearance] setFont:[MGStylesheet defaultLightFontOfSize:17]];
}
This method update all fonts in my application, and all works fine, until I start loading my UIView's from .Nib. When I removed this, everything start working as expected.
Set the attributes of the label in the nib-file. If you split your interface configuration to different places this causes just trubble.
If you don't want to do that move the configuration of the label into viewDidLoad: