สามารถเปลี่ยนขนาดได้ด้วย CGAffineTransform แต่ ไม่แนะนำ เพราะภาพจะเบลอ (Blurry) และไม่ใช่การ Scale ที่เหมาะสม
วิธีที่พบบ่อย (ไม่แนะนำ)
let indicator = UIActivityIndicatorView(style: .large)
indicator.color = .red
// Scale 2.5 เท่า
let transform = CGAffineTransform(scaleX: 2.5, y: 2.5)
indicator.transform = transform
ปัญหาของ Transform
- ภาพเบลอ (Rasterized แล้ว Scale)
- Hit Testing ผิด (Frame ไม่เปลี่ยน)
- Auto Layout Constraint ผิดปกติ
- Performance Impact
วิธีที่ถูกต้อง: ใช้ Style ที่มีอยู่
// iOS 13+ Styles
UIActivityIndicatorView(style: .medium) // 20pt
UIActivityIndicatorView(style: .large) // 37pt (Default)
// iOS 12 และก่อน
UIActivityIndicatorView(style: .white)
UIActivityIndicatorView(style: .gray)
UIActivityIndicatorView(style: .whiteLarge)
Custom Spinner (แนะนำ)
สร้าง Custom UIView Animation แทน:
class CustomActivityIndicator: UIView {
private let circleLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
let radius = min(bounds.width, bounds.height) / 2 - 2
let path = UIBezierPath(arcCenter: CGPoint(x: bounds.midX, y: bounds.midY),
radius: radius,
startAngle: -CGFloat.pi/2,
endAngle: 3*CGFloat.pi/2,
clockwise: true)
circleLayer.path = path.cgPath
circleLayer.strokeColor = UIColor.systemBlue.cgColor
circleLayer.lineWidth = 3
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineCap = .round
layer.addSublayer(circleLayer)
}
func startAnimating() {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 1
animation.repeatCount = .infinity
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
circleLayer.add(animation, forKey: "spin")
isHidden = false
}
func stopAnimating() {
circleLayer.removeAllAnimations()
isHidden = true
}
}
Library แนะนำ
- NVActivityIndicatorView - 30+ Animation Styles, Customizable Size/Color
- ProgressHUD - รวม HUD + Indicator
- Lottie - After Effects Animation (Vector, Sharp ทุกขนาด)
Lottie Example
import Lottie
let animationView = LottieAnimationView(name: "loading")
animationView.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .loop
animationView.play()
view.addSubview(animationView)
สรุป: อย่าใช้ Transform Scale ใช้ Style ที่มี, Custom CAShapeLayer, หรือ Lottie เพื่อคุณภาพสูง