The text is coming form a database. I would like to use it for a button and underline the text of the button. How can I do that?
In iOS 6, NSAttributedString is used modifying the text, you can use "NSMutableAttributedString" for multi color text, font, style, etc using single UIButton or UILabel.
NSMutableAttributedString *titleString = [[NSMutableAttributedString alloc] initWithString:#"The Underlined text"];
// making text property to underline text-
[titleString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(0, [titleString length])];
// using text on button
[button setAttributedTitle: titleString forState:UIControlStateNormal];
For this you can subclass UILabel and overwrite its -drawRect method and then use your own UILabel and add a UIButton over it of custom type.
Make your drawRect method in UILabel as
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 207.0f/255.0f, 91.0f/255.0f, 44.0f/255.0f, 1.0f);
CGContextSetLineWidth(context, 1.0f);
CGContextMoveToPoint(context, 0, self.bounds.size.height - 1);
CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height - 1);
CGContextStrokePath(context);
[super drawRect:rect];
}
In Swift 3 the following extension can be used for an underline:
extension UIButton {
func underlineButton(text: String) {
let titleString = NSMutableAttributedString(string: text)
titleString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSMakeRange(0, text.characters.count))
self.setAttributedTitle(titleString, for: .normal)
}
}
To make this a bit simpler (it's a common requirement) I've built a simple UIButton subclass called BVUnderlineButton that you can drop straight into your projects.
It's on Github at https://github.com/benvium/BVUnderlineButton (MIT licence).
You can use it in a XIB / Storyboard or direct via code.
Related
this is my first question on this message board so please go easy on me :)
A while ago I came across a useful piece of code to change a UILabel, this basically surounds the text in the label with a black (or an other color) outline.
- (void)drawTextInRect:(CGRect)rect; {
CGSize shadowOffset = self.shadowOffset;
UIColor *textColor = self.textColor;
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(c, 2);
CGContextSetLineJoin(c, kCGLineJoinRound);
CGContextSetTextDrawingMode(c, kCGTextStroke);
self.textColor = [UIColor blackColor];
[super drawTextInRect:rect];
CGContextSetTextDrawingMode(c, kCGTextFill);
self.textColor = textColor;
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];
self.shadowOffset = shadowOffset;
}
I successfully used this as a good template to subclass my UILabels, and now I would say I have a fair understanding on subclassing.
What I would like to do is use this subclass as the UILabel part of a UIButton so that the text within my buttons have a matching black outline.
Any help or even just being pointed in the right direction would be greatly appreciated.
Thanks
Dave
Why not just subclass UIButton, and then within that subclass make the same changes you made in your UILabel subclass to the button's label property. Basically you would do everything the exact same way, except all of your changes would refer to self.titleLabel instead of just self.
I used the following method to draw text in my custome cell, it's working fine but I just found that part of the text missing(Not showing all text in the cell):
- (void)drawContentView:(CGRect)rect {
UIColor * textColor = [UIColor blackColor];
if (self.selected || self.highlighted){
textColor = [UIColor whiteColor];
}
else
{
[[UIColor whiteColor] set];
UIRectFill(self.bounds);
}
[textColor set];
UIFont * textFont = [UIFont systemFontOfSize:16];
CGSize textSize = [text sizeWithFont:textFont constrainedToSize:rect.size];
[text drawInRect:CGRectMake(self.frame.size.width-(textSize.width+2 ) ,
(rect.size.height / 2) - (textSize.height / 2),
textSize.width, textSize.height) withFont:textFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentRight];
}
Thanks, please advice.
Try to make the space for drawing bigger than the textSize.width, textSize.heigh
UIFont * textFont = [UIFont systemFontOfSize:16];
CGSize sizeMe = CGSizeMake(300, rect.size.height*1.5);
CGSize textSize = [text sizeWithFont:textFont constrainedToSize:sizeMe];
[text drawInRect:CGRectMake(self.frame.size.width-(textSize.width+10 ) ,
(rect.size.height / 2) - (textSize.height / 2),
textSize.width, textSize.height+(textSize.height*1.5)) withFont:textFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentRight];
Perhaps you should change the line that determines text size to:
CGSize textSize = [text sizeWithFont:textFont constrainedToSize:rect.size lineBreakMode: NSLineBreakByWordWrapping];
You did not consider the lineBreakMode in sizeWithFont. You may want to use – sizeWithFont:constrainedToSize:lineBreakMode: instead for determine the actual size.
BTW, when your constraint is exactly the rect.size then the return value will never be larger than the actual rect.size. That may be what you want. Whenever I deal with strings of variable length in custom cells, I like to know whether the string fits in or not and may enlarge the individual cell (which requieres some more work of course).
If you do that then set the size.height of the constraints size to something very high. 10000.0f or so.
You are creating a custom cell .What is the need for drawing the text into it?That is the purpose of Label just add as the subview and use it.
drawInRect is a coregraphics drawing method
as per docs
Draws the string in the current graphics context using the specified
bounding rectangle and font. This method draws as much of the string
as possible using the given font and constraints. This method uses the
UILineBreakModeWordWrap line break mode and the UITextAlignmentLeft
alignment.
I dont see you get the context before drawing .Hence it doesnot have a valid context.and hence not drawing
So first, I needed to set the placeholder text color, so I subclassed the UITextfield as shown in several stack overflow posts. This works fine. Here is an example post of this: How do I subclass UITextField and override drawPlaceholderInRect to change Placeholder color.
But, when I try to use searchNameField.textAlignment = UITextAlignmentCenter; It is no longer centering the placeholder. The input text is still centered fine.
So then, assuming that the centering is not working because of the subclassing, what do I have to add to my UITextField subclass in order to have the placeholder text centered?
Thanks
Edit
Here is the code I used to solve this problem. This is placed inside my subclass of UITextField.
- (CGRect)placeholderRectForBounds:(CGRect)bounds
{
CGSize size = [[self placeholder] sizeWithFont:[UIFont fontWithName:#"Arial" size:placeholdTextSize]];
return CGRectMake( (bounds.size.width - size.width)/2 , bounds.origin.y , bounds.size.width , bounds.size.height);
}
Note that placeholdTextSize is a property that I set during initialization.
Here you go buddy
subclassing UITextField will do the work:
// CustomTextField.h
#interface CustomTextField : UITextField {
}
#end
override the methods:
#implementation
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
return CGRectMake(x,y,width,height);//Return your desired x,y position and width,height
}
- (void)drawPlaceholderInRect:(CGRect)rect {
//draw place holder.
[[self placeholder] drawInRect:rect withFont:[UIFont systemFontOfSize:12]];
}
#end
i think this will work (tested)
- (void) drawPlaceholderInRect:(CGRect)rect {
[[UIColor redColor] setFill];
[self.placeholder drawInRect:rect
withFont:self.font
lineBreakMode:UILineBreakModeTailTruncation
alignment:self.textAlignment];
}
https://github.com/mschulkind/cordova-true-native-ios/blob/master/Classes/UITextFieldPlugin.m
You can do this in UITextfield subclass
- (void)drawPlaceholderInRect:(CGRect)rect {
[[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.8] setFill];
[[self placeholder] drawInRect:rect withFont:[UIFont boldSystemFontOfSize:16.0] lineBreakMode:UILineBreakModeTailTruncation alignment:NSTextAlignmentCenter];
}
I am creating a UITextField programmatically and placing it inside a UIView. The font size is set to 15.0f (system font). But the placeholder that appears is not centered in the text view. Any one know how to resolve this?
I found some references on SO for blurred text etc and tried setting the frame of the textfield with integer values, but it doesn't make a difference.
UITextField *txtField = [[UITextField alloc] initWithFrame:CGRectMake(5.0f, 6.0f, 278.0f, 32.0f)];
[txtField setPlaceholder:#"My placeholder"];
[txtField setFont:[UIFont systemFontOfSize:15.0]];
[txtField setBorderStyle:UITextBorderStyleRoundedRect];
[txtField setAutocorrectionType:UITextAutocorrectionTypeNo];
[txtField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[txtField setKeyboardType:UIKeyboardTypeEmailAddress];
[txtField setReturnKeyType:UIReturnKeyDone];
[txtField setClearButtonMode:UITextFieldViewModeWhileEditing];
Thank you for any help
Note: I mean that the text is not centered vertically in the textfield (it is a bit towards the top). So setting the text alignment is not the solution.
Adding an image of the issue for clarification - as seen in the image, the placeholder text is more towards the top and not in the center vertically.
You need to add:
txtField.textAlignment = NSTextAlignmentCenter; // Pre-iOS6 SDK: UITextAlignmentCenter
Keep in mind, this adjusts both the alignment of the placeholder text as well as the text the user will enter in.
How to center vertically
Since the original question was updated to request how to vertically align the placeholder text and that answer is buried in the comments, here is how to do that:
txtField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
This does not work as expected on iOS7. On iOS7 you will have to override TextField class and
- (void) drawPlaceholderInRect:(CGRect)rect
method.
Like this:
- (void) drawPlaceholderInRect:(CGRect)rect
{
[[UIColor blueColor] setFill];
CGRect placeholderRect = CGRectMake(rect.origin.x, (rect.size.height- self.font.pointSize)/2, rect.size.width, self.font.pointSize);
[[self placeholder] drawInRect:placeholderRect withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment];
}
Works for both iOS7 and earlier versions.
I was using just the color, but we need to set the font as well.
This one worked for me:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:
#{
NSForegroundColorAttributeName:[UIColor whiteColor],
NSFontAttributeName: [UIFont systemFontOfSize:12]
}];
Changing the minimum line height using NSParagraphStyle was the only solution that worked for me:
NSMutableParagraphStyle *style = [self.addressBar.defaultTextAttributes[NSParagraphStyleAttributeName] mutableCopy];
style.minimumLineHeight = self.addressBar.font.lineHeight - (self.addressBar.font.lineHeight - placeholderFont.lineHeight) / 2.0;
self.addressBar.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Placeholder text" attributes:#{
NSForegroundColorAttributeName: [UIColor colorWithRed:79/255.0f green:79/255.0f blue:79/255.0f alpha:0.5f],
NSFontAttributeName : placeholderFont,
NSParagraphStyleAttributeName : style
}];
I am searching about drawing bordered text on UIView.
Implemented following method :
- (void)drawRect:(CGRect)rect {
//TODO draw bordered text here.
}
How to draw it ?
I mean each letter is bordered of whole text.
Thanks in advance.
To display bordered text (if I understand correctly what you want) you should set text drawing mode to kCGTextFillStroke (and set appropriate values for text drawing parameters, such as stroke and fill colors etc)
// Choose appropriate text font
CGContextSelectFont(context, [[UIFont boldSystemFontOfSize:24].fontName UTF8String], (int)fontSize, kCGEncodingMacRoman);
// Set text drawing mode
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
// Set appropriate color/line width values
// Here we're set to draw white letters with black border
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextSetRGBFillColor(context, 1, 1, 1, 1);
CGContextSetLineWidth(context, 1);
// Set this transformations or text will be displayed upside-down
CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(context, xform);
// Display text
CGContextShowTextAtPoint(...);
Edit: As Quartz does not work well with unicode, to draw unicode strings you'll need to use other APIs. I managed to draw "bordered" unicode string using NSAttributedString and OHAttributedLabel (thanks to this answer for that custom control). Sample code to get required string in some view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableAttributedString *s = [[NSMutableAttributedString alloc] initWithString:#"您好世界"];
[s addAttributes:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:-3.0f] forKey:(NSString*)kCTStrokeWidthAttributeName]
range:NSMakeRange(0, [s length])];
[s addAttributes:[NSDictionary dictionaryWithObject:(id)[UIColor greenColor].CGColor forKey:(NSString*)kCTStrokeColorAttributeName]
range:NSMakeRange(0, [s length])];
[s addAttributes:[NSDictionary dictionaryWithObject:(id)[UIColor redColor].CGColor forKey:(NSString*)kCTForegroundColorAttributeName]
range:NSMakeRange(0, [s length])];
[s setFont:[UIFont boldSystemFontOfSize:28.0f]];
[s setTextColor:[UIColor redColor]];
OHAttributedLabel *l = [[OHAttributedLabel alloc] initWithFrame:CGRectMake(40.0f, 40.0f, 200.0f, 80.0f)];
l.centerVertically = YES;
[l setAttributedText: s];
[self.view addSubview: l];
[l release];
}
Note that you'll need to link with CoreText.framework to make that work, and code uses some convenience methods provided in OHAttributedLabel implementation
I tried this way:
draw with NSString drawAtPoint:withFont: or drawInRect:withFont:
set line joint and lin cap to round.
draw your text with the border color using drawing mode kCGTextStroke, be sure to set the line width a little wider,
then draw your text with its inner color using drawing mode kCGTextFill.
may be you need a little adjustment in the position to make it perfect.