Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> iOS

สามารถเปลี่ยนขนาด UIActivityIndicatorView ใน Swift ได้หรือไม่

สามารถเปลี่ยนขนาดได้ด้วย 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 เพื่อคุณภาพสูง