2013-05-11 36 views
6

Tôi đang làm việc trên một thanh tiến trình hình tròn cho chế độ xem thành tích của trung tâm trò chơi tùy chỉnh và tôi có loại "nhấn tường". Tôi đang đấu tranh với điều này trong hơn hai giờ và vẫn không thể làm cho nó hoạt động.Sử dụng thanh tiến trình hình tròn với hình ảnh có mặt nạ?

Vấn đề là tôi cần một thanh tiến trình hình tròn, nơi tôi có thể đặt (ít nhất) hình ảnh bản nhạc (điền). Bởi vì tiến trình điền của tôi là một cầu vồng như gradient và tôi không thể đạt được kết quả tương tự chỉ bằng cách sử dụng mã.

Tôi đã làm phiền với CALayers và phương thức drawRect, tuy nhiên tôi đã không thành công. Bạn có thể vui lòng cho tôi một chút hướng dẫn không?

Dưới đây là ví dụ về các thanh tiến trình hình tròn: https://github.com/donnellyk/KDGoalBar https://github.com/danielamitay/DACircularProgress

Tôi chỉ cần điền là một hình ảnh đeo mặt nạ, tùy thuộc vào sự tiến bộ. Nếu bạn thậm chí có thể làm cho nó hoạt rằng sự tiến bộ sẽ được hoạt hình, đó sẽ là thực sự mát mẻ, nhưng tôi không yêu cầu sự giúp đỡ với điều đó :)

Cảm ơn, Nick

+0

Vậy là nó mặt nạ hoặc vẽ một "cầu vồng" như gradient đang dừng bạn?Hay là ghép hai miếng lại với nhau? –

+0

Tôi có thể đã mô tả nó không rõ ràng, xin lỗi vì điều đó - Tôi không muốn vẽ một gradient, tôi có một tô tròn tô tròn rất đẹp cho thanh tiến trình được thực hiện trong Photoshop, và tôi chỉ cần che nó, vì vậy nó là điền vào thanh tiến trình. Bạn biết ý tôi là gì không? :) –

Trả lời

23

Bạn về cơ bản chỉ cần xây dựng một con đường xác định khu vực cần điền (ví dụ: sử dụng CGPathAddArc), cắt bối cảnh đồ họa vào đường dẫn đó bằng cách sử dụng CGContextClip và sau đó chỉ cần vẽ hình ảnh của bạn.

Dưới đây là một ví dụ về một phương pháp drawRect: bạn có thể sử dụng trong một giao diện tùy chỉnh:

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef ctx = UIGraphicsGetCurrentContext(); 

    CGFloat progress = 0.7f; //This would be a property of your view 
    CGFloat innerRadiusRatio = 0.5f; //Adjust as needed 

    //Construct the path: 
    CGMutablePathRef path = CGPathCreateMutable(); 
    CGFloat startAngle = -M_PI_2; 
    CGFloat endAngle = -M_PI_2 + MIN(1.0f, progress) * M_PI * 2; 
    CGFloat outerRadius = CGRectGetWidth(self.bounds) * 0.5f - 1.0f; 
    CGFloat innerRadius = outerRadius * innerRadiusRatio; 
    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 
    CGPathAddArc(path, NULL, center.x, center.y, innerRadius, startAngle, endAngle, false); 
    CGPathAddArc(path, NULL, center.x, center.y, outerRadius, endAngle, startAngle, true); 
    CGPathCloseSubpath(path); 
    CGContextAddPath(ctx, path); 
    CGPathRelease(path); 

    //Draw the image, clipped to the path: 
    CGContextSaveGState(ctx); 
    CGContextClip(ctx); 
    CGContextDrawImage(ctx, self.bounds, [[UIImage imageNamed:@"RadialProgressFill"] CGImage]); 
    CGContextRestoreGState(ctx); 
} 

Để giữ cho nó đơn giản, tôi đã một vài điều mã hóa cứng - bạn rõ ràng là cần phải thêm một tài sản cho progress và gọi setNeedsDisplay trong setter. Điều này cũng giả định rằng bạn có một hình ảnh có tên là RadialProgressFill trong dự án của bạn.

Dưới đây là một ví dụ về những gì mà xấp xỉ sẽ trông như thế:

Screenshot

Tôi hy vọng bạn có một hình nền đẹp hơn. ;)

+0

Tôi hy vọng sẽ có càng nhiều người như bạn - điều này còn nhiều hơn tôi mong đợi! Cảm ơn bạn rất nhiều cho câu trả lời chi tiết của bạn - Tôi đã thưởng cho bạn :) –

+0

@DominikHadl Làm thế nào và nơi để cal phương pháp này - (void) drawRect: (CGRect) rect –

+0

@ yz nó thực sự hữu ích .. :) –

0

Giải pháp mà omz đề xuất làm việc tụt hậu khi tôi cố gắng tạo ra bất động sản, vì vậy tôi tiếp tục tìm kiếm. Tìm thấy giải pháp tuyệt vời - để sử dụng khung cốt lõi của Quartz Core và trình bao bọc được gọi là CADisplayLink. "Lớp này được thực hiện cụ thể cho hình ảnh động nơi‘dữ liệu của bạn là rất có khả năng thay đổi trong mỗi khung’. Nó cố gắng để gửi một thông điệp tới một mục tiêu mỗi khi một cái gì đó được vẽ lại vào màn hình" Source

library rằng làm việc theo cách đó.

Chỉnh sửa: Nhưng có giải pháp hiệu quả hơn. Để tạo hiệu ứng mặt nạ được áp dụng trên lớp với hình ảnh. Tôi không biết tại sao tôi không làm điều đó ngay từ đầu. CABasicAnimation hoạt động nhanh hơn bất kỳ bản vẽ tùy chỉnh nào. Dưới đây là thực hiện của tôi:

class ProgressBar: UIView { 
    var imageView:UIImageView! 

    var maskLayer: CAShapeLayer! 
    var currentValue: CGFloat = 1 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     updateUI() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     updateUI() 
    } 

    func updateUI(){ 
     makeGradient() 
     setUpMask() 
    } 

    func animateCircle(strokeEnd: CGFloat) { 
     let oldStrokeEnd = maskLayer.strokeEnd 
     maskLayer.strokeEnd = strokeEnd 

     //override strokeEnd implicit animation 
     let animation = CABasicAnimation(keyPath: "strokeEnd") 
     animation.duration = 0.5 
     animation.fromValue = oldStrokeEnd 
     animation.toValue = strokeEnd 
     animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     maskLayer.add(animation, forKey: "animateCircle") 

     currentValue = strokeEnd 
    } 

    func setUpMask(){ 

     let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width/2.0, y: frame.size.height/2.0), 
             radius: (frame.size.width - 10)/2, 
             startAngle: -CGFloat.pi/2, 
             endAngle: CGFloat.pi*1.5, 
             clockwise: true) 

     maskLayer = CAShapeLayer() 
     maskLayer.path = circlePath.cgPath 
     maskLayer.fillColor = UIColor.clear.cgColor 
     maskLayer.strokeColor = UIColor.red.cgColor 
     maskLayer.lineWidth = 8.0; 
     maskLayer.strokeEnd = currentValue 
     maskLayer.lineCap = "round" 
     imageView.layer.mask = maskLayer 
    } 

    func makeGradient(){ 
     imageView = UIImageView(image: UIImage(named: "gradientImage")) 
     imageView.frame = bounds 
     imageView.contentMode = .scaleAspectFill 
     addSubview(imageView) 
    } 

} 

Bằng cách này, nếu bạn đang tìm kiếm để trở nên tốt hơn ở hình ảnh động, tôi đề nghị một cuốn sách tuyệt vời "IOS Core Animation: Kỹ thuật nâng cao Sách Nick Lockwood"

Các vấn đề liên quan