iOS UIButton with multiple labels - ios

I have a UI button that I'd like to put two labels on it, similar to how a cell has a title text and detail text.
I'd like the button to have a larger font for the main text, and have smaller detail text under that.
Is this possible? I've tried to put multiple lines on a button, but I need to have different text sizes for each line, so setting the lineBreakMode and numberOfLines of the titleLabel doesn't really quite work.

Here's the code we finally used. Assistance from John Wang.
Thanks to everyone for the suggestions!
// Formats a label to add to a button. Supports multiline buttons
// Parameters:
// button - the button to add the label to
// height - height of the label. usual value is 44
// offset - the offset from the top of the button
// labelText - the text for the label
// color - color of the text
// formatAsBold - YES = bold NO = normal weight
// tagNumber - tag for the label
- (void) formatLabelForButton: (UIButton *) button withHeight: (double) height andVerticalOffset: (double) offset andText: (NSString *) labelText withFontSize: (double) fontSize withFontColor: (UIColor *) color andBoldFont:(BOOL) formatAsBold withTag: (NSInteger) tagNumber {
// Get width of button
double buttonWidth= button.frame.size.width;
// Initialize buttonLabel
UILabel *buttonLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, offset, buttonWidth, height)];
// Set font size and weight of label
if (formatAsBold) {
buttonLabel.font = [UIFont boldSystemFontOfSize:fontSize];
}
else {
buttonLabel.font = [UIFont systemFontOfSize:fontSize];
}
// set font color of label
buttonLabel.textColor = color;
// Set background color, text, tag, and font
buttonLabel.backgroundColor = [UIColor clearColor];
buttonLabel.text = labelText;
buttonLabel.tag = tagNumber;
// Center label
buttonLabel.textAlignment = UITextAlignmentCenter;
// Add label to button
[button addSubview:buttonLabel];
[buttonLabel autorelease];
} // End formatLabelForButton

A trick I would recommend is putting a UIButton with a transparent interior on top of UILabels. I've used this trick before and, although it may present some problems in terms of maintenance and i18n, it works like a charm.
Here is a 5 minutes sample using the suggestion above.
Given more time, you can make a better label with round corners.

you should be able to add subviews to it. Since everything is a view, everything can potentially have subviews.
I would subclass it and put the labels on it within the subclass, Then you can extend properties for text and subtext to change their values.
Not saying it can 100% work. But off the top of my head. UIView can have SubViews

Related

how to make a rectangle at run time to fit a dragged label of words in it objective c

I am making a words match app in iOS in which i have two parts of words strings and I want to make a complete word from two labels of random words so for all is fine.
Now I want to make a rectangle at run time as a target of draggable label, when I click on label to drag it the rectangle should become hi-lighted with the same size as the size of label of words.
How can i achieve this in objective-C?
For more clearness you can see in image where I want to make this green rectangle at run time to drop the right side labels in it
The left side labels are not moveable and should always in the rectangle as you see in given image.The code so far i try to make the rectangle as a UIView in viewDidLoad as
for(int i = 0; i <5;i++){
customView = [[UIView alloc]initWithFrame:CGRectMake(10,y,50, 30)];
customView.backgroundColor = [UIColor greenColor];
[gameLayer addSubview:customView];
y = y+40;
}
But this is not what i actually want. Any help appreciated...
Finally i got the rectangle size same as the size of tapped label as here, i make an array in .h file which contain the reference of my target rectangle NSMutableArray *rectangleLabels
after that i make the size of rectangle same as the size of my draggable labels using a loop in tapped gestures method and it works fine...
-(void)gotTapped:(Id)sender {
for (UIView *v in rectangleLabels) {
v.hidden = !v.hidden;
UILabel *tapLbl = (UILabel *)[sender view];
CGRect rect = tapLbl.frame;
for(int i=0;i<rectangleLabels.count;i++) {
UILabel *lblChange = (UILabel *)[rectangleLabels objectAtIndex:i];
lblChange.frame = CGRectMake(lblChange.frame.origin.x, lblChange.frame.origin.y, rect.size.width, rect.size.height);
}
}
}

Center a UIButton's title vertically for words longer than its width

I want to implement a UIButton so the title appears centered inside, no matter the length of the text.
The problem I'm facing is that the button's width and the font size need to be of a fixed value because they need to be consistent with the rest of the UI details. And I can't truncate the text either.
I am fine with splitting words, but only when the word that does not fit the title's width.
Currently it's working fine for 1-line and 2-line texts (with spaces) but when the title contains one long word without spaces, it centers the first line only (please see the images attached).
I guess I would like to do something like:
if (button.currentTitle.length > (buttonWidth/characterWidth)) { //2-line title buttons
// Do something special to fix the problem
}
But I've tried setting all these and non of them worked:
[button.titleLabel setTextAlignment:NSTextAlignmentCenter];
[button.titleLabel setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 20, 0)];
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
Any ideas/suggestions to keep the titleLabel vertically centered?
You can wrap the title by characters, setting your button's line break mode to NSLineBreakByCharWrapping (by default it wraps at word boundaries), only when it contains words that do not fit.
if (button.currentTitle.length > (buttonWidth/characterWidth)) { //2-line title buttons
// Check if title contains long words
NSArray *words = [button.currentTitle componentsSeparatedByString:#" "];
for (NSString *word in words) {
if (word.length > (buttonWidth/characterWidth)) {
// Set the line break mode to char wrapping
button.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
break; // No need to continue :-)
}
}
}

Text Alignment issue when I set the custom font

When I set the custom font for the segmented control then it changes the vertical text alignment. I am using below code to set the font .
// I dont think these lines are creating any issue but just wanted to paste all the code
self.segmentType.layer.borderColor = navigationTintColor.CGColor;
self.segmentType.layer.cornerRadius = 0.0;
self.segmentType.layer.borderWidth = 1.5;
// These are the lines that are changing the text alignment
UIFont *font = [UIFont fontWithName:ftHelveticaNeueLTPro_Th size:13.5];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font
forKey:UITextAttributeFont];
[self.segmentType setTitleTextAttributes:attributes
forState:UIControlStateNormal];
Here is the screenshot of whats is happening . If you observer, the text is not vertically centre aligned .
Please help me . Thank you in advance !!
The below code suggested by #Emmanuel works perfectly fine. You can change the vertical offset to align the text vertically at the center .
[self.segmentType setContentPositionAdjustment:UIOffsetMake(0, 2) forSegmentType:UISegmentedControlSegmentAny barMetrics:UIBarMetricsDefault];
Can you please try it using custom UILabel on custom view on it. Change & modify frame value of either titleLabel or customSegmentView as per convenience on actual view. And add this whole view as subview on your segmented control.
UIView *customSegmentView = [[UIView alloc] init];
UILabel *segmentTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 7.0f,180.0f,22.6f)];
segmentTitleLabel.text = #"your-text";
segmentTitleLabel.backgroundColor = [UIColor clearColor];
segmentTitleLabel.textAlignment = UITextAlignmentCenter;
segmentTitleLabel.font = [UIFont fontWithName:#"ftHelveticaNeueLTPro_Th" size:13.5f];
customSegmentView.frame = CGRectMake(60, 20, 180, 35);
[customSegmentView addSubview:segmentTitleLabel];
[self.segmentType setTitleView:customSegmentView];
Hope that will work for your issue. Please check and let me know if we have to go with another solution.
In InterfaceBuilder on XCode 6 there is a Content Offset control for the segments, which affects the baseline of the text. I had this problem because my Content Offset was 2 in the Y dimension instead of 0.

Set UILabel Align top is not working in the cell

I have a problem to implement the text vertical alignment inside a table cell.
What I want to do is based on the length of the text I want to display a message top aligned in side one UILabel inside a cell.
For example if the message is only one line
The text should align top:
And if there are two rows then it should look like this:
At the beginning what I can see is like this
So I have searched the web and what I found is to
use the
[label1 sizeToFit];
But the problem with that is within the table view cell it is not always necessarily called especially when I switched to and from another tab view.
Then I tried to generate the label on the fly by code, but the problem is that let alone the complicated process of setting up the font format I want. I have to manage whether the label has been inserted or not then reuse it every time cellForRowAtIndexpath is called.
And more weirdly, once I select the row. The alignment is switched from the one you see in the first picture to the third one. It also happens when I switched to a different tab view and switch back to the view.
I was wondering if anybody has encountered such issue and have a solution to the problem.
Thank you for your reply in advance.
Edit:
#βḧäṙℊặṿῗ, what you said I have tried. It successfully align the label text if there is only one line. My situation is that, since I have multiple tab views. Once I switch back and forth between tabs view. The alignment just restored to centre-vertical alignment again. It also happens when I selected the row. Any idea?
Try this
// label will use the number of lines as per content
[myLabel setNumberOfLines:0]; // VERY IMP
[myLabel sizeToFit];
EDIT:
As you have one extra condition that maximumly display two lines then you need to set setNumberOfLines: to 2
[myLabel setNumberOfLines:2];
Create UILabel+Extras and add following methods to this class.
- (void)alignTop{
CGSize fontSize = [self.text sizeWithAttributes:#{NSFontAttributeName:self.font}];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGRect rect = [self.text boundingRectWithSize:CGSizeMake(finalWidth, finalHeight) options:NSStringDrawingTruncatesLastVisibleLine attributes:#{NSFontAttributeName:self.font} context:nil];
CGSize theStringSize = rect.size;
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:#" \n"];
}
Call this method like this..
[YOUR_LABEL alignTop];
Either You set no of Lines to be 0 like
[yourLabelObject setNumberOfLines:0];
[yourLabelObject sizeToFit];
Or
You can find the height of label at run time depending upon textString length.
Following method will return you the size(height & width) of label for length of text string.
here width is fixed and only height will change :
- (CGSize) calculateLabelHeightWith:(CGFloat)width text:(NSString*)textString andFont:(UIFont *)txtFont
{
CGSize maximumSize = CGSizeMake(width, 9999);
CGSize size = [textString sizeWithFont:txtFont
constrainedToSize:maximumSize
lineBreakMode:UILineBreakModeWordWrap];
return size;
}
Yo need to calculate frame of label each time when u r doing to set text and set frame of label
I hope this will helps you.
Might sound a bit silly but this is my approach: For any field that needs to be top aligned I fill the text up with multiple "\n"s. This causes the text to be automatically top aligned. Pretty much the same as Mehul's method above.
http://i.stack.imgur.com/8u5q4.png

Split the full contents of cell between UILabel and UIButton

I've got a subclassed UITableViewCell. I'm dynamically adding a UILabel and UIButton to it.
Right now I've overridden layoutSubviews and am setting the x,y absolutely of the button and label. To be able to accommodate both screen layouts as well as larger screens I'd like to make this automatic. Is there a way to tell the label to "float left" and the button to "float right?" Ideally the label should use up all space that the button doesn't need (the button is going to be a fixed size for the most part).
this property of uiview should get you started
You can try something like this assuming cellLbl is the UILabel and cellBtn is the UIButton:
- (void) layoutSubviews
{
CGRect rctFrm;
CGFloat flW;
CGFloat flH;
int iSpacing = 4; // This could be fixed for a percentage of cell width
[super layoutSubviews];
flW = self.contentView.bounds.size.width;
flH = self.contentView.bounds.size.height;
rctFrm = self.cellBtn.frame;
flW -= rctFrm.size.width + iSpacing;
rctFrm.origin.x = flW; // Right justify button
rctFrm.origin.y = (flH - rctFrm.size.height) / 2; // Center button vertically
[self.cellBtn setFrame:rctFrm];
rctFrm = self.cellLbl.frame;
rctFrm.origin.x = iSpacing;
rctFrm.size.width = flW - (2 * iSpacing);
// You can adjust UILabel vertical position and height if desired
[self.cellLbl setFrame:rctFrm];
}

Resources