I am having huge problems with learning autolayout especially when integrating xibs and uiscrollviews. In an effort to simplify my problem, I started a new project with a single view tied to a storyboard. I then subclassed UIView (Diptic) and created a xib file for it. My storyboard is not using autolayout, but my Diptic xib is. Right now I want to have a horizontal scrollView with a few Diptic instances layed out across it. But I am only ever getting the first diptic instance to show up, because the frame isn't being initialized correctly.
In my ViewController.m's viewDidLoad:
self.scrollView.contentSize = CGSizeMake((self.view.frame.size.width+10)*5, self.view.frame.size.height);
for (int i = 0; i < 5; i++){
int x = i*(self.view.frame.size.width+10);
Diptic *diptic = [[Diptic alloc] initWithFrame:CGRectMake(x, 50, self.view.frame.size.width, self.view.frame.size.height-100)];
[self.scrollView addSubview:diptic];
[array addObject:diptic];
UIView *greenBox = [[UIView alloc] initWithFrame:CGRectMake(x, 5, 40, 40)];
greenBox.backgroundColor = [UIColor greenColor];
[self.scrollView addSubview:greenBox];
}
Diptic.m
#import "Diptic.h"
#implementation Diptic
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"Diptic" owner:nil options:nil];
self = [views objectAtIndex:0];
self.label.text = #"WOOT";
self.backgroundColor = [UIColor redColor];
}
return self;
}
#end
If I set the frame after I add it to the view it seems to work, but why can't I set the frame with initWithFrame?
The problem here is that you assign the frame to a view that is created with a call to [super initWithFrame:frame]. When the NIB is loaded in - (id)initWithFrame:(CGRect)frame, self is replaced with a view from [views objectAtIndex:0] and the frame for this view is never set. Instead, eliminate the call to super and load the view from the NIB instead:
#import "Diptic.h"
#implementation Diptic
- (id)initWithFrame:(CGRect)frame
{
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"Diptic" owner:nil options:nil];
self = [views objectAtIndex:0];
if (self) {
self.frame = frame;
self.label.text = #"WOOT";
self.backgroundColor = [UIColor redColor];
}
return self;
}
#end
When init a view/controller from storyboard or from xib, the init method is
- (id)initWithCoder:(NSCoder *)decoder
try to do other things in this method
Related
I have a custom view called TimeTooltipView. Here is the code:
TimeTooltipView.h
#import <UIKit/UIKit.h>
#interface TimeTooltipView : UIView
#property (weak, nonatomic) IBOutlet UILabel *timeLabel;
-(void)configureView;
#end
TimeTooltipView.m
#import "TimeTooltipView.h"
#implementation TimeTooltipView
-(id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"TimeTooltipView" owner:self options:nil];
UIView *mainView = [subviewArray objectAtIndex:0];
[self addSubview:mainView];
[self configureView];
}
return self;
}
-(void)configureView {
self.backgroundColor = [UIColor greenColor];
}
#end
I add a TimeTooltipView in a view controller, like so:
TimeTooltipView *timeTooltipView = [[TimeTooltipView alloc]
initWithFrame: CGRectMake(100, 100, 50, 50)];
timeTooltipView.timeLabel.text = #"TEST";
[self.view addSubview:timeTooltipView];
timeTooltipView.timeLabel.text = #"TEST2";
I need to change timeLabel's text on the fly from the view controller. Using the code above, the view gets added and has a green background color. But the label text never changes to "TEST" or "TEST2".
How can I change the custom view's label text on the fly?
-(id)initWithFrame:(CGRect)frame {
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"TimeTooltipView" owner:self options:nil];
//Instead of making it subView just replace it.
self = [subviewArray objectAtIndex:0];
self.frame = frame;
[self configureView];
return self;
}
-(void)configureView {
self.backgroundColor = [UIColor greenColor];
}
I have a tableview with 2 rows. In the first row I have an UIView and I'm gonna add a custom view on it. I made the custom view as a XIB and I'm adding it like following,
Layout6View *lookLayout6 = [[Layout6View alloc] initWithFrame:CGRectMake(0, 0,cell.mainView.frame.size.width, cell.mainView.frame.size.height)];
[cell.mainView addSubview:lookLayout6];
and my Layout6View looks like,
#implementation KCTLLookLayout6View
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [[[NSBundle mainBundle] loadNibNamed:#"Layout6"
owner:self
options:nil] lastObject];
self.frame = frame;
}
return self;
}
-(void)layoutSubviews{
[super layoutSubviews];
for (UIView *view in self.subviews) {
if (view == self.imageTopRightCorner) {
view.frame = CGRectOffset(CGRectMake(0, 0, /*(self.frame.size.width/2)-20, (self.frame.size.height/3)*/30,30), 0, 0);
}
}
}
#end
When I'm running this, the custom view didn't resized. It's spread all over the table view(not only inside the cell).
Is there a way to fix this?
Try:
[cell.contentView addSubview:lookLayout6];
Change the Size property of xib view. By default it is Inferred, make it Freeform and check.
I have a UIScrollView (similar to that seen showing the featured items on the App Store) which has 3 views, with xibs, loaded into it. Everything works find except I can get the UIButtons which I have on the xibs to fire. I guess I am missing something obvious just can't see it. I've tried various answers on here and other places to no avail.
Thanks in advance
Code from viewDidLoad on ViewController containing scroll view
LSCWInfoView *view1 = [[[NSBundle mainBundle]
loadNibNamed:#"LSCW-InfoView"
owner:self options:nil]
firstObject];
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size = self.activityPageControl.frame.size;
[view1 setFrame:frame];
[self.activityScrollView addSubview:view1];
ScrambledInfoView *view2 = [[[NSBundle mainBundle]
loadNibNamed:#"Scrambled-InfoView"
owner:self options:nil]
firstObject];
CGRect frame2;
frame2.origin.x = 320;
frame2.origin.y = 0;
frame2.size = self.activityPageControl.frame.size;
[view2 setFrame:frame2];
[self.activityScrollView addSubview:view2];
TestInfoView *view3 = [[[NSBundle mainBundle]
loadNibNamed:#"Test-InfoView"
owner:self options:nil]
firstObject];
CGRect frame3;
frame3.origin.x = 640;
frame3.origin.y = 0;
frame3.size = self.activityPageControl.frame.size;
[view3 setFrame:frame3];
[self.activityScrollView addSubview:view3];
_activityScrollView.contentSize = CGSizeMake(_activityScrollView.frame.size.width * 3, _activityScrollView.frame.size.height);
EDIT - Code for one of the views loaded into the scroll view (other 2 are the same)
#import "LSCWInfoView.h"
#implementation LSCWInfoView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
- (IBAction)lscwPlayButtonPressed:(id)sender
{
NSLog(#"YEP");
}
#end
Screenshots
This was fixed by setting the frame size of the view before it is added to the scrollview
firstly I want to say that I am newbie at iOS development. I have a problem with showing a view from xib file in ScrollView.
This MyView is only green background with one label. Here is a code from its controller:
#implementation MyView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//init code
}
return self;
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
}
return self;
}
#end
And here is a code from main controller where is the ScrollView:
- (void)viewDidLoad
{
[super viewDidLoad];
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 67, self.view.frame.size.width, self.view.frame.size.height)];
scroll.pagingEnabled = YES;
scroll.frame = CGRectMake(0, 20, 320, 350);
scroll.contentSize = CGSizeMake(320, 350);
scroll.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
scroll.bounces = YES;
scroll.bouncesZoom = YES;
scroll.scrollEnabled = YES;
scroll.minimumZoomScale = 0.5;
scroll.maximumZoomScale = 5.0;
scroll.delegate = self;
scroll.pagingEnabled = YES;
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil];
UIView *myView = [nibContents objectAtIndex:0];
myView.frame = CGRectMake(0,20,300,300);
[scroll addSubview:myView];
}
Only thing I want to do is that I want to see MyView (green background with one label) inside the ScrollView. If I run this app, scrollview is empty, nothing is shown inside.
Probably it is a stupid question but as I said, I am newbie at this. I have a PageControll app from Apple but for me this is quite complicated code in my iOS beginning. Of course I was googling... Please tell me where is a problem. Thank you
Where do you define scroll? Is it a property of your viewcontroller?
I think the problem here is that you don't add scroll view to your viewcontroller's view with
[self.view addSubview:scroll]
Everything seems to right. Just retain the view in your class that you are receiving from the following line and add that as a subview to your scrollview.
self.myView = [nibContents objectAtIndex:0];
Best Regards.
I want to position a view (red box with label and button) prepared in IB as Subview on the screen programmatically. The positioning works fine with the "blue lines" (there might actually be a better way to simply draw a line on a view?!). But the view of the "AttributeApertureView" view object sticks to the top instead of following the initFrame Parameter starting at y=60 as you can see in the screenshot.
//Add blue Line
CGRect lineB = CGRectMake(0, 48, bounds.size.width, 0.5);
UIView *secondLine = [[UIView alloc]initWithFrame:lineB];
[secondLine setBackgroundColor:[UIColor colorWithRed:0.396 green:0.796 blue:0.894 alpha:1]];
[[self view]addSubview:secondLine];
//Add Attribute Aperture
AttributeApertureView *aperture = [[AttributeApertureView alloc]initWithFrame:CGRectMake(0, 60, bounds.size.width, 50)];
[aperture setBackgroundColor:[UIColor redColor]];
[[self view]addSubview:aperture];
Init function in AttributeApertureView class. This should basically only load the related nib file with the IB Interface.
#implementation AttributeApertureView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:#"AttributeApertureView"
owner:self
options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
What is the best way to position the "aperture" view on the screen?
Seems like calling loadNibNamed: resets the view's frame to what it is in the nib. This should work:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:#"AttributeApertureView"
owner:self
options:nil];
self = [nib objectAtIndex:0];
self.frame = frame;
}
return self;
}
because self = [super initWithFrame:frame]; sets the frame once, but self = [nib objectAtIndex:0]; ends up changing it again because you are resetting the whole view, so you have to set the frame again to be the one in the argument.