Add header to UIPickerView - ios

I created the UIPickerView with 4 components.
Can I add the header title for each component in that UIPickerView?
Thanks for any advice

Swift version, based on #greentor's answer with some improvements:
var labelTexts = ["Months", "Weeks", "Days", "Hours", "Minutes"]
override func viewDidAppear(animated: Bool) {
let labelWidth = itemPicker.frame.width / CGFloat(itemPicker.numberOfComponents)
for index in 0..<labelTexts.count {
let label: UILabel = UILabel.init(frame: CGRectMake(itemPicker.frame.origin.x + labelWidth * CGFloat(index), 0, labelWidth, 20))
label.text = labelTexts[index]
label.textAlignment = .Center
itemPicker.addSubview(label)
}
Note that this might work incorrectly if called in ViewWillAppear or earlier because the UIPickerView won't know its frame dimensions at that point yet.

One other technique I use from time to time is the make the header the first row in each column:
You need to increment the number of rows of course..

I show 3 components and then use a UIView to show a title (UILabel) centred above each component (you can easily amend this for more or fewer components):
-(void)labelForDays
{
NSString *strDay = #"Days";
float lblWidth = self.pickerDayHourMin.frame.size.width / self.pickerDayHourMin.numberOfComponents;
float lblXposition = self.pickerDayHourMin.frame.origin.x;
float lblYposition = (self.pickerDayHourMin.frame.origin.y);
UILabel *lblDay = [[UILabel alloc] initWithFrame:CGRectMake(lblXposition,
lblYposition,
lblWidth,
20)];
[lblDay setText:strDay];
[lblDay setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:lblDay];
}
Then a label for 2nd component
-(void)labelForHours
{
NSString *strHours = #"Hours";
float lblWidth = self.pickerDayHourMin.frame.size.width / self.pickerDayHourMin.numberOfComponents;
float lblXposition = self.pickerDayHourMin.frame.origin.x;
float lblYposition = (self.pickerDayHourMin.frame.origin.y);
UILabel *lblHours;
if (self.pickerDayHourMin.numberOfComponents ==3)
{
lblHours = [[UILabel alloc] initWithFrame:CGRectMake((lblXposition + lblWidth),
lblYposition,
lblWidth,
20)];
}
[lblHours setText:strHours];
[lblHours setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:lblHours];
}
and finally a label centred above the 3rd component
-(void)labelForMinutes
{
NSString *strMinute = #"Minutes";
float lblWidth = self.pickerDayHourMin.frame.size.width / self.pickerDayHourMin.numberOfComponents;
float lblXposition = self.pickerDayHourMin.frame.origin.x;
float lblYposition = (self.pickerDayHourMin.frame.origin.y);
UILabel *lblMinute;
if (self.pickerDayHourMin.numberOfComponents ==3)
{
lblMinute = [[UILabel alloc] initWithFrame:CGRectMake((lblXposition + lblWidth + lblWidth),
lblYposition,
lblWidth,
20)];
}
[lblMinute setText:strMinute];
[lblMinute setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:lblMinute];
}

You can use UIlabel above the UIPicker view,that works well

Related

iOS: How to adjust placement of adjacent UIView based on text in UILabel next to it

There are two UIImageView and two UILabel set up like the illustration above. Both UILabel's text will be populated via Web Data and could be any length.
When the "Something" label inevitably gets populated with something longer than "something", the UIImageView to it's immediate right needs to move to the right based on the amount of text inside the "something" label.
How would one go about doing this?
Although please use auto layouts, here is a programmatic way of handling this:
// Image before Something text
UIImageView *somethingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(5.0, 10.0, 40, 40)];
CGFloat somethingLabelXM = 5.0;
NSString *somethingLabelText = #"Random Text";
CGFloat somethingLabelTextW = [somethingLabelText sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:CGSizeMake(MAXFLOAT, 1000) lineBreakMode:NSLineBreakByTruncatingTail].width;
// Something text
UILabel *somethingLabel = [[UILabel alloc] initWithFrame:CGRectMake(somethingImageView.frame.origin.x + somethingImageView.frame.size.width + somethingLabelXM, somethingImageView.frame.origin.y, somethingLabelTextW, 40.0)];
somethingLabel.text = somethingLabelText;
UIImage *moreImage = [UIImage imageNamed:#"SomeImage"];
// Image after Something text
UIImageView *moreImageView = [[UIImageView alloc] initWithFrame:CGRectMake(somethingLabel.frame.origin.x + somethingLabel.frame.size.width + somethingLabelXM, somethingImageView.frame.origin.y, moreImage.size.width, moreImage.size.height)];
moreImageView.image = moreImage;
// More text
NSString *moreLabelText = #"Random Text";
CGFloat moreLabelTextW = [moreLabelText sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:CGSizeMake(MAXFLOAT, 1000) lineBreakMode:NSLineBreakByTruncatingTail].width;
UILabel *moreLabel = [[UILabel alloc] initWithFrame:CGRectMake(moreImageView.frame.origin.x + moreImageView.frame.size.width + somethingLabelXM, somethingImageView.frame.origin.y, moreLabelTextW, 40.0)];
somethingLabel.text = moreLabelText;

Integer and string won't right pad.. Objective C

The code is below. What ends up happening is it's as if I used leftPadding instead of rightPadding and a string or long integer will run of the screen to the right. What I want is for the string is pad itself on the right and it's length extends to the left..
- (void)constructTimeStampLabel {
CGFloat rightPadding = 250.f;
CGFloat topPadding = -30.f;
CGRect frame = CGRectMake(rightPadding,
topPadding,
floorf(CGRectGetWidth(__informationView.frame)),
CGRectGetHeight(__informationView.frame) - topPadding);
_timeStampLabel = [[UILabel alloc] initWithFrame:frame];
_timeStampLabel.text = [NSString stringWithFormat:#"Sent on %#", _feedItem.timeStamp];
_timeStampLabel.textColor = [UIColor whiteColor];
[_timeStampLabel setFont:[UIFont systemFontOfSize:12]];
[__informationView addSubview:_timeStampLabel];
}
try setting the alignment to the right.
_timeStampLabel.textAlignment = NSTextAlignmentRight;

how create uilabel's dynamically from an NSMutableArray?

NSMutableArray *items // contains 15 items
I need to put one down label from another i try something like this but not work
int count=20;
for(int i = 0; i < [items count]; i++){
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(0,0,0,count)];
label.text = #"text"; //etc...
count+=20;
[_scroll addSubview:label];
}
What can i do thanks
You need to set the frame properly.
int count=20;
for(int i = 0; i < [items count]; i++){
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(0,count,0,0)];
label.text = #"text"; //etc...
[label sizeToFit]; // resize the width and height to fit the text
count+=20;
[_scroll addSubview:label];
}
As suggested by rmaddy...adding a new line to adjust the height of the label as well, assumed that you have an NSMutableArray object 'items' containing strings.
float previousLabelHeight = 0.0;
for(int i = 0; i < [items count]; i++){
CGSize theSize = [[items objectAtIndex: i] sizeWithFont:[UIFont systemFontOfSize:17.0] constrainedToSize:CGSizeMake(320, FLT_MAX) lineBreakMode:UILineBreakModeWordWrap]; //can adjust width from 320 to whatever you want and system font as well
float newLabelHeight = previousLabelHeight + theSize.height;
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(0,newLabelHeight,0,0)];
label.text = [items objectAtIndex: i];
[label sizeToFit]; // resize the width and height to fit the text
previousLabelHeight = newLabelHeight + 5 //adding 5 for padding
[_scroll addSubview:label];
}
Cheers,
Happy Coding.
I think you're trying to change the frame's Y value, but the last parameter of CGRectMake() is the rect's height. You want the second parameter.
Here is the Swift version to add labels dynamically from array..
var previousLabelHeight: CGFloat = 0.0;
for dict in items {
let text: String = "Some text to display in the UILabel"
let size = heightNeededForText(text as NSString, withFont: UIFont.systemFontOfSize(15.0), width: scrollView.frame.size.width - 20, lineBreakMode: NSLineBreakMode.ByWordWrapping)
let newLabelHeight = previousLabelHeight + size;
let label = UILabel(frame: CGRectMake(0, newLabelHeight, 0, 0))
label.text = text
label.sizeToFit() // resize the width and height to fit the text
previousLabelHeight = newLabelHeight + 5 //adding 5 for padding
scroll.addSubview(label)
}
As sizeWithFont: ConstraintedToSize is deprecated from ios 7.0,
we have to use boundingRectWithSize method from NSString....
func heightNeededForText(text: NSString, withFont font: UIFont, width: CGFloat, lineBreakMode:NSLineBreakMode) -> CGFloat {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = lineBreakMode
let size: CGSize = text.boundingRectWithSize(CGSizeMake(width, CGFloat.max), options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: [ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle], context: nil).size//text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MA
return ceil(size.height);
}

Multiple lines of text in UILabel

Is there a way to have multiple lines of text in UILabel like in the UITextView or should I use the second one instead?
Set the line break mode to word-wrapping and the number of lines to 0:
// Swift
textLabel.lineBreakMode = .byWordWrapping
textLabel.numberOfLines = 0
// Objective-C
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
// C# (Xamarin.iOS)
textLabel.LineBreakMode = UILineBreakMode.WordWrap;
textLabel.Lines = 0;
Restored old answer (for reference and devs willing to support iOS below 6.0):
textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;
On the side: both enum values yield to 0 anyway.
In IB, set number of lines to 0 (allows unlimited lines)
When typing within the text field using IB, use "alt-return" to insert a return and go to the next line (or you can copy in text already separated out by lines).
The best solution I have found (to an otherwise frustrating problem that should have been solved in the framework) is similar to vaychick's.
Just set number of lines to 0 in either IB or code
myLabel.numberOfLines = 0;
This will display the lines needed but will reposition the label so its centered horizontally (so that a 1 line and 3 line label are aligned in their horizontal position). To fix that add:
CGRect currentFrame = myLabel.frame;
CGSize max = CGSizeMake(myLabel.frame.size.width, 500);
CGSize expected = [myString sizeWithFont:myLabel.font constrainedToSize:max lineBreakMode:myLabel.lineBreakMode];
currentFrame.size.height = expected.height;
myLabel.frame = currentFrame;
Use this to have multiple lines of text in UILabel:
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
Swift:
textLabel.lineBreakMode = .byWordWrapping
textLabel.numberOfLines = 0
myUILabel.numberOfLines = 0;
myUILabel.text = #"your long string here";
[myUILabel sizeToFit];
If you have to use the:
myLabel.numberOfLines = 0;
property you can also use a standard line break ("\n"), in code, to force a new line.
You can use \r to go to next line while filling up the UILabel using NSString.
UILabel * label;
label.text = [NSString stringWithFormat:#"%# \r %#",#"first line",#"seconcd line"];
lets try this
textLabel.lineBreakMode = NSLineBreakModeWordWrap; // UILineBreakModeWordWrap deprecated
textLabel.numberOfLines = 0;
textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;
The solution above does't work in my case. I'm doing like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// ...
CGSize size = [str sizeWithFont:[UIFont fontWithName:#"Georgia-Bold" size:18.0] constrainedToSize:CGSizeMake(240.0, 480.0) lineBreakMode:UILineBreakModeWordWrap];
return size.height + 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
// ...
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:#"Georgia-Bold" size:18.0];
}
// ...
UILabel *textLabel = [cell textLabel];
CGSize size = [text sizeWithFont:[UIFont fontWithName:#"Georgia-Bold" size:18.0]
constrainedToSize:CGSizeMake(240.0, 480.0)
lineBreakMode:UILineBreakModeWordWrap];
cell.textLabel.frame = CGRectMake(0, 0, size.width + 20, size.height + 20);
//...
}
Swift 3
Set number of lines zero for dynamic text information, it will be useful for varying text.
var label = UILabel()
let stringValue = "A label\nwith\nmultiline text."
label.text = stringValue
label.numberOfLines = 0
label.lineBreakMode = .byTruncatingTail // or .byWrappingWord
label.minimumScaleFactor = 0.8 . // It is not required but nice to have a minimum scale factor to fit text into label frame
Use story borad : select the label to set number of lines to zero......Or Refer this
Try using this:
lblName.numberOfLines = 0;
[lblName sizeToFit];
UILabel *helpLabel = [[UILabel alloc] init];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:label];
helpLabel.attributedText = attrString;
// helpLabel.text = label;
helpLabel.textAlignment = NSTextAlignmentCenter;
helpLabel.lineBreakMode = NSLineBreakByWordWrapping;
helpLabel.numberOfLines = 0;
For some reasons its not working for me in iOS 6 not sure why. Tried it with and without attributed text. Any suggestions.
Method 1:
extension UILabel {//Write this extension after close brackets of your class
func lblFunction() {
numberOfLines = 0
lineBreakMode = .byWordWrapping//If you want word wraping
//OR
lineBreakMode = .byCharWrapping//If you want character wraping
}
}
Now call simply like this
myLbl.lblFunction()//Replace your label name
EX:
Import UIKit
class MyClassName: UIViewController {//For example this is your class.
override func viewDidLoad() {
super.viewDidLoad()
myLbl.lblFunction()//Replace your label name
}
}//After close of your class write this extension.
extension UILabel {//Write this extension after close brackets of your class
func lblFunction() {
numberOfLines = 0
lineBreakMode = .byWordWrapping//If you want word wraping
//OR
lineBreakMode = .byCharWrapping//If you want character wraping
}
}
Method 2:
Programmatically
yourLabel.numberOfLines = 0
yourLabel.lineBreakMode = .byWordWrapping//If you want word wraping
//OR
yourLabel.lineBreakMode = .byCharWrapping//If you want character wraping
Method 3:
Through Story board
To display multiple lines set 0(Zero), this will display more than one line in your label.
If you want to display n lines, set n.
See below screen.
If you want to set minimum font size for label Click Autoshrink and Select Minimum Font Size option
See below screens
Here set minimum font size
EX: 9 (In this image)
If your label get more text at that time your label text will be shrink upto 9
These things helped me
Change these properties of UILabel
label.numberOfLines = 0;
label.adjustsFontSizeToFitWidth = NO;
label.lineBreakMode = NSLineBreakByWordWrapping;
And while giving input String use \n to display different words in different lines.
Example :
NSString *message = #"This \n is \n a demo \n message for \n stackoverflow" ;
Swift 4:
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.preferredMaxLayoutWidth = superview.bounds.size.width - 10
UILabel *labelName = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
[labelName sizeToFit];
labelName.numberOfLines = 0;
labelName.text = #"Your String...";
[self.view addSubview:labelName];
You can do that via the Storyboard too:
Select the Label on the view controller
In the Attribute Inspector, increase the value of the Line option (Press Alt+Cmd+4 to show Attributes Inspector)
Double click the Label in the view controller and write or paste your text
Resize the Label and/or increase the font size so that the whole text could be shown
you should try this:
-(CGFloat)dynamicLblHeight:(UILabel *)lbl
{
CGFloat lblWidth = lbl.frame.size.width;
CGRect lblTextSize = [lbl.text boundingRectWithSize:CGSizeMake(lblWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:lbl.font}
context:nil];
return lblTextSize.size.height;
}
Oh, in 2021 I'm trapped by a label text unable to change lines for 1 hour, then realize I forget to set label's width, WTF.
let stepLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.text = "Put your device and computer under same Wi-Fi network."
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(stepLabel)
NSLayoutConstraint.activate([
stepLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stepLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stepLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.7)
])
}
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 30)];
[textLabel sizeToFit];
textLabel.numberOfLines = 0;
textLabel.text = #"Your String...";
Already answered, but you can do it manually in the storyboard too. Under Attributes Inspector for the Label, you can change Line Breaks to Word Wrap (or character wrap).
In this function pass string that you want to assign in label and pass font size in place of self.activityFont and pass label width in place of 235, now you get label height according to your string.
it will work fine.
-(float)calculateLabelStringHeight:(NSString *)answer
{
CGRect textRect = [answer boundingRectWithSize: CGSizeMake(235, 10000000) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:self.activityFont} context:nil];
return textRect.size.height;
}
Set below either in code or in storyboard itself
Label.lineBreakMode = NSLineBreakByWordWrapping;
Label.numberOfLines = 0;
and please don't forget to set left, right, top and bottom constraints for label otherwise it won't work.
On C#, this worked for me inside UITableViewCell.
UILabel myLabel = new UILabel();
myLabel.Font = UIFont.SystemFontOfSize(16);
myLabel.Lines = 0;
myLabel.TextAlignment = UITextAlignment.Left;
myLabel.LineBreakMode = UILineBreakMode.WordWrap;
myLabel.MinimumScaleFactor = 1;
myLabel.AdjustsFontSizeToFitWidth = true;
myLabel.InvalidateIntrinsicContentSize();
myLabel.Frame = new CoreGraphics.CGRect(20, mycell.ContentView.Frame.Y + 20, cell.ContentView.Frame.Size.Width - 40, mycell.ContentView.Frame.Size.Height);
myCell.ContentView.AddSubview(myLabel);
I think the point here is:-
myLabel.TextAlignment = UITextAlignment.Left;
myLabel.LineBreakMode = UILineBreakMode.WordWrap;
myLabel.MinimumScaleFactor = 1;
myLabel.AdjustsFontSizeToFitWidth = true;
This code is returning size height according to text
+ (CGFloat)findHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font
{
CGFloat result = font.pointSize+4;
if (text)
{
CGSize size;
CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, 999)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
size = CGSizeMake(frame.size.width, frame.size.height+1);
result = MAX(size.height, result); //At least one row
}
return result;
}

iOS - Add Badge to UITableViewCell

How do I add a badge to UITableViewCell, like this:
alt text http://img17.imageshack.us/img17/9974/img0001ac9.png
Should I simply add a subview with a text and label on it?
Here's a swift enhancement to #POF's answer. We don't need as many subviews and we can use math to support N digits, not just 1-3:
func setDiscountBadge(count: Int) {
let size: CGFloat = 26
let digits = CGFloat( count("\(number)") ) // digits in the label
let width = max(size, 0.7 * size * digits) // perfect circle is smallest allowed
let badge = UILabel(frame: CGRectMake(0, 0, width, size))
badge.text = "\(number)"
badge.layer.cornerRadius = size / 2
badge.layer.masksToBounds = true
badge.textAlignment = .Center
badge.textColor = UIColor.whiteColor()
badge.backgroundColor = cfg.UIColors.brand
YOURCELL.accessoryView = badge // !! change this line
}
And the result (I use a brand color, but yours can be any color):
TDBadgedCell is a pretty good choice. Highly customizable for your needs.
As for me the simplest way is to use cell.accessoryView. Please look into my code how I did it:
UIImageView * commentsViewBG = [[UIImageView alloc] initWithImage: [UIImage imageNamed: #"counter1.png"]];
commentsViewBG.frame = CGRectMake(
commentsViewBG.frame.origin.x,
commentsViewBG.frame.origin.y, 30, 20);
UILabel *commentsCount;
if (commentsArray.totalCount < 10)
commentsCount = [[UILabel alloc]initWithFrame:CGRectMake(10, -10, 40, 40)];
else if (commentsArray.totalCount < 100)
commentsCount = [[UILabel alloc]initWithFrame:CGRectMake(5, -10, 40, 40)];
else if (commentsArray.totalCount < 1000)
{
commentsViewBG.frame = CGRectMake(
commentsViewBG.frame.origin.x,
commentsViewBG.frame.origin.y, 40, 20);
commentsCount = [[UILabel alloc]initWithFrame:CGRectMake(5, -10, 40, 40)];
}
commentsCount.text = [NSString stringWithFormat:#"%ld",(long)commentsArray.totalCount];
commentsCount.textColor = [UIColor whiteColor];
commentsCount.backgroundColor = [UIColor clearColor];
[commentsViewBG addSubview:commentsCount];
cell.accessoryView = commentsViewBG;
And my result:
Hope it helps.
Yes, there is currently no supported way of adding a badge to a UITableView Cell. In this example, it is most likely a custom subview which contains an image and UILabel.
I'd like to add another alternative to create customized Badges. CustomBadge is a little bit more powerful. It's open and for free.

Resources