I'm using a standard prototype cell with a label and a detail text. I set the detail text to be two lines and set the text to something with a line break. This works fine - however, the (left aligned) main label has lost its vertical centering, though I didn't change any of its attributes.
This is what it looks like in Storyboard:
"Title" should be vertically centered.
You can use a custom cell in which you can define the attributes of the custom properties.The size of the text label is not fixed. I think this is the reason why the alignment does not work.
You can subclass the UITableViewCell and do your layout in the initWithStyle method. For ex:
MyCustomCell.h file:
#interface MyCustomCell : UITableViewCell
{
UILabel *_label1;
UILabel *_label2;
UILabel *_titleLabel;
}
#property (nonatomic, strong) UILabel *label1;
#property (nonatomic, strong) UILabel *label2;
#property (nonatomic, strong) UILabel *titleLabel;
#end
MyCustomCell.m file:
#import "MyCustomCell.h"
#implementation MyCustomCell
#synthesize label1 = _label1;
#synthesize label2 = _label2;
#synthesize titleLabel = _titleLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.label1 = [[UILabel alloc]initWithFrame:CGRectMake(x, y, w, h)]; //x: x coordinate, y: y coordinate, w is width , h is height
self.label2 = [[UILabel alloc]initWithFrame:CGRectMake(x, y, w, h)];
self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(x, y, w, h)];
self.titleLabel.font = [UIFont fontWithName:#"Times New Roman" size:30.0f]; //change font name and size per your needed.
[self addSubview:self.label1];
[self addSubview:self.label1];
[self addSubview:self.titleLabel];
}
return self;
}
In the class file where you have cellForRowAtIndexPath method, make sure include the #import "MyCustomCell.h" and use MyCustomCell instead of UITableViewCell to allocate the cell. And assigning data to labels as so:
cell.label1.text = xxxx;
cell.label2.text = xxxx;
cell.titleLabel.text = xxxx;
Related
I have a Popup-View which contains two labels, a tableview and button. I created a ViewController as in Display UIViewController as Popup in iPhone described.
My special requirement is now, that the tableview is not necessary in all cases, so I tried to hide it and expected a reduced height of the Popup-View. But I always get the same height. I also tried to use a UIStackView, but the height of the view wasn't changed in case of hiding the tableview.
I also need to have the view in center of the display in both cases of height.
enter image description here
#interface AuthorizationMessageViewController ()
#property (weak, nonatomic) IBOutlet UIView *messageView;
#property (weak, nonatomic) IBOutlet UILabel *titelLabel;
#property (weak, nonatomic) IBOutlet UILabel *detailsLabel;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UIButton *okButton;
- (IBAction)okButtonTouchUp:(id)sender;
#end
#implementation AuthorizationMessageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.messageView.layer.cornerRadius = 5;
self.messageView.layer.masksToBounds = YES;
self.messageView.backgroundColor = COLOR_BACKGROUND_WHITE;
self.messageView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.backgroundColor = COLOR_BACKGROUND_WHITE;
self.titelLabel.text = WHLocalizedString(#"EventHeaderAuthorization", nil);
[self setupView];
}
- (void)setupView
{
NSString *ns_messageText;
ns_messageText = #"test";
if (YES)
{
ns_messageText = #"Hide"
[self.tableView setHidden:YES];
}
else
{
ns_messageText = #"No Hide"
[self.tableView setHidden:NO];
}
self.detailsLabel.text = ns_messageText;
self.detailsLabel.textColor = COLOR_TEXT_GREY_KEY;
self.detailsLabel.numberOfLines = 0;
[self.detailsLabel sizeToFit];
}
#pragma mark - Table view data source
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 7;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 21;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"testCell"];
UILabel *weekDayLabel = (UILabel *)[cell viewWithTag:10];
weekDayLabel.text = #"weekday";
weekDayLabel.textColor = COLOR_TEXT_GREY_KEY;
weekDayLabel.font = FONT_LIGHT_SIZE_15;
UILabel *testLabel = (UILabel *)[cell viewWithTag:11];
testLabel = #"testLabel"
testLabel = COLOR_TEXT_GREY_KEY;
testLabel = FONT_LIGHT_SIZE_15;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
I hope that someone has a solution or an idea for that.
Imagine the following UI
a centered UIView that contains a UIButton and UITableView , you need to hook height constraint of the table and do this inside the popup if you want to hide it
#IBOutlet weak var heightTblCon:NSLayoutConstraint!
//
self.heightTblCon.constant = show ? 300 : 0
self.view.layoutIfNeeded()
BTW i changed color of background view for clarification purposes that should be transparent for modals
Try calling sizeToFit() on Popup-View after hiding the tableView:
popupView.sizeToFit()
Try to Adjust the Height of your view using the NSLayoutConstraint. Create an outlet for the same and manage height programatically. For example:
myConstraintOutlet.constant = 10
myTableView.layoutIfNeeded()
Here is the link for further assistant.
Regarding your second query to have the pop up always in centre you can either do it using Autolayout or programatically define the centre of your pop up.
myView.center = CGPoint(x: superView.center.x, y: superView.center.y)
Hope that helps.
Example:
Text in textLabel and descriptionLabel isn't empty
Text descriptionLabel is empty
It's possible con Autolayout or it's necessary to override some method.
OK, answer version 1.1. This time we do this:
Add your top titleLabel: Set a vertical constraint in auto layout to the superview. Go to your size inspector and change the constant to -15 (which will slide it up). Set another constraint to the top of the view to whatever you want for padding. Set the priority on that constraint to 900.
Now control drag from the vertical constraint of tltleLabel to the interface of your .m file to create an outlet for the constraint.
Add your bottom subtitleLabel: Set a vertical constraint to the superview with a multiplier of 1.5 (or whatever you need to make it look OK). Don't add any constraints that show a relationship with the top label.
In your code, if you have a subtitle, then just fill your labels and you’re good. If you don’t have a subtitle, then set the subtitle to hidden, and change the constant value of your titleLabel vertical constraint to 0 so it is centered. Q.E.D.
Here's the new code for the CustomCell class. Should have done this the first time around. 100% easier than the first solution I did (I was hopped-up on coffee). Hope this works for you.
// CustomCell.m
#import "CustomCell.h"
#interface CustomCell()
//IBOutlet to custom .xib file of UITableViewCell file
#property (weak, nonatomic) IBOutlet UILabel *titleLabel;
#property (weak, nonatomic) IBOutlet UILabel *subtitleLabel;
//This is the new outlet to the contraint.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *titleLabelVerticalConstraint;
#end
#implementation CustomCell
+ (NSString *)nibName
{
return #"CustomCell";
}
+ (NSString *)resuseIdentifier
{
return #"CustomCellReuseIdentifier";
}
- (void)setTitle:(NSString *)title
{
_title = title;
self.titleLabel.text = self.title;
}
- (void)setSubTitle:(NSString *)subTitle
{
_subTitle = subTitle;
self.subtitleLabel.text = self.subTitle;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
//1. If no subtitle, override current constraint
if (!self.subTitle) {
self.subtitleLabel.hidden = YES;
self.titleLabelVerticalConstraint.constant = 0;
}
}
#end
If it's a custom label, the easy fix here is to just use one label and add either 1 or 2 lines of attributed text. I just threw a project together and it works OK. I've put more explanation than you'll need (you already know how to subclass a table view cell, but for people who might need it, I've added a lot of detail).
Basically:
Subclass UITableViewCell and add a single label. Set your auto layout so the label is aligned vertically in the cell and set your left and right margins. You'll probably have to mess with auto layout to add padding to the top or bottom, but I'll leave the wrestling with auto layout to you lol
Create either 1 or 2 NSMutableAttributedStrings. If you have only 1 string, it will center in the label on one line, with auto layout fitting around the text. If you have two lines, just add a return character.
Note: This code assumes you will always have at least the title, with the subtitle being optional.
Here is the tableViewController.m code I used
#import "MyTableViewController.h"
#import "CustomCell.h"
#implementation MyTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//1. Register custom nib
[self.tableView registerNib:[UINib nibWithNibName:[CustomCell nibName] bundle:nil] forCellReuseIdentifier:[CustomCell resuseIdentifier]];
//2. Set a suggested height for auto-layout
self.tableView.estimatedRowHeight = 45;
}
#pragma mark - UITableView datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//1. Create an instance of the custom cell
CustomCell *cell = (CustomCell*)[self.tableView dequeueReusableCellWithIdentifier:[CustomCell resuseIdentifier] forIndexPath:indexPath];
//2. Setting some filler text (this would come from your data object)
if (indexPath.row == 0) {
cell.title = #"A cell with only title text";
} else {
cell.title = #"First we have the title";
cell.subTitle = #"And here is the subtitle";
}
return cell;
}
And this is the .h and .m for the custom UITableViewCell. Remember to subclass your prototype cell in storyboard to this class.
// CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell
+ (NSString *)nibName;
+ (NSString *)resuseIdentifier;
#property (strong, nonatomic) NSString *title;
#property (strong, nonatomic) NSString *subTitle;
#end
And finally the CustomCell.m. It's long, so you'll have to scroll through. Sorry about that.
// CustomCell.m
#import "CustomCell.h"
//1. Created a typeDef to identify which label we are dealing with
typedef NS_ENUM(NSInteger, CustomLabelType) {
CustomLabelTypeTitle = 0,
CustomLabelTypeSubtitle,
};
#interface CustomCell()
//IBOutlet to custom .xib file of UITableViewCell file
#property (weak, nonatomic) IBOutlet UILabel *customLabel;
#end
#implementation CustomCell
+ (NSString *)nibName
{
return #"CustomCell";
}
+ (NSString *)resuseIdentifier
{
return #"CustomCellReuseIdentifier";
}
- (void)setTitle:(NSString *)title
{
_title = title;
}
- (void)setSubTitle:(NSString *)subTitle
{
_subTitle = subTitle;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
//1. Add a line return after the title if we have a subtitle
if (self.subTitle) {
self.title = [NSString stringWithFormat:#"%#%#",self.title, #"\n"];
//2. Set the title to allow for 2 lines of text
self.customLabel.numberOfLines = 2;
}
NSMutableAttributedString *attTitle;
NSMutableAttributedString *attSubTitle;
//3. Set the title
if (self.title)
attTitle = [self _mutableStringWithText:self.title type:CustomLabelTypeTitle];
//4. If we have a subtitle, append it to the title attributed string
if (self.title && self.subTitle) {
attSubTitle = [self _mutableStringWithText:self.subTitle type:CustomLabelTypeSubtitle];
[attTitle appendAttributedString:attSubTitle];
}
//5. Set your label
[self.customLabel setAttributedText:attTitle];
}
- (NSMutableAttributedString *)_mutableStringWithText:(NSString *)labelText type:(CustomLabelType)labelType
{
//1. Create attributes for title vs subtitle
UIFont *labelFont = [UIFont systemFontOfSize: (labelType == CustomLabelTypeTitle) ? 16 : 12];
UIColor *textColor = (labelType == CustomLabelTypeTitle) ? [UIColor blackColor] : [UIColor grayColor];
//2. Create the paragraph style you want, including line spacing
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:6.5];
paragraphStyle.alignment = NSTextAlignmentLeft;
//3. Create your attributes dictionary
NSDictionary *paragraphAttributes = #{NSParagraphStyleAttributeName: paragraphStyle, NSFontAttributeName: labelFont, NSForegroundColorAttributeName:textColor};
//4. Create and return your string
NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:paragraphAttributes];
return mutableString;
}
#end
I've used the following code to make a cell indent from the left:
[cell setIndentationWidth:1];
[cell setIndentationLevel:15];
Unfortunately this offsets table view cell text labels when a cell contains a lot of text, so the problem here is that the ellipsis is the contents of the text label are further to the right and the ellipsis shows up further than usual when indenting from the left.
How can I make my UITableViewCell's textLabel have a right indent (or margin) as well?
I did the following (seems you can't just set the frame of the text label any other way).
Header (.h):
#interface UITableViewCellFixed : UITableViewCell
#property (nonatomic, assign) CGRect textLabelFrame;
#end
Implementation (.m):
#implementation UITableViewCellFixed : UITableViewCell
- (id)initWithLabelFrame:(CGRect)textLabelFrame {
self = [super init];
if (self)
self.textLabelFrame = textLabelFrame;
return self;
}
- (void) layoutSubviews {
[super layoutSubviews];
self.textLabel.frame = self.textLabelFrame;
}
#end
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
UITableViewCellFixed *cell = [[UITableViewCellFixed alloc] initWithLabelFrame:CGRectMake(30, 0, tableView.frame.size.width - 60, 50)];
...
}
I've created a custom UITableViewCell, but when I run my app on iPad the cell's content is the same width as on iPhone. I want the content - the background UIView for example - to be the complete width.
customCell.h
#import <UIKit/UIKit.h>
#interface customCell : UITableViewCell
#property (nonatomic, strong) UILabel *title;
#property (nonatomic, strong) UILabel *description;
#property (nonatomic, strong) UIView *background;
#end
customCell.m
#import "customCell.h"
#implementation customCell
#synthesize title = _title;
#synthesize description = _description;
#synthesize background = _background;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// configure background
self.background = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width, 115.0f)];
// configure title
self.title = [[UILabel alloc] initWithFrame:CGRectMake(5, 10, self.contentView.frame.size.width-10, 70)];
self.title.textAlignment = NSTextAlignmentNatural;
self.title.lineBreakMode = NSLineBreakByWordWrapping;
self.title.numberOfLines = 4;
self.title.preferredMaxLayoutWidth = 20;
self.title.adjustsFontSizeToFitWidth = NO;
self.title.textColor = [UIColor whiteColor];
self.title.font = [UIFont fontWithName:#"SourceSansPro-Regular" size:16];
[self.background addSubview:self.title];
// configure description
self.description = [[UILabel alloc] initWithFrame:CGRectMake(5, 80, self.contentView.frame.size.width-10, 20)];
self.description.textColor = [UIColor whiteColor];
self.description.textAlignment = NSTextAlignmentLeft;
self.description.font = [UIFont fontWithName:#"SourceSansPro-Bold" size:13];
[self.background addSubview:self.description];
[self addSubview:self.background];
[self sendSubviewToBack:self.background];
}
return self;
}
#end
What am I doing wrong here?
The cell's size is not yet set in the initWithStyle:reuseIdentifier: method. Either setup your subviews with proper autoresizingMask values or implement the cell's layoutSubviews method to update their sizes.
Also, since you add the title and description labels to the background view, the labels' sizes should be based on the size of the background view, not the size of the cell's contentView.
And lastly, never name a property description. It will conflict with the description method inherited from NSObject.
im making an app to sell tickets, there are different ticket types, for each ticket type i would like to ass a:
nameLabel UIStepper amountLabel priceLabel.
so those 4 views * ticket types.. added to the viewcontroller during runtime.
can i do this without doing it in a tableviewcontroller?
cant seem to add them dynamicly below eachother, any hints?
Im assuming your ticket is a UITableViewCell since you are mentioning "tableviewcontroller".
If thats the case your should make a subclass of UITableViewCell and add those 4 views to the subclassed cell.
So that your subclassed cell header would look something like:
#Import <UIKit/UIKit.h>
#interface TicketCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *nameLabel;
#property (weak, nonatomic) IBOutlet UIStepper *stepper;
#property (weak, nonatomic) IBOutlet UILabel *ammountLabel;
#property (weak, nonatomic) IBOutlet UILabel *priceLabel;
#end
Then you should set this class as your UITableViews prototype cell class in Interface Builder and then drag and drop the UILabels and the UIStepper into the prototype cell. After that you need to connect the outlets to the right UILabels and UIStepper.
And in your uitableviewcontroller you want to reuse this prototype
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId= #"PrototypeCellStoryboardIdentifier";
TicketCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[TicketCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
}
return cell;
}
and finally you want to set the number of rows in your table to the number of objects in your "number-of-ticket-types-array" like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [ticketTypes count];
}
if you don't want to use tableview you can do this by using UIScollView as follows
import "ViewController.h"
#interface ViewController ()
{
float y;
}
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
- (IBAction)newTicket:(UIButton *)sender;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
y=50.0;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)newTicket:(UIButton *)sender
{
UILabel * nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(10.0,y,50, 30)];
UILabel * priceLabel = [[UILabel alloc]initWithFrame:CGRectMake(10.0,y+32, 50, 30)];
UILabel * amountLabel = [[UILabel alloc]initWithFrame:CGRectMake(10.0,y+64, 50, 30)];
UIStepper * stepper = [[UIStepper alloc]initWithFrame:CGRectMake(10.0,y+96,50,30)];
nameLabel.text = #"name";
priceLabel.text = #"price";
amountLabel.text = #"amount";
[self.scrollView addSubview:nameLabel];
[self.scrollView addSubview:priceLabel];
[self.scrollView addSubview:amountLabel];
[self.scrollView addSubview:stepper];
y = y +130.0;
if (y>=self.view.frame.size.height)
{
self.scrollView.contentSize =CGSizeMake(320.0, y+120.0);
}
}
#end