I think the 2 labels, the bigger one and smaller one are just positioned at the centre of the screen.
Changing the coordinates doesnt seem to have an effect on where they are getting placed. Why?
Ideally I would want them to be of same size, not overlap and one below the other so that they cover nearly the whole screen.
I thought the labelframe uses the format - starting coodinates, size.
Where is my origin? is at top left of the screen?
can I translate it in xcode?
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) UILabel *label;
#property (nonatomic, strong) UILabel *label1;
#end
#implementation ViewController
- (void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
CGRect labelFrame = CGRectMake(-200.0f,0.0f, 200.0f, 200.0f);
self.label = [[UILabel alloc] initWithFrame:labelFrame];
//self.label.adjustsFontSizeToFitWidth = YES;
self.label.text = #"One two three four five six seven eight nine.";
self.label.font = [UIFont boldSystemFontOfSize:28.0f];
self.label.numberOfLines = 5;
self.label.center = self.view.center;
[self.view addSubview:self.label];
CGRect labelFrame1 = CGRectMake(600.0f,600.0f, 100.0f, 100.0f);
self.label1 = [[UILabel alloc] initWithFrame:labelFrame1];
self.label1.text = #"One 1 two three four five six seven eight nine.";
self.label1.font = [UIFont boldSystemFontOfSize:18.0f];
self.label1.numberOfLines = 0;
self.label1.center = self.view.center;
[self.view addSubview:self.label1];
}
#end
Origin 0,0 is the top left corner of the screen superview. If you want the labels at the center of the screen, one on top of the other, you can do :
self.label = [[UILabel alloc] init];
// setup label text, font..
[self.label sizeToFit]; // automatically set the appropriate size
self.label.center = self.view.center;
[self.view addSubview:self.label];
self.label1 = [[UILabel alloc] init];
// setup label text, font..
[self.label sizeToFit]; // automatically set the appropriate size
self.label1.center = self.view.center; // set at center of screen
// just overwrite origin.y to set it below the previous label
self.label1.frame = (CGRect) { self.label1.frame.origin.x, self.label.frame.origin.x + self.label.frame.size.height, self.label1.frame.size };
[self.view addSubview:self.label1];
Update: based on your comment, to have it two rows, one column is easier. Just set the frame to be full width, and half height :
self.label = [[UILabel alloc] initWithFrame:CGrectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height / 2];
self.label1 = [[UILabel alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height / 2, self.view.frame.size.width, self.view.frame.size.height / 2];
You're overwritting the origins you set when you call
self.label.center = self.view.center
Related
I have a UIView that contains drop shadows and corners which I am loading four of in my UIViewController and I am seeing a performance hit when the screen loads. Since I am using the same white background with shadows and corner radii I figured I would store the UIView in NSCache.
When I run the app there is a large gap where the first UIView should be, however, it is not showing up. What does show up is the last view in my list of views. If I comment out the last one and run it again, the third one shows up. It seems like I am having an issue with the pointer in memory but not sure. Perhaps I am using NSCache incorrectly?
(Note: The first view shown is not using the NSCache)
Here is how I am using the NSCache:
.h file
#interface LunchDetailViewController : UIViewController <UIScrollViewDelegate>
#property (nonatomic) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) NSCache *entreeViewsCache;
#end
.m file
#synthesize scrollView;
#synthesize entreeViewsCache;
- (void)viewDidLoad
{
[super viewDidLoad];
self.entreeViewsCache = [[NSCache alloc] init];
UIView *entreeView = [[UIView alloc] init];
entreeView.backgroundColor = [UIColor whiteColor];
entreeView.layer.masksToBounds = NO;
entreeView.layer.cornerRadius = 3.0;
entreeView.layer.shadowOffset = CGSizeMake(1.1, 2.1);
entreeView.layer.shadowOpacity = 0.2;
[self.entreeViewsCache setObject:entreeView forKey:#"EntreeView"];
}
- (void) configureScrollView
{
// This line of code allows the scroll view to be 'scrollable'.
self.scrollView.contentSize = CGSizeMake(320, 620);
UIView *elementaryRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
elementaryRoundedCornerView.frame = CGRectMake(15,15,290,180);
UIView *middleRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
middleRoundedCornerView.frame = CGRectMake(15,210,290,180);
UIView *highRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
highRoundedCornerView.frame = CGRectMake(15,404,290,180);
NSMutableArray *entreeItems = [[NSMutableArray alloc] initWithObjects:#"Pancakes w/ Sausage Patties", #"Corn Dog", #"Grilled Cheese Sandwhich", #"Chicken Tender Wraps", nil];
UIView *elementaryLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
[elementaryLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 5, 215, 160) schoolType:#"Elementary"]];
[elementaryRoundedCornerView addSubview:elementaryLunchMenuDetails];
UIView *middleLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
[middleLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:#"Middle"]];
[middleRoundedCornerView addSubview:middleLunchMenuDetails];
UIView *highLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10,10, 240, 160)];
[highLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:#"High"]];
[highRoundedCornerView addSubview:highLunchMenuDetails];
[self.scrollView addSubview:elementaryRoundedCornerView];
[self.scrollView addSubview:middleRoundedCornerView];
[self.scrollView addSubview:highRoundedCornerView];
}
Wow. That's clever. But not correct.
Instead of using NSCache to duplicate a view, you probably want to create a UIView subclass that formats the view the way you want. Then just throw a bunch of those views on your scrollview.
ABCView.m
#implementation ABCDayView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 3.0;
self.layer.shadowOffset = CGSizeMake(1.1f, 2.1f);
self.layer.shadowOpacity = 0.2f;
}
return self;
}
- (void)setItems:(NSArray *)items
{
if ([_items isEqualToArray:items] == NO) {
_items = items;
[self createItemViews];
[self setNeedsLayout];
}
}
// You'll also need to add -createItemViews and -setNeedsLayout methods.
.m file
- (void)configureScrollView
{
NSMutableArray *entreeItems = #[#"Pancakes w/Sausage Patties",
#"Corn Dog",
#"Grilled Cheese Sandwhich",
#"Chicken Tender Wraps"];
CGRect frame = CGRectMake(15,15,290,180);
ABCDayView *elementaryView = [[ABCDayView alloc] initWithFrame:frame];
elementaryView.items = entreeItems;
CGFloat y = CGRectGetMaxY(elementaryView.frame) + 10.0f;
frame = CGRectMake(15, y, 290, 180);
ABCDayView *middleView = [[ABCDayView alloc] initWithFrame:frame];
middleView.items = entreeItems;
...
CGFloat length = // Use CGRectGetMaxY on the last frame to get the length.
self.scrollView.contentSize = CGSizeMake(320, length);
}
That's by no means perfect code. But hopefully it will give you an idea of a better way to implement this.
Ok, I have done this kind of thing a million times but this particular case escapes me and I'm sure its just something stupid I am missing...
But I am trying to display a UIView on top of a mapView to give the impression the mapview is 'disabled.'
I created a UIView subclass and added a single label. like so...
.h
#import <UIKit/UIKit.h>
#interface DisabledOverlayView : UIView
#property (nonatomic, strong) UILabel *disabledOverlayViewText;
#end
nothing complicated...
in my .m I set the text and add it to my UIView.
#synthesize disabledOverlayViewText = _disabledOverlayViewText;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor blackColor];
self.alpha = 1;
_disabledOverlayViewText.textColor = [UIColor whiteColor];
_disabledOverlayViewText.frame = CGRectMake(0, 0, 200, 200);
// [_disabledOverlayViewText setCenter:self.center];
_disabledOverlayViewText.text = #"testing";
[self addSubview:_disabledOverlayViewText];
}
return self;
}
then the class i wish to use this overlay i call it with...
DisabledOverlayView *disabledView = [[DisabledOverlayView alloc] initWithFrame:CGRectMake(12, 12, _mapView.frame.size.width, _mapView.frame.size.height)];
disabledView.disabledOverlayViewText.text = #"No Location";
[self.view addSubview:disabledView];
None of this is too complicated.. but the label doesn't show up. the overlay appears just fine, but no label text. Ive messed with the frames of the label thinking maybe it was off the visible view but no dice. and i cannot figure out what is going on.
Replace your initWithFrame method with the below code. I have added the alloc init line and changes the background color of the label. Try it and see whether it works :)
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor blackColor];
self.alpha = 1;
_disabledOverlayViewText = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
_disabledOverlayViewText.textColor = [UIColor whiteColor];
_disabledOverlayViewText.backgroundColor = [UIColor blackColor];
// [_disabledOverlayViewText setCenter:self.center];
_disabledOverlayViewText.text = #"testing";
[self.view addSubview:_disabledOverlayViewText];
}
It seems the label is not allocated and it's nil.
Try this
(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor blackColor];
self.alpha = 1;
self.disabledOverlayViewText = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
_disabledOverlayViewText.textColor = [UIColor whiteColor];
// [_disabledOverlayViewText setCenter:self.center];
_disabledOverlayViewText.text = #"testing";
[self addSubview:_disabledOverlayViewText];
}
I want to set an image and a label at the center of my UINavigationBar, along all my navigation stack.
What I'm currently doing is adding it to my navigation item titleView.
The "problem" with this approach is that I have to call this method in the viewDidLoad for each view controller I push to my navigation stack.
The other way around is to add the UILable and UIImageView directly to the UINavigationBar, however that why I have to calculate the center myself, and in addition I read that's not the recommended approach.
Any Idea how to get what I want ?
My Code:
CGRect navTitle = controller.navigationController.navigationBar.bounds;
CGFloat aHeight = navTitle.size.height;
UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 163, aHeight)];
UIImage* statusImg = [UIUtils getStatusImage];
UIImageView *statusImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,aHeight/2-statusImg.size.height/2, 33., 32.)];
statusImage.autoresizingMask = UIViewAutoresizingNone;
statusImage.image = statusImg;
statusImage.backgroundColor = [UIColor clearColor];
[statusImage setTag:1];
[statusImage setHidden:NO];
initWithFrame:CGRectMake(statusImage.frame.origin.x + 33. + 3, 0, 130., navTitle.size.height)];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(statusImage.frame.origin.x + 33. + 3, 0, 130., navTitle.size.height)];
titleLabel.textAlignment = UITextAlignmentLeft;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont boldSystemFontOfSize:20.];
titleLabel.shadowOffset = CGSizeMake(1, -1);
titleLabel.opaque = NO;
titleLabel.backgroundColor = [UIColor clearColor];
[titleLabel setTag:2];
[container addSubview:statusImage];
[container addSubview:titleLabel];
controller.navigationItem.titleView = container;
[statusImage release];
[titleLabel release];
[container release];
Found the a nice way to do it :
Registering yourself as the delegate of UINavigationController will let you receive a callback each time a new controller is about to be pushed.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
Inside that function, getting the viewController and operating on his navigationitem will do the trick.
Why doesn't view2 appear in this code? In the result I see the local View1 label shown, at the top with a red border, and within the overall green border, however I see nothing of view2? That is the label with text "View2 Label Text", does NOT appear.
test11ViewController.m
#implementation test11ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
View1 *view1 = [[[View1 alloc] initWithFrame:CGRectMake(0.0, 0.0, 400, 100) ] autorelease];
view1.layer.borderColor = [UIColor redColor].CGColor;
view1.layer.borderWidth = 1;
[self.view addSubview:view1];
}
#end
View1.m
#implementation View1
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Local Label
CGFloat width = self.frame.size.width;
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, width, 30)] autorelease];
label.text = #"View1 Label Text";
label.layer.borderColor = [UIColor greenColor].CGColor;
label.layer.borderWidth = 1.0;
[self addSubview:label];
// External - Label2
View2 *view2 = [[[View2 alloc] initWithFrame:CGRectMake(0.0, 30, width, 30)] autorelease];
[super addSubview:view2];
}
return self;
}
#end
View2.m
#implementation View2
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGFloat width = self.frame.size.width;
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, width, 30)] autorelease];
label.text = #"View2 Label Text"; // Does NOT appear in output
label.layer.borderColor = [UIColor blueColor].CGColor;
label.layer.borderWidth = 1.0;
}
return self;
}
#end
view2 isn't actually adding the label to itself. You're missing this:
[self addSubview:label];
In other words, try:
#implementation View2
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGFloat width = self.frame.size.width;
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, width, 30)] autorelease];
label.text = #"View2 Label Text"; // Does NOT appear in output
label.layer.borderColor = [UIColor blueColor].CGColor;
label.layer.borderWidth = 1.0;
[self addSubview:label]; // NEW LINE HERE
}
return self;
}
#end
In your test view controller line after...
[self.view addSubview:view1];
...add...
[self.view sendSubviewToBack:view1];
Does view2 show now? Alertnately, set the alpha of both views to 0.5 to make sure one is not obscuring the other.
What is the best way to position a view relative to the size of its superview, when the bounds of the superview are not yet known?
I am trying to avoid hard-coding coordinates if it is at all possible. Perhaps this is silly, and if so, that's a perfectly acceptable answer.
I've run into this many times when working with custom UI. The most recent example is that I'm trying to replace the UINavigationItem plain-text title with a custom view. I want that view to fill the superview, but in addition, I want a UIActivityIndicatorView on the right side, inset about 2 pixels and centered vertically. Here's the code:
- (void) viewDidLoad
{
[super viewDidLoad];
customTitleView = [[UIView alloc] initWithFrame:CGRectZero];
customTitleView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
titleLabel.numberOfLines = 2;
titleLabel.minimumFontSize = 11.0;
titleLabel.font = [UIFont systemFontOfSize:17.0];
titleLabel.adjustsFontSizeToFitWidth = YES;
[customTitleView addSubview:titleLabel];
spinnerView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
spinnerView.center = CGPointMake(customTitleView.bounds.size.width - (spinnerView.bounds.size.width / 2) - 2,
customTitleView.bounds.size.height / 2);
spinnerView.hidesWhenStopped = YES;
[customTitleView addSubview:spinnerView];
self.navigationItem.titleView = customTitleView;
[customTitleView release];
}
Here's my problem: at the time that this code runs, customTitleView.bounds is still zeroes. The auto-resizing mask hasn't had a chance to do its thing yet, but I very much want those values so that I can compute the relative positions of other sub-views (here, the activity indicator).
Is this possible without being ugly?
The only reason customTitleView.bounds has zero width and height is because you've initialized it that way by using CGRectZero. You can initialize the view with any nonzero size and then define its subviews in relation to that arbitrary size. As long as you've defined the autoresizing behaviors of the subviews properly, their layout will be adjusted appropriately when the frame of the superview changes at runtime.
For example:
- (void) viewDidLoad
{
[super viewDidLoad];
customTitleView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
customTitleView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel = [[UILabel alloc] initWithFrame:customTitleView.bounds];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
titleLabel.numberOfLines = 2;
titleLabel.minimumFontSize = 11.0;
titleLabel.font = [UIFont systemFontOfSize:17.0];
titleLabel.adjustsFontSizeToFitWidth = YES;
[customTitleView addSubview:titleLabel];
[titleLabel release];
spinnerView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
spinnerView.center = CGPointMake(customTitleView.bounds.size.width - (spinnerView.bounds.size.width / 2) - 2,
customTitleView.bounds.size.height / 2);
spinnerView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
spinnerView.hidesWhenStopped = YES;
[customTitleView addSubview:spinnerView];
[spinnerView release];
self.navigationItem.titleView = customTitleView;
[customTitleView release];
}