2017-10-28 3 views

Antwort

0

Wenn Sie kennen die Akkordposition Sie kann den Akkord füllen, indem Sie den Clip-Bereich einstellen und dann den Kreis füllen.

Um die Position des Akkords zu bestimmen, um einen Bereich von x% zu erhalten, müssen Sie einige Geometrie/Trigonometrie durchführen. Jeder Akkord, der nicht durch das Zentrum verläuft, bildet ein gleichschenkliges Dreieck mit dem Mittelpunkt, und die beiden Seiten dieses Dreiecks, die Radien sind, begrenzen ein Segment des Kreises. Der Bereich auf einer Seite eines Akkords, der nicht durch das Zentrum verläuft, ist also die Differenz der Fläche eines Dreiecks und eines Segments, und Sie können herausfinden, wie der Akkord den Bereich teilt oder wo der Akkord sein muss, um das zu teilen Bereich in einem bestimmten Verhältnis.

Wenn das alles klingt wie Goobbledegook versuchen Sie Akkordgeometrie nachschlagen und Sie werden zweifellos Bücher/Websites mit hilfreichen Diagrammen und Formeln finden.

HTH

1

Der einfachste Ansatz eine Ansicht mit zwei Subviews zu haben wäre, ein für die grünen „Prozent gefüllt“ Niveau, und einem für das Etikett für den Text. Dann können Sie die frame für die "Prozent gefüllt" basierend auf, natürlich, wie viel Prozent gefüllt Sie wollen es aktualisieren. Und dann wenden Sie eine kreisförmige Maske auf das Ganze an.

Zum Beispiel:

// CircleLevelView.h 
// 
// Created by Robert Ryan on 10/28/17. 

#import <UIKit/UIKit.h> 

IB_DESIGNABLE 
@interface CircleLevelView : UIView 

/// Percent filled 
/// 
/// Value between 0.0 and 1.0. 

@property (nonatomic)   IBInspectable CGFloat percent; 

/// Text to show up in center of view 
/// 
/// Value between 0.0 and 1.0. 

@property (nonatomic, strong) IBInspectable NSString *text; 

@end 

Und

// CircleLevelView.m 
// 
// Created by Robert Ryan on 10/28/17. 

#import "CircleLevelView.h" 

@interface CircleLevelView() 
@property (nonatomic, weak) CAShapeLayer *circleMask; 
@property (nonatomic, weak) UILabel *label; 
@property (nonatomic, weak) UIView *fillView; 

@end 

@implementation CircleLevelView 

@synthesize percent = _percent; 

- (instancetype)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 

    [self configure]; 

    return self; 
} 

- (instancetype)initWithFrame:(CGRect)frame { 
    self = [super initWithFrame:frame]; 

    [self configure]; 

    return self; 
} 

- (instancetype)init { 
    return [self initWithFrame:CGRectZero]; 
} 

- (void)configure { 
    self.clipsToBounds = true; 

    UILabel *fillView = [[UILabel alloc] init]; 
    fillView.translatesAutoresizingMaskIntoConstraints = false; 
    fillView.backgroundColor = [UIColor colorWithRed:169.0/255.0 
               green:208.0/255.0 
               blue:66.0/255.0 
               alpha:1.0]; 
    [self addSubview:fillView]; 
    self.fillView = fillView; 

    UILabel *label = [[UILabel alloc] init]; 
    label.translatesAutoresizingMaskIntoConstraints = false; 
    label.backgroundColor = [UIColor clearColor]; 
    label.textColor = [UIColor blackColor]; 
    label.textAlignment = NSTextAlignmentCenter; 
    [self addSubview:label]; 
    self.label = label; 

    [NSLayoutConstraint activateConstraints:@[ 
     [label.topAnchor constraintEqualToAnchor:self.topAnchor], 
     [label.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], 
     [label.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], 
     [label.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], 
     [fillView.topAnchor constraintEqualToAnchor:self.topAnchor], 
     [fillView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], 
     [fillView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], 
     [fillView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor] 
    ]]; 

    CAShapeLayer *circleMask = [CAShapeLayer layer]; 
    circleMask.fillColor = [UIColor whiteColor].CGColor; 
    circleMask.strokeColor = [UIColor blackColor].CGColor; 
    circleMask.lineWidth = 0; 
    self.layer.mask = circleMask; 
    self.circleMask = circleMask; 
} 

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    CGPoint center = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2.0, self.bounds.origin.y + self.bounds.size.height/2.0); 
    CGFloat radius = MIN(self.bounds.size.width, self.bounds.size.height)/2.0; 
    self.circleMask.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI * 2.0 clockwise:true].CGPath; 

    [self updatePercentFill]; 
} 

- (void)updatePercentFill { 
    CGFloat circleHeight = MIN(self.bounds.size.width, self.bounds.size.height); 
    CGFloat percentHeight = circleHeight * self.percent; 
    self.fillView.frame = CGRectMake(0, 
            (self.bounds.size.height - circleHeight)/2 + (circleHeight - percentHeight), 
            self.bounds.size.width, 
            circleHeight); 
} 

// MARK: - Custom Accessor Methods 

- (CGFloat)percent { 
    return _percent; 
} 

- (void)setPercent:(CGFloat)percent { 
    _percent = percent; 

    [self updatePercentFill]; 
} 

- (NSString *)text { 
    return self.label.text; 
} 

- (void)setText:(NSString *)text { 
    self.label.text = text; 
} 

@end 

Das ergibt:

enter image description here

+0

Ist Ihr zu 75% gefüllter Kreis nicht näher an 80% gefüllt? ;-) – CRD

+0

Es ist 75% der Höhe, aber nicht 75% des Volumens. Es hängt davon ab, was das OP will. Und die Wahl der Schriftgröße in Relation zur Höhe des Kreises wirkt sich auch auf den visuellen Effekt aus. – Rob

Verwandte Themen