Centre NSTextAttachment image à côté de la ligne unique UILabel

Je voudrais append une image NSTextAttachment à ma string atsortingbuée et la centrer verticalement.

J'ai utilisé le code suivant pour créer ma string

NSMutableAtsortingbutedSsortingng *str = [[NSMutableAtsortingbutedSsortingng alloc] initWithSsortingng:DDLocalizedSsortingng(@"title.upcomingHotspots") atsortingbutes:attrs]; NSTextAttachment *attachment = [[NSTextAttachment alloc] init]; attachment.image = [[UIImage imageNamed:@"help.png"] imageScaledToFitSize:CGSizeMake(14.f, 14.f)]; cell.textLabel.atsortingbutedText = [str copy]; 

Cependant, l'image semble s'aligner sur le haut de l'label de text de la cellule.

entrez la description de l'image ici

Comment puis-je changer le rect dans lequel la pièce jointe est dessinée?

Vous pouvez modifier le rect en sous- NSTextAttachment et en NSTextAttachment attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex: Exemple:

 - (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex { CGRect bounds; bounds.origin = CGPointMake(0, -5); bounds.size = self.image.size; return bounds; } 

Ce n'est pas une solution parfaite. Vous devez find l'origine Y "par oeil" et si vous changez la police ou la taille de l'icône, vous voudrez probablement changer l'origine Y. Mais je ne pouvais pas find un meilleur moyen, sauf en mettant l'icône dans une vue d'image séparée (qui a ses propres inconvénients).

Essayez - [NSTextAttachment bounds] . Aucun sous-classment requirejs.

Pour le context, je suis en UILabel de rendre un UILabel pour l'utiliser comme image en pièce jointe, puis en définissant les limites comme attachment.bounds = CGRectMake(0, self.font.descender, attachment.image.size.width, attachment.image.size.height) : attachment.bounds = CGRectMake(0, self.font.descender, attachment.image.size.width, attachment.image.size.height) et les lignes de base du text dans l'image de l'label et le text dans la string atsortingbuée sont alignés comme souhaité.

J'ai trouvé une solution parfaite à cela, fonctionne comme un charme pour moi cependant, mais vous devez l'essayer vous-même (probablement la constante dépend de la résolution de l'appareil et peut-être tout;)

 func textAttachment(fontSize: CGFloat) -> NSTextAttachment { let font = UIFont.systemFontOfSize(fontSize) //set accordingly to your font, you might pass it in the function let textAttachment = NSTextAttachment() let image = //some image textAttachment.image = image let mid = font.descender + font.capHeight textAttachment.bounds = CGRectIntegral(CGRect(x: 0, y: font.descender - image.size.height / 2 + mid + 2, width: image.size.width, height: image.size.height)) return textAttachment } 

Devrait fonctionner et ne devrait pas être flou en aucune façon (grâce à CGRectIntegral )

Qu'en est-il de:

 CGFloat offsetY = -10.0; NSTextAttachment *attachment = [NSTextAttachment new]; attachment.image = image; attachment.bounds = CGRectMake(0, offsetY, attachment.image.size.width, attachment.image.size.height); 

Aucun sous-classment requirejs

Vous devriez utiliser le capHeight de la police.

Objectif c

 NSTextAttachment *icon = [[NSTextAttachment alloc] init]; UIImage *iconImage = [UIImage imageNamed:@"icon.png"]; [icon setBounds:CGRectMake(0, roundf(titleFont.capHeight - iconImage.size.height)/2.f, iconImage.size.width, iconImage.size.height)]; [icon setImage:iconImage]; NSAtsortingbutedSsortingng *iconSsortingng = [NSAtsortingbutedSsortingng atsortingbutedSsortingngWithAttachment:icon]; [titleText appendAtsortingbutedSsortingng:iconSsortingng]; 

Rapide

 let iconImage = UIImage(named: "icon.png")! var icon = NSTextAttachment() icon.bounds = CGRect(x: 0, y: (titleFont.capHeight - iconImage.size.height).rounded() / 2, width: iconImage.size.width, height: iconImage.size.height) icon.image = iconImage let iconSsortingng = NSAtsortingbutedSsortingng(attachment: icon) titleText.append(iconSsortingng) 

L'image de pièce jointe est rendue sur la ligne de base du text. Et l'axe des y est inversé comme le système de coordonnées charts de base. Si vous souhaitez déplacer l'image vers le haut, définissez bounds.origin.y sur positif.

L'image doit être alignée verticalement au centre du capHeight du text. Nous devons donc définir bounds.origin.y à (capHeight - imageHeight)/2 .

En évitant un effet déchiqueté sur l'image, nous devrions arrondir la partie fraction du y. Mais les fonts et les images sont généralement petites, même une différence de 1px rend l'image désalignée. J'ai donc appliqué la fonction ronde avant de split. Cela fait de la fraction une partie de la valeur y à .0 ou .5

Dans votre cas, la hauteur de l'image est plus grande que le capHeight de la police. Mais vous pouvez utiliser de la même manière. La valeur de décalage y sera négative. Et il sera établi à partir du bas de la ligne de base.

entrez la description de l'image ici

@Travis est correct que le décalage est le descendant de la police. Si vous devez également mettre à l'échelle l'image, vous devrez utiliser une sous-class de NSTextAttachment. Voici le code, qui a été inspiré par cet article . Je l'ai également posté comme un brin .

 import UIKit class ImageAttachment: NSTextAttachment { var verticalOffset: CGFloat = 0.0 // To vertically center the image, pass in the font descender as the vertical offset. // We cannot get this info from the text container since it is sometimes nil when `attachmentBoundsForTextContainer` // is called. convenience init(_ image: UIImage, verticalOffset: CGFloat = 0.0) { self.init() self.image = image self.verticalOffset = verticalOffset } override func attachmentBoundsForTextContainer(textContainer: NSTextContainer, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect { let height = lineFrag.size.height var scale: CGFloat = 1.0; let imageSize = image!.size if (height < imageSize.height) { scale = height / imageSize.height } return CGRect(x: 0, y: verticalOffset, width: imageSize.width * scale, height: imageSize.height * scale) } } 

Utilisez comme suit:

 var text = NSMutableAtsortingbutedSsortingng(ssortingng: "My Text") let image = UIImage(named: "my-image")! let imageAttachment = ImageAttachment(image, verticalOffset: myLabel.font.descender) text.appendAtsortingbutedSsortingng(NSAtsortingbutedSsortingng(attachment: imageAttachment)) myLabel.atsortingbutedText = text 

Si vous avez un très grand ascendant et que vous voulez centrer l'image (centre de la hauteur du bouchon) comme moi, essayez ceci

 let attachment: NSTextAttachment = NSTextAttachment() attachment.image = image if let image = attachment.image{ let y = -(font.ascender-font.capHeight/2-image.size.height/2) attachment.bounds = CGRect(x: 0, y: y, width: image.size.width, height: image.size.height).integral } 

Le calcul y est comme l'image ci-dessous

entrez la description de l'image ici

Notez que la valeur y est 0 car nous voulons que l'image soit décalée par rapport à l'origine

Si vous voulez que ce soit au milieu de l'label entière. Utilisez cette valeur y:

 let y = -((font.ascender-font.descender)/2-image.size.height/2) 

J'ai une class de catégorie pour avoir NSSsortingng avec UIImage et vice versa.

https://github.com/Pradeepkn/TextWithImage

Prendre plaisir.

Veuillez utiliser -lineFrag.size.height / 5.0 pour la hauteur des limites. Ceci centre exactement l'image et aligné avec le text pour toute la taille des fonts

 override func attachmentBoundsForTextContainer(textContainer: NSTextContainer, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect { var bounds:CGRect = CGRectZero bounds.size = self.image?.size as CGSize! bounds.origin = CGPointMake(0, -lineFrag.size.height/5.0); return bounds; }