UILabel 글꼴 크기 변경 애니메이션화
현재 사용자 지정 View 컨트롤러 컨테이너를 사용하는 응용 프로그램을 만들고 있습니다.한 번에 여러 보기가 화면에 표시되고 하나를 누르면 선택한 보기 컨트롤러가 전체 화면으로 애니메이션화됩니다.이렇게 하면 선택한 뷰 컨트롤러가 스케일(프레임, 글꼴 크기 등)도 봅니다.그러나 UILabel의 글꼴 속성은 애니메이션화가 불가능하여 문제가 발생할 수 있습니다.저는 여러 가지 해결책을 시도해 보았지만 완전히 엉망이었습니다.
제가 시도한 솔루션은 다음과 같습니다.
- 더 큰 화면을 캡처하여 변경 사항을 애니메이션화합니다(Flipboard의 기능과 유사).
- 변환 속성을 사용하여 애니메이션을 만듭니다.
- UIScrollView를 축소하고 전체 화면으로 이동할 때 확대합니다.
- 설정은 FontSizeToFitWidth를 YES로 조정하고 애니메이션 전에 fontSize를 설정합니다.
하나는 지금까지 최고의 해결책이었지만 나는 그것에 만족하지 않습니다.
[UIView animate...]를 사용하여 부드럽게 애니메이션화되는 UILabel 대체물이나 UILabel 대체물이 있다면 다른 제안을 찾고 있습니다.
다음은 UILabel이 수행했으면 하는 작업과 유사한 좋은 예입니다. http://www.cocoawithlove.com/2010/09/zoomingviewcontroller-to-animate-uiview.html
편집: 이 코드는 작동합니다.
// Load View
self.label = [[UILabel alloc] init];
self.label.text = @"TEXT";
self.label.font = [UIFont boldSystemFontOfSize:20.0];
self.label.backgroundColor = [UIColor clearColor];
[self.label sizeToFit];
[self.view addSubview:self.label];
// Animation
self.label.font = [UIFont boldSystemFontOfSize:80.0];
self.label.transform = CGAffineTransformScale(self.label.transform, .25, .25);
[self.label sizeToFit];
[UIView animateWithDuration:1.0 animations:^{
self.label.transform = CGAffineTransformScale(self.label.transform, 4.0, 4.0);
self.label.center = self.view.center;
} completion:^(BOOL finished) {
self.label.font = [UIFont boldSystemFontOfSize:80.0];
self.label.transform = CGAffineTransformScale(self.label.transform, 1.0, 1.0);
[self.label sizeToFit];
}];
의 크기와 글꼴을 변경할 수 있습니다.UILabel
아래와 같은 애니메이션으로여기에 글꼴을 변경하는 방법에 대한 예를 넣었습니다.UILabel
변환 애니메이션 사용...
yourLabel.font = [UIFont boldSystemFontOfSize:35]; // set font size which you want instead of 35
yourLabel.transform = CGAffineTransformScale(yourLabel.transform, 0.35, 0.35);
[UIView animateWithDuration:1.0 animations:^{
yourLabel.transform = CGAffineTransformScale(yourLabel.transform, 5, 5);
}];
2017년 이후로는..
스위프트 3.0, 4.0
UIView.animate(withDuration: 0.5) {
label.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) //Scale label area
}
중요:
흐림을 방지하기 위한 중요한 점은 가장 큰 크기로 시작하여 축소해야 한다는 것입니다.그런 다음 필요할 때 "1"로 확장합니다.
빠른 "팝"(하이라이트 애니메이션과 같은)의 경우 1 이상으로 확장해도 괜찮지만 두 가지 크기 사이에서 전환하는 경우 큰 크기를 "올바른" 일반 크기로 설정합니다.
내가 만든UILabel
스위프트 내선 번호입니다.
import UIKit
extension UILabel {
func animate(font: UIFont, duration: TimeInterval) {
// let oldFrame = frame
let labelScale = self.font.pointSize / font.pointSize
self.font = font
let oldTransform = transform
transform = transform.scaledBy(x: labelScale, y: labelScale)
// let newOrigin = frame.origin
// frame.origin = oldFrame.origin // only for left aligned text
// frame.origin = CGPoint(x: oldFrame.origin.x + oldFrame.width - frame.width, y: oldFrame.origin.y) // only for right aligned text
setNeedsUpdateConstraints()
UIView.animate(withDuration: duration) {
//L self.frame.origin = newOrigin
self.transform = oldTransform
self.layoutIfNeeded()
}
}
}
레이블 텍스트가 왼쪽 또는 오른쪽으로 정렬된 경우 선에 주석을 달 수 있습니다.
또한 fontSize가 있는 CATextLayer를 애니메이션 가능한 속성으로 사용할 수 있습니다.
let startFontSize: CGFloat = 20
let endFontSize: CGFloat = 80
let textLayer = CATextLayer()
textLayer.string = "yourText"
textLayer.font = yourLabel.font.fontName as CFTypeRef?
textLayer.fontSize = startFontSize
textLayer.foregroundColor = UIColor.black.cgColor
textLayer.contentsScale = UIScreen.main.scale //for some reason CATextLayer by default only works for 1x screen resolution and needs this line to work properly on 2x, 3x, etc. ...
textLayer.frame = parentView.bounds
parentView.layer.addSublayer(textLayer)
//animation:
let duration: TimeInterval = 1
textLayer.fontSize = endFontSize //because upon completion of the animation CABasicAnimation resets the animated CALayer to its original state (as opposed to changing its properties to the end state of the animation), setting fontSize to endFontSize right BEFORE the animation starts ensures the fontSize doesn't jump back right after the animation.
let fontSizeAnimation = CABasicAnimation(keyPath: "fontSize")
fontSizeAnimation.fromValue = startFontSize
fontSizeAnimation.toValue = endFontSize
fontSizeAnimation.duration = duration
fontSizeAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
textLayer.add(fontSizeAnimation, forKey: nil)
제 프로젝트에 사용했습니다: https://github.com/yinanq/AngelListJobs
이 애니메이션은 (CGAfineTransformScale이 레이블을 중앙에서 스케일링하는 것과 달리) 필요에 따라 글꼴 상단을 왼쪽으로 정렬하거나 반대로 유지합니다.CATextLayer의 단점은 CATextLayer가 자동 레이아웃 제약 조건 애니메이션과 함께 작동하지 않는다는 것입니다(CATextLayer만 포함하는 UIView를 만들고 제약 조건을 애니메이션화하여 필요하게 되었습니다).
혁신이 아닌 실제 가치 변화를 원하는 고객:
UIView.transition(with: label, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.label.font = UIFont.systemFont(ofSize: 15)
}) { isFinished in }
애니메이션의 방향을 조정하고 싶은 사람을 위한 것입니다.
▁extension의 확장자를 .UILabel
글꼴 크기 변경을 애니메이션화합니다.
extension UILabel {
func animate(fontSize: CGFloat, duration: TimeInterval) {
let startTransform = transform
let oldFrame = frame
var newFrame = oldFrame
let scaleRatio = fontSize / font.pointSize
newFrame.size.width *= scaleRatio
newFrame.size.height *= scaleRatio
newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * 0.5
newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * 0.5
frame = newFrame
font = font.withSize(fontSize)
transform = CGAffineTransform.init(scaleX: 1 / scaleRatio, y: 1 / scaleRatio);
layoutIfNeeded()
UIView.animate(withDuration: duration, animations: {
self.transform = startTransform
newFrame = self.frame
}) { (Bool) in
self.frame = newFrame
}
}
애니메이션의 방향을 조정하려면 아래 방법을 사용하여 적합한 앵커 포인트를 배치합니다.
스위프트
struct LabelAnimateAnchorPoint {
// You can add more suitable archon point for your needs
static let leadingCenterY = CGPoint.init(x: 0, y: 0.5)
static let trailingCenterY = CGPoint.init(x: 1, y: 0.5)
static let centerXCenterY = CGPoint.init(x: 0.5, y: 0.5)
static let leadingTop = CGPoint.init(x: 0, y: 0)
}
extension UILabel {
func animate(fontSize: CGFloat, duration: TimeInterval, animateAnchorPoint: CGPoint) {
let startTransform = transform
let oldFrame = frame
var newFrame = oldFrame
let archorPoint = layer.anchorPoint
let scaleRatio = fontSize / font.pointSize
layer.anchorPoint = animateAnchorPoint
newFrame.size.width *= scaleRatio
newFrame.size.height *= scaleRatio
newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * animateAnchorPoint.x
newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * animateAnchorPoint.y
frame = newFrame
font = font.withSize(fontSize)
transform = CGAffineTransform.init(scaleX: 1 / scaleRatio, y: 1 / scaleRatio);
layoutIfNeeded()
UIView.animate(withDuration: duration, animations: {
self.transform = startTransform
newFrame = self.frame
}) { (Bool) in
self.layer.anchorPoint = archorPoint
self.frame = newFrame
}
}
}
목표-C
// You can add more suitable archon point for your needs
#define kLeadingCenterYAnchorPoint CGPointMake(0.f, .5f)
#define kTrailingCenterYAnchorPoint CGPointMake(1.f, .5f)
#define kCenterXCenterYAnchorPoint CGPointMake(.5f, .5f)
#define kLeadingTopAnchorPoint CGPointMake(0.f, 0.f)
@implementation UILabel (FontSizeAnimating)
- (void)animateWithFontSize:(CGFloat)fontSize duration:(NSTimeInterval)duration animateAnchorPoint:(CGPoint)animateAnchorPoint {
CGAffineTransform startTransform = self.transform;
CGRect oldFrame = self.frame;
__block CGRect newFrame = oldFrame;
CGPoint archorPoint = self.layer.anchorPoint;
CGFloat scaleRatio = fontSize / self.font.pointSize;
self.layer.anchorPoint = animateAnchorPoint;
newFrame.size.width *= scaleRatio;
newFrame.size.height *= scaleRatio;
newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * animateAnchorPoint.x;
newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * animateAnchorPoint.y;
self.frame = newFrame;
self.font = [self.font fontWithSize:fontSize];
self.transform = CGAffineTransformScale(self.transform, 1.f / scaleRatio, 1.f / scaleRatio);
[self layoutIfNeeded];
[UIView animateWithDuration:duration animations:^{
self.transform = startTransform;
newFrame = self.frame;
} completion:^(BOOL finished) {
self.layer.anchorPoint = archorPoint;
self.frame = newFrame;
}];
}
@end
예를 들어 레이블 글꼴 크기를 30으로 변경하는 애니메이션을 만들려면 가운데에서 지속 시간 1초를 더 크게 조정합니다.간단히 전화하기
스위프트
YOUR_LABEL.animate(fontSize: 30, duration: 1, animateAnchorPoint: LabelAnimateAnchorPoint.centerXCenterY)
목표-C
[YOUR_LABEL animateWithFontSize:30
duration:1
animateAnchorPoint:kCenterXCenterYAnchorPoint];
스위프트 3.0 & 스위프트 4.0
UIView.animate(withDuration: 0.5, delay: 0.1, options: .curveLinear, animations: {
label.transform = label.transform.scaledBy(x:4,y:4) //Change x,y to get your desired effect.
} ) { (completed) in
//Animation Completed
}
저는 다음과 같은 이유로 여기에 제시된 각각의 제안이 부적절하다는 것을 알게 되었습니다.
- 그들은 실제로 글꼴 크기를 바꾸지 않습니다.
- 프레임 크기 조정 및 자동 레이아웃을 사용할 수 없습니다.
- 인터페이스가 단순하지 않거나 애니메이션 블록 내부에서 제대로 작동하지 않습니다.
이러한 모든 기능을 유지하면서도 원활한 애니메이션 전환을 위해 변환 접근 방식과 글꼴 접근 방식을 결합했습니다.
인터페이스는 간단합니다.업데이트하기만 하면 됩니다.fontSize
속성을 입력하면 글꼴 크기를 업데이트합니다.애니메이션 블록 안에서 이렇게 하면 애니메이션이 됩니다.
@interface UILabel(MPFontSize)
@property(nonatomic) CGFloat fontSize;
@end
구현에는 간단한 방법이 있고 더 나은 방법이 있습니다.
단순:
@implementation UILabel(MPFontSize)
- (void)setFontSize:(CGFloat)fontSize {
CGAffineTransform originalTransform = self.transform;
UIFont *targetFont = [self.font fontWithSize:fontSize];
[UIView animateWithDuration:0 delay:0 options:0 animations:^{
self.transform = CGAffineTransformScale( originalTransform,
fontSize / self.fontSize, fontSize / self.fontSize );
} completion:^(BOOL finished) {
self.transform = originalTransform;
if (finished)
self.font = targetFont;
}];
}
- (CGFloat)fontSize {
return self.font.pointSize;
};
@end
이것의 문제는 애니메이션이 완료될 때까지 보기의 프레임 크기가 원래 글꼴을 기준으로 크기가 조정되므로 레이아웃이 완료될 때마다 말을 더듬을 수 있다는 것입니다. 이때 프레임은 애니메이션 없이 대상 글꼴에 맞게 업데이트됩니다.
이 문제를 해결하는 것은 우리가 오버라이드해야 하기 때문에 조금 더 어렵습니다.intrinsicContentSize
하위 분류를 통해 이 작업을 수행할 수 있습니다.UILabel
또는 방법을 스와이프함으로써.저는개로그방변다니경합을법으인적을 할 수 해주기 에 그 방법을 . 왜냐하면 그것은 제가 제네릭을 유지할 수 있게 해주기 때문입니다.fontSize
모든 할 수 .UILabel
수 . s, 하만여기공유수할코라리러드따다다릅니라에.하위 분류를 사용하여 이 작업을 수행하는 방법은 다음과 같습니다.
인터페이스:
@interface AnimatableLabel : UILabel
@property(nonatomic) CGFloat fontSize;
@end
구현:
@interface AnimatableLabel()
@property(nonatomic) UIFont *targetFont;
@property(nonatomic) UIFont *originalFont;
@end
@implementation AnimatableLabel
- (void)setFontSize:(CGFloat)fontSize {
CGAffineTransform originalTransform = self.transform;
self.originalFont = self.font;
self.targetFont = [self.font fontWithSize:fontSize];
[self invalidateIntrinsicContentSize];
[UIView animateWithDuration:0 delay:0 options:0 animations:^{
self.transform = CGAffineTransformScale( originalTransform,
fontSize / self.fontSize, fontSize / self.fontSize );
} completion:^(BOOL finished) {
self.transform = originalTransform;
if (self.targetFont) {
if (finished)
self.font = self.targetFont;
self.targetFont = self.originalFont = nil;
[self invalidateIntrinsicContentSize];
}
}];
}
- (CGFloat)fontSize {
return self.font.pointSize;
};
- (CGSize)intrinsicContentSize {
@try {
if (self.targetFont)
self.font = self.targetFont;
return self.intrinsicContentSize;
}
@finally {
if (self.originalFont)
self.font = self.originalFont;
}
}
@end
다른 앵커 포인트에서 텍스트 크기를 애니메이션화하려면 Swift 5 솔루션을 사용합니다.
신청 방법:
yourLabel.setAnimatedFont(.systemFont(ofSize: 48), duration: 0.2, anchorPointX: 0, anchorPointY: 1)
확장:
extension UILabel {
/// Animate font size from a given anchor point of the label.
/// - Parameters:
/// - duration: Animation measured in seconds
/// - anchorPointX: 0 = left, 0.5 = center, 1 = right
/// - anchorPointY: 0 = top, 0.5 = center, 1 = bottom
func setAnimatedFont(_ font: UIFont, duration: TimeInterval, anchorPointX: CGFloat, anchorPointY: CGFloat) {
guard let oldFont = self.font else { return }
setAnchorPoint(CGPoint(x: anchorPointX, y: anchorPointY))
self.font = font
let scaleFactor = oldFont.pointSize / font.pointSize
let oldTransform = transform
transform = transform.scaledBy(x: scaleFactor, y: scaleFactor)
setNeedsUpdateConstraints()
UIView.animate(withDuration: duration) {
self.transform = oldTransform
self.layoutIfNeeded()
}
}
}
extension UIView {
/// Change the anchor point without moving the view's position.
/// - Parameters:
/// - point: The layer's bounds rectangle.
func setAnchorPoint(_ point: CGPoint) {
let oldOrigin = frame.origin
layer.anchorPoint = point
let newOrigin = frame.origin
let translation = CGPoint(x: newOrigin.x - oldOrigin.x, y: newOrigin.y - oldOrigin.y)
translatesAutoresizingMaskIntoConstraints = true
center = CGPoint(x: center.x - translation.x, y: center.y - translation.y)
}
}
언급URL : https://stackoverflow.com/questions/14494566/animating-uilabel-font-size-change
'programing' 카테고리의 다른 글
기호 'AppCompatActivity'를 확인할 수 없습니다. (0) | 2023.08.10 |
---|---|
수식과 필터링을 사용한 Excel 데이터 유효성 검사 목록 (0) | 2023.08.10 |
PowerShell 문자열 형식 지정:콜론 문자로 인해 변수 값이 비어 있는 이유는 무엇입니까? (0) | 2023.08.10 |
테이블의 열을 하나만 업데이트하도록 CSV 가져오기 (0) | 2023.08.10 |
열이 구분된 테이블을 사용하여 조회 (0) | 2023.08.10 |