여러 줄이있는 UILabel에서 자동 축소
의 여러 줄에서 autoshrink 속성을 함께 사용할 수 UILabel
있습니까? 예를 들어, 사용 가능한 두 줄에서 가능한 큰 텍스트 크기입니다.
이 사람들은 해결책을 찾았습니다.
http://www.11pixel.com/blog/28/resize-multi-line-text-to-fit-uilabel-on-iphone/
그들의 해결책은 다음과 같습니다.
int maxDesiredFontSize = 28;
int minFontSize = 10;
CGFloat labelWidth = 260.0f;
CGFloat labelRequiredHeight = 180.0f;
//Create a string with the text we want to display.
self.ourText = @"This is your variable-length string. Assign it any way you want!";
/* This is where we define the ideal font that the Label wants to use.
Use the font you want to use and the largest font size you want to use. */
UIFont *font = [UIFont fontWithName:@"Marker Felt" size:maxDesiredFontSize];
int i;
/* Time to calculate the needed font size.
This for loop starts at the largest font size, and decreases by two point sizes (i=i-2)
Until it either hits a size that will fit or hits the minimum size we want to allow (i > 10) */
for(i = maxDesiredFontSize; i > minFontSize; i=i-2)
{
// Set the new font size.
font = [font fontWithSize:i];
// You can log the size you're trying: NSLog(@"Trying size: %u", i);
/* This step is important: We make a constraint box
using only the fixed WIDTH of the UILabel. The height will
be checked later. */
CGSize constraintSize = CGSizeMake(labelWidth, MAXFLOAT);
// This step checks how tall the label would be with the desired font.
CGSize labelSize = [self.ourText sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
/* Here is where you use the height requirement!
Set the value in the if statement to the height of your UILabel
If the label fits into your required height, it will break the loop
and use that font size. */
if(labelSize.height <= labelRequiredHeight)
break;
}
// You can see what size the function is using by outputting: NSLog(@"Best size is: %u", i);
// Set the UILabel's font to the newly adjusted font.
msg.font = font;
// Put the text into the UILabel outlet variable.
msg.text = self.ourText;
이 작업을 수행하려면 인터페이스 빌더에서 IBOutlet을 UILabel에 할당해야합니다.
"IBOutlet UILabel * msg;"
모든 장점은 11 픽셀의 사람들입니다.
위의 코드를 약간 수정하여 카테고리로 만들었습니다 UILabel
.
헤더 파일 :
#import <UIKit/UIKit.h>
@interface UILabel (MultiLineAutoSize)
- (void)adjustFontSizeToFit;
@end
그리고 구현 파일 :
@implementation UILabel (MultiLineAutoSize)
- (void)adjustFontSizeToFit
{
UIFont *font = self.font;
CGSize size = self.frame.size;
for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumFontSize; maxSize -= 1.f)
{
font = [font fontWithSize:maxSize];
CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
if(labelSize.height <= size.height)
{
self.font = font;
[self setNeedsLayout];
break;
}
}
// set the font to the minimum size anyway
self.font = font;
[self setNeedsLayout];
}
@end
이 링크를 찾았습니다 http://beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/
이 문제는 Interface Builder를 사용하여 간단한 3 단계로 해결할 수 있습니다.
- "Autoshrink"를 "최소 글꼴 크기"로 설정합니다.
- 글꼴을 원하는 가장 큰 글꼴 크기 (20)로 설정하고 Lines를 예를 들어 10으로 설정합니다. 제 경우에는 해당 글꼴 크기의 레이블에 들어갈 수있는 줄 수입니다.
- 그런 다음 "줄 바꿈"을 "단어 줄 바꿈"에서 "꼬리 자르기"로 변경합니다.
도움이 되었기를 바랍니다.
다음은 itecedor의 iOS 6 업데이트를 기반으로 iOS 7로 업데이트 된 카테고리 솔루션입니다.
헤더 파일 :
#import <UIKit/UIKit.h>
@interface UILabel (MultiLineAutoSize)
- (void)adjustFontSizeToFit;
@end
그리고 구현 파일 :
@implementation UILabel (MultiLineAutoSize)
- (void)adjustFontSizeToFit {
UIFont *font = self.font;
CGSize size = self.frame.size;
for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f)
{
font = [font fontWithSize:maxSize];
CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
CGRect textRect = [self.text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:font}
context:nil];
CGSize labelSize = textRect.size;
if(labelSize.height <= size.height)
{
self.font = font;
[self setNeedsLayout];
break;
}
}
// set the font to the minimum size anyway
self.font = font;
[self setNeedsLayout]; }
@end
해결책으로 표시된 대답은 엉망이고 부정확합니다. UILabel은 다음 속성을 올바르게 설정하면 자동으로 처리합니다.
numberOfLines
0이 아니어야합니다
adjustsFontSizeToFitWidth
반드시 YES
lineBreakMode
있어야 하지 수 NSLineBreakByCharWrapping
또는NSLineBreakByWordWrapping
@DaGaMs에서 채택한 신속한 버전.
SWIFT 2 :
extension UILabel {
func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
let maxFontSize = maximumFontSize ?? font.pointSize
for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
let proposedFont = font.fontWithSize(size)
let constraintSize = CGSizeMake(bounds.size.width, CGFloat(MAXFLOAT))
let labelSize = ((text ?? "") as NSString).boundingRectWithSize(constraintSize,
options: .UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: proposedFont],
context: nil)
if labelSize.height <= bounds.size.height {
font = proposedFont
setNeedsLayout()
break;
}
}
}
}
SWIFT 3 :
extension UILabel {
func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
let maxFontSize = maximumFontSize ?? font.pointSize
for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
let proposedFont = font.withSize(size)
let constraintSize = CGSize(width: bounds.size.width, height: CGFloat(MAXFLOAT))
let labelSize = ((text ?? "") as NSString).boundingRect(with: constraintSize,
options: .usesLineFragmentOrigin,
attributes: [NSFontAttributeName: proposedFont],
context: nil)
if labelSize.height <= bounds.size.height {
font = proposedFont
setNeedsLayout()
break;
}
}
}
}
평판이 부족해서 몬티 래빗의 게시물에 대해서는 댓글을 달 수 없으니 새로운 답변을 드리겠습니다. 그가 제안한 솔루션은 Xcode 7.3 이상에서 작동하지 않으며 정확하지 않습니다. 제대로 작동하려면 스토리 보드에서 다음을 수행해야했습니다.
- 너비 제한 설정 (순수 너비 또는 꼬리 및 리드)
- HEIGHT CONSTRAINT 설정 (매우 중요합니다. 일반적으로 자동 크기 조정은 레이블 높이를 설정하지 않습니다.)
- "Autoshrink"속성을 "최소 글꼴 크기"또는 "최소 글꼴 크기"로 설정합니다 (두 경우 모두 작동).
- "줄 바꿈"속성을 "꼬리 자르기"로 설정합니다.
- "Lines"속성을 0이 아닌 값으로 설정합니다.
도움이 되었기를 바랍니다. ;)
나는 DaGaMs의 대답을 좋아했지만 dequeueReusableCell : 반환 될 수있는 UITableViewCells와 같은 레이블을 사용하면 원래 글꼴 크기가 텍스트가 적고 활용할 수있는 일부 tableView 셀에 대해 여전히 원하는 경우에도 일반 글꼴 크기가 계속 축소됩니다. 원래 라벨의 원래 글꼴 크기.
그래서 저는 DaGaMs의 카테고리로 시작하여 별도의 카테고리가 아닌 별도의 클래스를 만들고 스토리 보드의 UILabels가이 새로운 클래스를 사용하는지 확인합니다.
#import "MultiLineAutoShrinkLabel.h"
@interface MultiLineAutoShrinkLabel ()
@property (readonly, nonatomic) UIFont* originalFont;
@end
@implementation MultiLineAutoShrinkLabel
@synthesize originalFont = _originalFont;
- (UIFont*)originalFont { return _originalFont ? _originalFont : (_originalFont = self.font); }
- (void)quoteAutoshrinkUnquote
{
UIFont* font = self.originalFont;
CGSize frameSize = self.frame.size;
CGFloat testFontSize = _originalFont.pointSize;
for (; testFontSize >= self.minimumFontSize; testFontSize -= 0.5)
{
CGSize constraintSize = CGSizeMake(frameSize.width, MAXFLOAT);
CGSize testFrameSize = [self.text sizeWithFont:(font = [font fontWithSize:testFontSize])
constrainedToSize:constraintSize
lineBreakMode:self.lineBreakMode];
// the ratio of testFontSize to original font-size sort of accounts for number of lines
if (testFrameSize.height <= frameSize.height * (testFontSize/_originalFont.pointSize))
break;
}
self.font = font;
[self setNeedsLayout];
}
@end
itedcedor의 답변에는 pwightman이 지적한 문제가 있습니다. 또한 공백을 다듬을 필요가 없습니다. 다음은 수정 된 버전입니다.
- (void)adjustFontSizeToFit {
UIFont *font = self.font;
CGSize size = self.frame.size;
for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f) {
font = [font fontWithSize:maxSize];
CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
if(labelSize.height <= size.height) {
self.font = font;
[self setNeedsLayout];
break;
}
}
// set the font to the minimum size anyway
self.font = font;
[self setNeedsLayout];
}
이 솔루션에 대해 DaGaMs에 감사드립니다.
다음과 같이 업데이트했습니다.
1-iOS 6에서 작업하려면 (minimumFontSize 및 UILineBreakModeWordWrap이 모두 사용되지 않기 때문에) 2-크기 조정이 실패 할 수 있으므로 레이블 텍스트에서 공백을 제거합니다 (찾는 데 얼마나 걸 렸는지 알고 싶지 않습니다 곤충)
-(void)adjustFontSizeToFit
{
self.text = [self.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
UIFont *font = self.font;
CGSize size = self.frame.size;
for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor; maxSize -= 1.f)
{
font = [font fontWithSize:maxSize];
CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
if(labelSize.height <= size.height)
{
self.font = font;
[self setNeedsLayout];
break;
}
}
// set the font to the minimum size anyway
self.font = font;
[self setNeedsLayout];
}
UIButton의 경우 다음 줄만 작동합니다.
self.centerBtn.titleLabel.numberOfLines = 2;
self.centerBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
self.centerBtn.titleLabel.adjustsFontSizeToFitWidth = YES;
@wbarksdale의 Swift 3 솔루션을 사용했지만 긴 단어가 중간에서 잘리는 것을 발견했습니다. 단어를 그대로 유지하려면 다음과 같이 수정해야했습니다.
extension UILabel {
func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
let maxFontSize = maximumFontSize ?? font.pointSize
let words = self.text?.components(separatedBy: " ")
var longestWord: String?
if let max = words?.max(by: {$1.characters.count > $0.characters.count}) {
longestWord = max
}
for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
let proposedFont = font.withSize(size)
let constraintSize = CGSize(width: bounds.size.width, height: CGFloat(MAXFLOAT))
let labelSize = ((text ?? "") as NSString).boundingRect(with: constraintSize,
options: .usesLineFragmentOrigin,
attributes: [NSFontAttributeName: proposedFont],
context: nil)
let wordConstraintSize = CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT))
let longestWordSize = ((longestWord ?? "") as NSString).boundingRect(with: wordConstraintSize,
options: .usesFontLeading,
attributes: [NSFontAttributeName: proposedFont],
context: nil)
if labelSize.height <= bounds.size.height && longestWordSize.width < constraintSize.width {
font = proposedFont
setNeedsLayout()
break
}
}
}
}
이 기능을 달성하기 위해 위의 "The Dude 's"답변을 기반으로 UILabel에 작은 범주를 작성했습니다.
https://gist.github.com/ayushn21/d87b835b2efc756e859f
There is a method on NSString
, -sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:
which has apparently existed since iOS 2.0, but unfortunately is deprecated in iOS 7 without a suggested alternative as the automatic reduction of font size is discouraged. I don't really understand Apple's stance on this as they use it in keynote etc and I think if the font sizes are within a small range it is ok. Here's an implementation in Swift using this method.
var newFontSize: CGFloat = 30
let font = UIFont.systemFontOfSize(newFontSize)
(self.label.text as NSString).sizeWithFont(font, minFontSize: 20, actualFontSize: &newFontSize, forWidth: self.label.frame.size.width, lineBreakMode: NSLineBreakMode.ByWordWrapping)
self.label.font = font.fontWithSize(newFontSize)
I'm not aware of a way this can be achieved without using deprecated methods.
Try this:
Either subclass UILabel or call adjustFontSize method after setting the text property on a label
override var text : String? { didSet { self.adjustFontSize() } }
func adjustFontSize()
{
var lineCount = self.string.components(separatedBy: "\n").count - 1
var textArray = self.string.components(separatedBy: " ")
var wordsToCompare = 1
while(textArray.count > 0)
{
let words = textArray.first(n: wordsToCompare).joined(separator: " ")
let wordsWidth = words.widthForHeight(0, font: self.font)
if(wordsWidth > self.frame.width)
{
textArray.removeFirst(wordsToCompare)
lineCount += 1
wordsToCompare = 1
}
else if(wordsToCompare > textArray.count)
{
break
}
else
{
wordsToCompare += 1
}
}
self.numberOfLines = lineCount + 1
}
extension UILabel{
func adjustFont(minSize:Int, maxSize:Int){
var newFont = self.font
for index in stride(from: maxSize, to: minSize, by: -1) {
newFont = UIFont.systemFont(ofSize: CGFloat(index))
let size = CGSize(width: self.frame.width, height: CGFloat(Int.max))
let size2 = (self.text! as NSString).boundingRect(with: size, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font:newFont!], context: nil).size
if size2.height < self.frame.size.height{
break
}
}
self.font = newFont
}
}
you need to assign value to the numberOfLines property of UILabel as well.
ReferenceURL : https://stackoverflow.com/questions/9059631/autoshrink-on-a-uilabel-with-multiple-lines
'Nice programing' 카테고리의 다른 글
jQuery : 일시적으로 스타일을 변경 한 다음 원래 클래스로 재설정 (0) | 2020.12.27 |
---|---|
루비에서 날짜의 요일을 어떻게 계산할 수 있습니까? (0) | 2020.12.27 |
imagebutton으로 listview 행을 클릭 할 수 없습니다. (0) | 2020.12.27 |
@PropertySource 주석을 사용할 때 @Value가 확인되지 않습니다. (0) | 2020.12.27 |
Android 스튜디오 : Gradle 새로 고침 실패-com.android.tools.build:gradle:2.2.0-alpha6을 찾을 수 없음 (0) | 2020.12.27 |