iPhone 6 simulator:
iPhone5 hardware:
Channel Header:
- (id)initWithFrame:(CGRect)frame title:(NSString *)title {
self = [super initWithFrame:frame];
UILabel *l = [[UILabel alloc] initWithFrame:frame];
l.textAlignment = NSTextAlignmentCenter;
l.backgroundColor = BGC;
l.text = title;
[self addSubview:l];
return self;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
ChannelHeader *h = [[ChannelHeader alloc] initWithFrame:CGRectMake(0, 0, self.tv.frame.size.width, 44) title:[self titles][section]];
return h;
}
Why is my tableview header's textfield showing up off center?
Tableview frame in iPhone6 sim:
<UITableView: 0x7fce2c821a00; frame = (0 0; 414 736)
EDIT:
so I changed my simulated nib size from "iPhone 6" to "inferred", and the view boundaries grew. I stretched my UITableView to fit the bounds and now the text is even more off-centered. So somehow it's getting the wrong values for its frame..
Well, your frame for iPhone 6 is wrong.
iPhone 6 screen size is 375 x 667 points.
iPhone 6 plus screen size is 414 x 736 points.
Therefore, if you are running the application on iPhone 6 simulator and tableView frame is giving you iPhone 6 plus boundaries, then that is the error. Your header and UILabel is being rendered correctly according to the given frames.
So if you run your application in iPhone 6 plus simulator, you will get correct results.
More info on frames.
Solution:
If your setting your tableView through nib, and if you are using AutoLayout then you need to apply constraints accordingly.
If you have disabled AutoLayout then apply proper resizing masks to your tableView, i.e. Flexible Height & Flexible Width
Also, it would be a good practice, if you take values of the tableView frame provided by the delegate method instead of referring to the tableView property.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
ChannelHeader *h = [[ChannelHeader alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 44) title:[self titles][section]];
return h;
}
Note: This is just a piece of good practice and it doesn't effect the logic or the answer.
Whilst I await your response on the above comment, I'm quite certain I know why you are having an issue.
If you want to create UITableViewCell(s) which have centred labels there are really only two correct ways.
Either:
Subclass UITableViewCell and create a custom subclass which has an indigenously centred label.
Set the NSTextAlignment of the regular UITableViewCell textLabel control to centre in cellForRowAtIndexPath like so: cell.textLabel!.textAlignment = .Center.
To change the header text alignment, you should do something like this:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UILabel * sectionHeader = [[UILabel alloc] initWithFrame:CGRectZero];
sectionHeader.backgroundColor = [UIColor clearColor];
sectionHeader.textAlignment = NSTextAlignmentCenter;
sectionHeader.font = [UIFont boldSystemFontOfSize:10];
sectionHeader.textColor = [UIColor whiteColor];
return sectionHeader;
}
Related
I want to do a large tableView header like in Health app in iOS 11. I added a screenshot to show this element in red text. How to do large a tableView header?
If I understand your question correctly (and unfortunately the screenshot is gone), you can do that using the prefersLargeTitles property. This works on iOS 11 and higher only.
For instance:
if (#available(iOS 11.0, *)) {
self.navigationController.navigationBar.prefersLargeTitles = YES;
self.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAlways;
} else {
// Fallback on earlier versions
}
You can call this code in viewDidLoad or viewWillAppear of your UITableViewController.
Just set the frame property of the tableHeaderView.
No recorded Data is table view header. you can customize the tableview header with viewForHeaderInSection method of tableview. Your question is already answered in this link. Changing Font Size For UITableView Section Headers
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UILabel *TESTLabel = [[UILabel alloc] init];
TESTLabel .frame = CGRectMake(20, 8, 320, 40);
TESTLabel .font = [UIFont boldSystemFontOfSize:18];
TESTLabel .text = [self tableView:tableView titleForHeaderInSection:section];
UIView *headerView = [[UIView alloc] init];
[headerView addSubview: TESTLabel];
return headerView;
}
TRY THIS
My tableview cells are created entirely programmatically (I'm trying to learn to build an app from scratch without using storyboards) and the width of the cells is getting messed up.
Here is a screen shot http://imgur.com/ki6txqg of what the cell looks like in an iPhone 6 Plus. I'm trying to set the cell so that the UIView in the cell(self.view) gets adjusted automatically so that it fills the entire screen. I'm not sure why the width is staying static. Any advice would be greatly appreciated.
-(instancetype)initWithTweet:(PCRTweet *)tweet reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super init];
if (self) {
_tweet = tweet;
reuse = reuseIdentifier;
CGSize cellSize = self.contentView.frame.size;
CGRect backgroundView = CGRectMake(10.f, 5.f, (cellSize.width-20.f), (cellSize.height + 90.f));
self.view = [[UIView alloc] initWithFrame:backgroundView];
self.view.backgroundColor = [UIColor whiteColor];
self.view.layer.cornerRadius = 8;
self.view.layer.masksToBounds = YES;
self.view.layer.borderWidth = 1.0f;
self.view.layer.borderColor = background_color_gray.CGColor;
self.view.layer.masksToBounds = NO;
[self.contentView addSubview:self.view];
CGRect picView = CGRectMake(0.f, 0.f, 65.f, 65.f);
self.contentView.backgroundColor = background_color_gray;
}
return self;
}
Please read the points on following checklist to ensure you doing it all right:
-[ ] Have you checked that your contentView is dynamically changing?
-[ ] Have you tried putting constraints programatically?
-[ ] Try using constraints on the largest view : will auto adjust the relative views
Apart from it, you can auto-resizing for your frame.
You try this two UITableView Delegate method in table view class
For Dynamic Height
#pragma mark - UITableView Delegates
-(CGFloat)tableView:(UITableView )tableView estimatedHeightForRowAtIndexPath:(NSIndexPath )indexPath {
return 44.0;
}
-(CGFloat)tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath {
return UITableViewAutomaticDimension;
}
For Width (Get view controller width and take to backgroundView)
CGSize viewWidth = self.contentView.superview.superview.superview.superview.frame.size;
// self.contentView.superview -> return UITableViewCell
// self.contentView.superview.superview -> return UITableViewWrapperView
// self.contentView.superview.superview.superview -> return UITableView
// self.contentView.superview.superview.superview.superview -> return View Controller
CGRect backgroundView = CGRectMake(10.f, 5.f, (viewWidth.width-20.f), (cellSize.height + 90.f));
Try to use auto-resizing for your view.
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
I am setting up a UITableView programmatically. I would like the content of the cell to span the entire width of the screen. I have successfully set the cell to span the width of the screen, but the content and separators are still inset significantly (iPad screenshot below).
Here is the tableview layout setup in my view controller implementation:
- (void) viewDidLoad {
[super viewDidLoad];
// table layout
self.tableView.rowHeight = 192;
UILayoutGuide *margins = [self.view layoutMarginsGuide];
[self.tableView.leadingAnchor constraintEqualToAnchor:margins.leadingAnchor] ;
[self.tableView.trailingAnchor constraintEqualToAnchor:margins.trailingAnchor];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
CGRect tableRect = self.view.frame;
self.tableView.frame = tableRect;
// table colors
self.tableView.backgroundColor = [UIColor grayColor];
self.tableView.separatorColor = [UIColor grayColor];
UIView *backView = [[UIView alloc] init];
[backView setBackgroundColor:[UIColor grayColor]];
[self.tableView setBackgroundView:backView];
}
Then I set the cell's content:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
cell.backgroundColor = [UIColor blueColor];
cell.indentationWidth = 0;
cell.indentationLevel = 0;
cell.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
cell.contentView.backgroundColor = [UIColor purpleColor];
return cell;
}
The cell background is blue, and it spans the width of the screen. The purple area in my screenshot is the contentView, and as you can see, it doesn't stretch to the right edge of the screen, and the cell text is inset at the left. The separator is also inset at left and right.
I discovered the issue thanks to the comment on my question by #technerd. Thank you!
I was testing my app on iOS 9.2, and I neglected to account for the new iOS9+ cell property cellLayoutMarginsFollowReadableWidth, which adjusts the cell layout by default.
To turn the auto-resizing off, you'll need to check the iOS version and then disable the property, as #technerd demonstrates:
Objective C
- (void)viewDidLoad {
[super viewDidLoad];
//For iOS 9 and Above
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 9.0) {
self.tableView.cellLayoutMarginsFollowReadableWidth = NO;
}
}
Swift
override func viewDidLoad() {
super.viewDidLoad()
//For iOS 9 and Above
if #available(iOS 9, *) {
tableView.cellLayoutMarginsFollowReadableWidth = false
}
}
Hope this helps others.
The above solution doesn't really work perfectly anymore. Although, all you need to do now is:
tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
This will make your separator run throughout the width of the table view.
I am trying to change the position of the images in my UITableViewController cells. Here is my code:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIImageView *cellImage = cell.imageView;
CGRect frame = cellImage.frame;
frame.origin.x = 4;
frame.origin.y = 2;
cell.backgroundColor = [UIColor lightGrayColor];
}
So far the only thing that is working is the background color. Any suggestions?
Here is a screenshot of what I have now:
Right now the images are centered but I was hoping to move them a little bit closer to the top-left of the cell.
If your UI was created in IB and auto layout is turned on you need to update the constraints on the image view and then you don't even have to worry about changing the frame as auto layout will force the change itself.
This guide is technically for OS X but most of it is the same: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Articles/Introduction.html#//apple_ref/doc/uid/TP40010853
There is also a WWDC video from 2012 that gives an overview if you are unfamiliar with auto layout all together.
you can add this code to layoutSubviews method of cell. Something like this
-(void)layoutSubviews
{
[super layoutSubviews];
UIImageView *cellImage = self.imageView;
CGRect frame = cellImage.frame;
frame.origin.x = 4;
frame.origin.y = 2;
self.imageView.frame = frame;
self.backgroundColor = [UIColor grayColor];
}
And don't forget to actually change self.imageView.frame
You are almost there, you have modified the frame and the background color but you forgot to set the cell's actual frame. You need to add this after you change the frame:
cellImage.frame = frame;
or
cell.imageView.frame = frame;
The reason it is not working in your implementation is you are taking the image view's frame and setting it into another property (frame in this case). You are then changing that properties origin, not the cell's origin.
The background color worked because you are making that call directly on the cell cell.backgroundColor (you are calling the cell's setter). So you need to do the same thing with the view's frame.
Here is the way to achieve the same in one liner:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell.imageView setFrame:CGRectMake(2, 4, cell.imageView.frame.size.width, cell.imageView.frame.size.height)];
}
I have to build a custom tableViewHeader in which at least two labels should be displayed, viz. a projectName and projectDescription. The contents of these two labels vary (i.e. in terms of string-length).
I managed to get a working version for the default device orientation (portrait) but if the user rotates the device to landscape the width of my custom headerView is not adjusted, and the user will see unused white space to the right.
The following code fragment is being used:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 50.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
CGFloat wd = tableView.bounds.size.width;
CGFloat ht = tableView.bounds.size.height;
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0., 0., wd, ht)];
headerView.contentMode = UIViewContentModeScaleToFill;
// Add project name/description as labels to the headerView.
UILabel *projName = [[UILabel alloc] initWithFrame:CGRectMake(5., 5., wd, 20)];
UILabel *projDesc = [[UILabel alloc] initWithFrame:CGRectMake(5., 25., wd, 20)];
projName.text = #"Project: this project is about an interesting ..";
projDesc.text = #"Description: a very long description should be more readable when your device is in landscape mode!";
[headerView addSubview:projName];
[headerView addSubview:projDesc];
return headerView;
}
I noticed that the tableView:viewForHeaderInSection: will only be called once after viewDidLoad, but not after a device orientation change.
Should I implement the willRotateToInterfaceOrientation: method with something like:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
[self.tableView reloadSections:nil withRowAnimation:UITableViewRowAnimationNone];
}
I cannot figure out how to get the reloadSections: to work, forcing a recalculation of my customView.
If you use autoresizingMask the header adjusts correctly on rotation. No need to override anything else. I would set the automasks at the end of the code just before returning the view:
[headerView addSubview:projName];
[headerView addSubview:projDesc];
projName.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
projDesc.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
return headerView;