我在
UISegmentedControl
内使用 UIToolBar
作为按钮。我无法使用普通的UIButtonBarItem
,因为我需要设置tintColor
并支持iOS 4.3。
所以我使用以下代码:
UISegmentedControl* searchButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"", nil]];
[searchButton setImage:[UIImage imageNamed:@"search_picto"] forSegmentAtIndex:0];
searchButton.momentary = YES;
searchButton.segmentedControlStyle = UISegmentedControlStyleBar;
searchButton.tintColor = [UIColor colorWithRed:0.27 green:0.60 blue:0.20 alpha:1.00];
[searchButton addTarget:self action:@selector(actionSearch:) forControlEvents:UIControlEventValueChanged];
这很好用,但是有没有办法可以在图像旁边添加文本/标题? setTitle: 方法删除图像。一定还有其他方法...
感谢您的帮助。
--
编辑: 我决定将文本直接添加到
UIImageView
上,如下所示:
NSString* label = @"My Label";
UIImage* image = [self addText:label toImage:[UIImage imageNamed:@"icon"]];
[_segmentedControl insertSegmentWithImage:image atIndex:0 animated:NO];
[_segmentedControl setWidth:image.size.width + 10]; // add some margin on the right
- (UIImage *)addText:(NSString *)text toImage:(UIImage *)image {
UIFont* font = [UIFont boldSystemFontOfSize: 12];
CGSize expectedSize = [text sizeWithFont:font];
[self retinaAwareUIGraphicsBeginImageContext:CGSizeMake(image.size.width + expectedSize.width + 10, image.size.height)];
[image drawAtPoint: CGPointZero];
[[UIColor whiteColor] set];
[text drawAtPoint: CGPointMake(30, 2) withFont:font];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (void)retinaAwareUIGraphicsBeginImageContext:(CGSize) size {
CGFloat scale = -1.0;
if (scale<0.0) {
UIScreen *screen = [UIScreen mainScreen];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.0) {
scale = [screen scale];
}
else {
scale = 0.0;
}
}
if (scale>0.0) {
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
}
else {
UIGraphicsBeginImageContext(size);
}
}
你可以做到:
为 UIImage 添加类别:
在UIImage+UISegmentIconAndText.h中
@interface UIImage (UISegmentIconAndText)
+ (id) imageFromImage:(UIImage*)image string:(NSString*)string color:(UIColor*)color;
+ (id) imageFromImage:(UIImage*)image string:(NSString*)string color:(UIColor*)color position:(NSString*)position;
@end
在 UIImage+UISegmentIconAndText.m
#import "UIImage+UISegmentIconAndText.h"
@implementation UIImage (UISegmentIconAndText)
+ (id) imageFromImage:(UIImage*)image string:(NSString*)string color:(UIColor*)color
{
UIFont *font = [UIFont systemFontOfSize:16.0];
CGSize expectedTextSize = [string sizeWithAttributes:@{NSFontAttributeName: font}];
int width = expectedTextSize.width + image.size.width + 5;
int height = MAX(expectedTextSize.height, image.size.width);
CGSize size = CGSizeMake((float)width, (float)height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
int fontTopPosition = (height - expectedTextSize.height) / 2;
CGPoint textPoint = CGPointMake(image.size.width + 5, fontTopPosition);
[string drawAtPoint:textPoint withAttributes:@{NSFontAttributeName: font}];
// Images upside down so flip them
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, size.height);
CGContextConcatCTM(context, flipVertical);
CGContextDrawImage(context, (CGRect){ {0, (height - image.size.height) / 2}, {image.size.width, image.size.height} }, [image CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
在你的代码中实现Segment:
UIImage *imageWithText = [UIImage imageFromImage:[UIImage imageNamed:@"images/jobaids_tab_icon"] string:@"Hello", nil) color:[UIColor whiteColor]];
[_segmentedController setImage:imageWithText forSegmentAtIndex:0];
斯威夫特5
对于我们这些喜欢尽可能使用现代 API 的人来说:
extension UIImage {
static func textEmbeded(image: UIImage,
string: String,
isImageBeforeText: Bool,
segFont: UIFont? = nil) -> UIImage {
let font = segFont ?? UIFont.systemFont(ofSize: 16)
let expectedTextSize = (string as NSString).size(withAttributes: [.font: font])
let width = expectedTextSize.width + image.size.width + 5
let height = max(expectedTextSize.height, image.size.width)
let size = CGSize(width: width, height: height)
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { context in
let fontTopPosition: CGFloat = (height - expectedTextSize.height) / 2
let textOrigin: CGFloat = isImageBeforeText
? image.size.width + 5
: 0
let textPoint: CGPoint = CGPoint.init(x: textOrigin, y: fontTopPosition)
string.draw(at: textPoint, withAttributes: [.font: font])
let alignment: CGFloat = isImageBeforeText
? 0
: expectedTextSize.width + 5
let rect = CGRect(x: alignment,
y: (height - image.size.height) / 2,
width: image.size.width,
height: image.size.height)
image.draw(in: rect)
}
}
}
斯威夫特 5.x
extension UIImage {
class func textEmbededImage(image: UIImage, string: String, color:UIColor, imageAlignment: Int = 0, segFont: UIFont? = nil) -> UIImage {
let font = segFont ?? UIFont.systemFont(ofSize: 16.0)
let expectedTextSize: CGSize = (string as NSString).size(withAttributes: [NSAttributedString.Key.font: font])
let width: CGFloat = expectedTextSize.width + image.size.width + 5.0
let height: CGFloat = max(expectedTextSize.height, image.size.width)
let size: CGSize = CGSize(width: width, height: height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let context: CGContext = UIGraphicsGetCurrentContext()!
context.setFillColor(color.cgColor)
let fontTopPosition: CGFloat = (height - expectedTextSize.height) / 2.0
let textOrigin: CGFloat = (imageAlignment == 0) ? image.size.width + 5 : 0
let textPoint: CGPoint = CGPoint.init(x: textOrigin, y: fontTopPosition)
string.draw(at: textPoint, withAttributes: [NSAttributedString.Key.font: font])
let flipVertical: CGAffineTransform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height)
context.concatenate(flipVertical)
let alignment: CGFloat = (imageAlignment == 0) ? 0.0 : expectedTextSize.width + 5.0
context.draw(image.cgImage!, in: CGRect.init(x: alignment, y: ((height - image.size.height) / 2.0), width: image.size.width, height: image.size.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
使用示例:
segmentedControl.setImage(
UIImage.textEmbededImage(
image: UIImage(systemName: "photo")!,
string: "Standard",
color: .black
),
forSegmentAt: 0
)
对于斯威夫特。
segFont 是嵌入文本的字体。
imageAlignment 是出现在文本左侧或右侧的图像的对齐方式。
将 imageAlignment 设置为 0 表示左对齐(图像将显示在文本的左侧),设置 1 表示右对齐(图像将显示在文本的右侧)
class func textEmbededImage(image: UIImage, string: String, color:UIColor, imageAlignment: Int = 0, segFont: UIFont? = nil) -> UIImage {
let font = segFont ?? UIFont.systemFontOfSize(16.0)
let expectedTextSize: CGSize = (string as NSString).sizeWithAttributes([NSFontAttributeName: font])
let width: CGFloat = expectedTextSize.width + image.size.width + 5.0
let height: CGFloat = max(expectedTextSize.height, image.size.width)
let size: CGSize = CGSizeMake(width, height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let context: CGContextRef = UIGraphicsGetCurrentContext()!
CGContextSetFillColorWithColor(context, color.CGColor)
let fontTopPosition: CGFloat = (height - expectedTextSize.height) / 2.0
let textOrigin: CGFloat = (imageAlignment == 0) ? image.size.width + 5 : 0
let textPoint: CGPoint = CGPointMake(textOrigin, fontTopPosition)
string.drawAtPoint(textPoint, withAttributes: [NSFontAttributeName: font])
let flipVertical: CGAffineTransform = CGAffineTransformMake(1, 0, 0, -1, 0, size.height)
CGContextConcatCTM(context, flipVertical)
let alignment: CGFloat = (imageAlignment == 0) ? 0.0 : expectedTextSize.width + 5.0
CGContextDrawImage(context, CGRectMake(alignment, ((height - image.size.height) / 2.0), image.size.width, image.size.height), image.CGImage)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
斯威夫特3
extension UIImage{
class func textEmbededImage(image: UIImage, string: String, color:UIColor, imageAlignment: Int = 0, segFont: UIFont? = nil) -> UIImage {
let font = segFont ?? UIFont.systemFont(ofSize: 16.0)
let expectedTextSize: CGSize = (string as NSString).size(attributes: [NSFontAttributeName: font])
let width: CGFloat = expectedTextSize.width + image.size.width + 5.0
let height: CGFloat = max(expectedTextSize.height, image.size.width)
let size: CGSize = CGSize(width: width, height: height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let context: CGContext = UIGraphicsGetCurrentContext()!
context.setFillColor(color.cgColor)
let fontTopPosition: CGFloat = (height - expectedTextSize.height) / 2.0
let textOrigin: CGFloat = (imageAlignment == 0) ? image.size.width + 5 : 0
let textPoint: CGPoint = CGPoint.init(x: textOrigin, y: fontTopPosition)
string.draw(at: textPoint, withAttributes: [NSFontAttributeName: font])
let flipVertical: CGAffineTransform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height)
context.concatenate(flipVertical)
let alignment: CGFloat = (imageAlignment == 0) ? 0.0 : expectedTextSize.width + 5.0
context.draw(image.cgImage!, in: CGRect.init(x: alignment, y: ((height - image.size.height) / 2.0), width: image.size.width, height: image.size.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
斯威夫特5
我需要在右上角添加图像,所以我添加了 imageOffset。
extension UIImage {
static func textEmbeded(image: UIImage, string: String, titleColor: UIColor, imageBeforeText: Bool, imageOffset: CGPoint, segFont: UIFont? = nil) -> UIImage {
let font = segFont ?? UIFont.systemFont(ofSize: 16)
let expectedTextSize = (string as NSString).size(withAttributes: [.font: font])
let width = expectedTextSize.width + image.size.width +
max(0, imageBeforeText ? imageOffset.x * -1 : imageOffset.x)
let height = max(expectedTextSize.height, (image.size.height / 2 + abs(imageOffset.y)) * 2)
let size = CGSize(width: width, height: height)
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { context in
let textTopPosition: CGFloat = (height - expectedTextSize.height) / 2
let textLeftPosition: CGFloat = imageBeforeText ? image.size.width - imageOffset.x : 0
let textPoint: CGPoint = CGPoint.init(x: textLeftPosition, y: textTopPosition)
string.draw(at: textPoint, withAttributes: [.font: font, .foregroundColor: titleColor])
let imageLeftPosition: CGFloat = imageBeforeText ? 0 : expectedTextSize.width + imageOffset.x
let imageTopPosition: CGFloat = (height - image.size.height) / 2 + imageOffset.y
let imageRect = CGRect(x: imageLeftPosition,
y: imageTopPosition,
width: image.size.width,
height: image.size.height)
image.draw(in: imageRect)
}.withRenderingMode(.alwaysOriginal)
}
}
使用此代码在图像下制作文字并支持深色模式。
extension UIImage {
static func with(text: String, under image: UIImage, withinSize boundingSize: CGSize, font: UIFont = UIFont.systemFont(ofSize: 10)) -> UIImage {
let imageSize: CGSize = CGSize(width: boundingSize.width, height: (image.size.height / image.size.width) * boundingSize.width)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
paragraphStyle.lineBreakMode = .byWordWrapping
let attrs: [NSAttributedString.Key: Any] = [
.font: font,
.foregroundColor:UIColor.label,
.paragraphStyle: paragraphStyle
]
let expectedTextSize: CGSize = (text as NSString).boundingRect(with: CGSize(width: boundingSize.width, height: .greatestFiniteMagnitude), options: [.usesLineFragmentOrigin], attributes: attrs, context: nil).size
let height: CGFloat = imageSize.height + expectedTextSize.height
let size: CGSize = CGSize(width: boundingSize.width, height: height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
// Draw image
image.draw(in: CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height))
// Draw text
let textRect: CGRect = CGRect(x: 0, y: imageSize.height, width: boundingSize.width, height: expectedTextSize.height)
(text as NSString).draw(in: textRect.integral, withAttributes: attrs)
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
// Render image as original
return newImage.withRenderingMode(.alwaysOriginal)
}
}
使用示例:
let image = UIImage.with(text: “SOME_TEXT”), under: UIImage(named: “IMAGE_NAME"), withinSize: CGSize(width: 60, height: 80), font: UIFont.systemFont(ofSize: 9))
我的要求有点不同,我需要更改选择和取消选择时的文本颜色。我玩了赞成票的答案,我能够实现它。
我使用的代码如下
static func textEmbededImage(image: UIImage, string: String, color: UIColor?, imageAlignment: Int = 0, segFont: UIFont? = nil) -> UIImage {
let font = segFont ?? <anySystemfont>
let expectedTextSize: CGSize = (string as NSString).size(withAttributes: [NSAttributedString.Key.font: font])
let width: CGFloat = expectedTextSize.width + image.size.width + 5.0
let height: CGFloat = max(expectedTextSize.height, image.size.width)
let size: CGSize = CGSize(width: width, height: height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let context: CGContext = UIGraphicsGetCurrentContext()!
context.setFillColor(color.cgColor)
let fontTopPosition: CGFloat = (height - expectedTextSize.height) / 2.0
let textOrigin: CGFloat = (imageAlignment == 0) ? image.size.width + 5 : 0
let textPoint: CGPoint = CGPoint.init(x: textOrigin, y: fontTopPosition)
string.draw(at: textPoint, withAttributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: color])
let flipVertical: CGAffineTransform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height)
context.concatenate(flipVertical)
let alignment: CGFloat = (imageAlignment == 0) ? 0.0 : expectedTextSize.width + 5.0
context.draw(image.cgImage!, in: CGRect.init(x: alignment, y: ((height - image.size.height) / 2.0), width: image.size.width, height: image.size.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage?.withRenderingMode(.alwaysOriginal) ?? UIImage()
}
初始化如下
segmentControl.setImage(
UIImage.textEmbededImage(image: Asset.icLightning.image, string: Localized.integrations.string, color: <Color>),
forSegmentAt: 0)
segmentControl.setImage(
UIImage.textEmbededImage(image: Asset.icGotoGrey.image, string: Localized.externalConnections.string, color: <Color>),
forSegmentAt: 1)
段值改变动作
if sender.selectedSegmentIndex == 0 {
self.segmentControl.setImage(
UIImage.textEmbededImage(image: Asset.icLightning.image, string: Localized.integrations.string, color: <Color>), forSegmentAt: 0)
self.segmentControl.setImage(
UIImage.textEmbededImage(image: Asset.icGotoGrey.image, string: Localized.externalConnections.string, color: <Color>),
forSegmentAt: 1)
} else {
self.segmentControl.setImage(
UIImage.textEmbededImage(image: Asset.icLightningGrey.image, string: Localized.integrations.string, color: <Color>), forSegmentAt: 0)
self.segmentControl.setImage(
UIImage.textEmbededImage(image: Asset.icGotoDark.image, string: Localized.externalConnections.string, color: <Color>),
forSegmentAt: 1)
}
试试这个:
UISegmentedControl* searchButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"", nil]];
[searchButton insertSegmentWithImage:[UIImage imageNamed:@"up_button.png"] atIndex:0 animated:YES];
[searchButton insertSegmentWithImage:[UIImage imageNamed:@"down_button.png"] atIndex:1 animated:YES];
searchButton.segmentedControlStyle = UISegmentedControlStyleBar;
searchButton.tintColor = [UIColor colorWithRed:0.27 green:0.60 blue:0.20 alpha:1.00];
[searchButton setMomentary:YES];