Update: I ended up implementing the code below into it's own method and then called it from viewDidLayoutSubviews and willAnimateRotationToInterfaceOrientation. Doing it from viewDidAppear (as suggested) would not resize the view when returning from a segue.
I have a UIView defined in a storyboard which I'm using for a header view on my UIViewController. I have a constant in my code for all header views to be 80 units high. I have a tag on the storyboard header view of 200. I thought I could use this tag to get the view, modify the height of the underlying CGRect, and then re-set the header view to the modified CGRect. That doesn't seem to affect the height however. What am I missing?
- (void)viewDidLoad
{
UIView *header = [self.view viewWithTag:200];
CGRect hrect = [header frame];
hrect.size.height = HEADER_HEIGHT;
[header setFrame:hrect];
...
Try to do that on viewDidAppear then call
[self setNeedsLayout]
The problem is that you're using the tag as an NSString. The tag property is an NSInteger. Try doing the following:
- (void)viewDidLoad
{
UIView *header = [self.view viewWithTag:200];// give the tag as an int
CGRect hrect = [header frame];
hrect.size.height = HEADER_HEIGHT;
[header setFrame:hrect];
...
Also, make sure the tag you defined in the Storyboard is also 200 and not #"200".
Hope this helps!
Related
I have a UITextField that I want to create a custom class on. So I created a file with a subclass of UITextField. Next, in the custom class, I want to implement a tableView. Kind of like a auto-complete textField.
I started creating it, and added the tableView like this:
[self addSubview:self.tableView];
When I run the app, the tableView is in the textField, so I can only see part of the tableView. How can I add it as a subview so I can see the full tableView?
This is what you are looking for
https://github.com/gaurvw/MPGTextField
This uitextfield subclass does what you want - it's builed for 'search' feature.
If you still want to use your own,
add tableview not to uitextfield itself, but like
[[self superview] addSubview:tableViewController.tableView];
EDIT:
you can set frame as:
CGRect frameForPresentation = [self frame];
frameForPresentation.origin.y += self.frame.size.height;
frameForPresentation.size.height = 200;
[tableViewController.tableView setFrame:frameForPresentation];
The way to add subview to uitextfield is to overload layoutSubviews method and init your tableview there:
- (void)layoutSubviews
{
[super layoutSubviews];
if (!self.tableview.superview)
{
[self setupView];
}
}
This will add the tableView as the subView of the textField.
self.tableView.frame = CGRectMake(0, CGRectGetHeight(self.bounds), CGRectGetWidth(self.bounds), YOUR_TABLE_HEIGHT);
[self addSubview:self.tableView];
self.clipsToBounds = NO;
However, a better way is to make the tableView as the textField's superView's subView, that is, the textField and the tableView should be siblings.
I have a Storyboard that is using a UITableViewController. I have added a UIView as the UITableView header and set the height to 200. But, for some reason, when I preview it, the header is huge! looks to be about 540 high (header is white):
Here are my settings:
It looks correct in the storyboard preview. What could be causing it to be so huge and prevent my height setting from working?
Apple figured it out. Here is what they said:
Because the frame of a view can not be customized per-size class, you
need to make changes to your header view's frame while editing the
[wAny hAny] size class.
I was in the [wCompact hRegular] mode, which apparently you cannot set frame sizes in.
Just solved this question, try this:
UIView *v = self.tableView.tableHeaderView;
CGRect fr = v.frame;
fr.size.height = [UIScreen mainScreen].bounds.size.height -100;
v.frame = fr;
[self.tableView updateConstraintsIfNeeded];
Can't set constraints of UItableView's tableHeaderView height by autolayout in Storyboard
For me in order to make it work, I needed to create an IBOutlet reference to the header view. Then I added in the viewDidLoad:
self.header.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 40);
self.tableView.sectionHeaderHeight = 0;
You have to take a seperate NibFile and resize the nib file as per your required size (Resize the height manually do not use attribute inspector.). Change Simulated metrics to freeform in attribute inspector.
Then You can customize the HeaderView .
static NSString *SectionHeaderViewIdentifier = #"SectionHeaderViewIdentifier";
#define HEADER_HEIGHT 200
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.sectionHeaderHeight = HEADER_HEIGHT;
// Set up default values.
self.tableView.sectionHeaderHeight = HEADER_HEIGHT;
UINib *sectionHeaderNib = [UINib nibWithNibName:#"SectionHeaderView" bundle:nil];
[self.tableView registerNib:sectionHeaderNib forHeaderFooterViewReuseIdentifier:SectionHeaderViewIdentifier];
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *sectionHeaderView = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderViewIdentifier];
//You can customize your header view
return sectionHeaderView;
}
I would like to know how to access a UIScrollView using a subview UILabel.
I have tried to access the UIScrollView using .superview; however I am now receiving an error
No visible #interface for 'UIView' declares the selector 'scrollRectToVisible:animated:'
The code I am using looks like this
- (void) SymbolButtonPressed:(NSString *)selectedString {
UILabel *label = (UILabel *)[self.view viewWithTag:currentlySelectedTag];
// perform scrolling here, figure out what view your uilable is in.
float newPosition = label.superview.contentOffset.x+label.frame.size.width;
CGRect toVisible = CGRectMake(newPosition, 0, label.superview.frame.size.width, label.superview.frame.size.height);
[label.superview scrollRectToVisible:toVisible animated:YES];
}
The superview of a UILabel is of type UIView and so does not respond to the method you are trying to call. You can cast the superview as a UIScrollView so that Xcode can see the methods and properties you are trying to access. You should also check if the superview responds to the method.
if([label.superview respondsToSelector:#selector(scrollRectToVisible:animated:)]) {
[(UIScrollView *)label.superview scrollRectToVisible:toVisible animated:YES];
}
Given your sample code you will also need to cast the superview to get contentOffset
float newPosition = ((UIScrollView *)label.superview).contentOffset.x+label.frame.size.width;
I have a custom view class which inherits from UIView. This class has an UILabel as its subview. In the init-function of this custom view class I set up everything needed like this:
//h-file
#import <UIKit/UIKit.h>
#interface MyCustomView : UIView
#property (strong, nonatomic) UILabel *myLabel;
#end
//m-file
#implementation MyCustomView
#synthesize myLabel = _myLabel;
- (id)init
{
self = [super init];
if (self) {
_myLabel = [UILabel new];
if(_textView){
_myLabel.highlightedTextColor = [UIColor whiteColor];
_myLabel.translatesAutoresizingMaskIntoConstraints = NO;
_myLabel.lineBreakMode = NSLineBreakByWordWrapping;
_myLabel.numberOfLines = 0;
_myLabel.backgroundColor = [UIColor clearColor];
[self addSubview:_myLabel];
}
}
return self;
}
#end
I also set up a bunch of constraints to manage padding inside my custom view - furthermore there are constraints to layout multiple MyCustomView-instances for both vertical and horizontal axis as well.
To get a multilined label output I have to set the preferredMaxLayoutWidth-property of the UILabel myLabel. The width depends on the free space available. At http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html I read, that I can let Auto Layout calculate the width first and set it as preferredMaxLayoutWidth after the frame of the MyCustomView-instance (the label inside is single lined at this moment) has been set.
If I put the following function into the MyCustomView, the label still has a single line of text:
- (void)layoutSubviews
{
[super layoutSubviews];
float width = _myLabel.frame.size.width;
_myLabel.preferredMaxLayoutWidth = width;
[super layoutSubviews];
}
If I set the preferredMaxLayoutWidth to an explicit value inside the init-function, the label is multilined.
Does anybody know what I am doing wrong here?
Thanks in advance!
Without seeing all the constrains you have setup for your custom view, and the superview that contains it, it's really hard to determine the problem, I suggest you to print out all the view frames of the entire view hierarchy starting from the view controller's view at viewDidLayoutSubviews and determine if the label and its superviews have correct frame set.
I have an encountered similar issues with dynamic label size and scroll view so I created a prototype here, might be useful to you too: https://github.com/briandotnet/AutoLayoutScrollViewExperiment
In my awakeFromNib function, I have:
[_descriptionLabel setLineBreakMode:UILineBreakModeWordWrap];
[_descriptionLabel setNumberOfLines:10];
[_descriptionLabel sizeToFit];
and yet my label looks like this:
I know I'm setting these calls on the right label, because without these lines, the text appears vertically centered rather than aligned at the top. How can I make make my UILabel multiline?
I also tried setNumberOfLines:0.
SOLUTION I had set the width incorrectly in the xib file.
Try to set [_descriptionLabel setNumberOfLines:0]; which set the number of lines to auto.
It might be that sizeToFit is changing your label width, try to set it to explicit width, or remove it.
Just make sure that the initial width is set correctly. Then it should expand/shrink the height. But still the label won't be aligned to the top, it will be centered in its previous size after a call of sizeToFit (in case the new height is smaller than before, otherwise the origin will stay the same).
If you're not using AutoLayout, you need to measure text in code:
CGRect frame = _descriptionLabel.frame;
CGSize size = [_descriptionLabel.text sizeWithFont:_descriptionLabel.font constrainedToSize:CGSizeMake(frame.size.width, FLOAT_MAX) lineBreakMode:_descriptionLabel.lineBreakMode];
frame.size.height = MIN(MAX(size.height, frame.size.height), MAX_ALLOWED_HEIGHT);
_descriptionLabel.frame = frame;
Are you sure your awakeFromNib is in the right place. If it's in the view controller, it won't work. If it's in the implementation of a custom label, it should get called and that code should work:
#interface TestLabel : UILabel
#end
#implementation TestLabel
- (void)awakeFromNib
{
[self setLineBreakMode:UILineBreakModeWordWrap];
[self setNumberOfLines:10];
[self sizeToFit];
NSLog(#"Label: %#", NSStringFromCGRect(self.frame));
}
#end
Also, it's easier to set numberOfLines to 0, which means "any number of lines". And you shouldn't need to set UILineBreakModeWordWrap, since that's the default.
If you want to keep the code in the view controller, you can move it to viewDidLoad, which is the best place to do this kind of setup.