Cách vẽ một UIView tùy chỉnh chỉ là một vòng tròn - ứng dụng iPhone


129

Làm thế nào tôi có thể vẽ một UIView tùy chỉnh theo nghĩa đen chỉ là một quả bóng (một vòng tròn 2D)? Tôi sẽ chỉ ghi đè phương thức drawRect? Và ai đó có thể chỉ cho tôi mã để vẽ một vòng tròn màu xanh không?

Ngoài ra, có thể thay đổi khung của khung nhìn đó trong chính lớp đó không? Hay tôi cần thay đổi khung hình từ một lớp khác?

(chỉ cố gắng để thiết lập một quả bóng nảy xung quanh)

Câu trả lời:


209

Bạn có thể sử dụng QuartzCore và làm một cái gì đó -

self.circleView = [[UIView alloc] initWithFrame:CGRectMake(10,20,100,100)];
self.circleView.alpha = 0.5;
self.circleView.layer.cornerRadius = 50;  // half the width/height
self.circleView.backgroundColor = [UIColor blueColor];

104
FYI, để chế độ xem của bạn là một vòng tròn sử dụng QuartCore, bán kính góc của bạn cần bằng một nửa chiều cao / chiều rộng khung hình của bạn. Đây là cách dễ nhất để tạo một vòng tròn, nhưng không nhất thiết là hiệu quả nhất. Nếu hiệu suất là quan trọng, drawRect có thể sẽ mang lại kết quả tốt hơn.
Benjamin Mayo

4
Và nó là. 100 là chiều cao / chiều rộng.
Kal

3
Vâng, xin lỗi đã không chỉ đạo điều đó với bạn, Kal. Tôi đã đề cập điều đó với StanLe trong trường hợp anh ta muốn sử dụng các khung nhìn có kích thước khác nhau.
Benjamin Mayo

Nếu kích thước CircleView của bạn không phải là 100X100, angleRadius sẽ là (kích thước mới) / 2
gran33

Nhưng tôi nhận thấy rằng hình tròn có góc cạnh đôi khi hơi "phẳng" / bị cắt bớt. Ít nhất là khi được sử dụng với một đường viền. Bất cứ ý tưởng tại sao? Bán kính chính xác bằng một nửa kích thước của khung nhìn. Tôi nghĩ rằng nó có thể là vấn đề cắt, nhưng có vẻ như không, đã thử ngay cả với một lớp con nhỏ hơn - vẫn có hiệu quả tương tự.
Ixx

135

Tôi sẽ chỉ ghi đè phương thức drawRect?

Đúng:

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextAddEllipseInRect(ctx, rect);
    CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
    CGContextFillPath(ctx);
}

Ngoài ra, có thể thay đổi khung của khung nhìn đó trong chính lớp đó không?

Lý tưởng là không, nhưng bạn có thể.

Hay tôi cần thay đổi khung hình từ một lớp khác?

Tôi sẽ để phụ huynh kiểm soát điều đó.


1
Làm cách nào tôi có thể đặt màu tùy chỉnh, không chỉ màu xanh? Tôi cố gắng sử dụng màu trắng và màu xanh như thế này: ([self.colorOfCircle CGColor]) nhưng không có gì xảy ra: \
gaussblurinc

@loldop là self.colorOfCircle một UIColor? Được đặt chưa? Nếu bạn đặt một điểm dừng trên dòng đó và xem giá trị, đó có phải là điều bạn đang mong đợi không? NẾU bạn thiết lập rằng sau thực tế, bạn sẽ phải làm mất hiệu lực phần quan điểm của bạn có chứa vòng tròn.
Steve

9
@gaussblurinc sử dụng CGContextSetFillColorWithColor(ctx, self.colorOfCircle.CGColor);, phương pháp được đề xuất trong giải pháp CGColorGetComponentschỉ hoạt động với một số màu, xem stackoverflow.com/questions/9238743/
Kẻ

Lưu ý cho bất cứ ai bị mắc kẹt về điều này. Thay vì rect, tôi vô tình sử dụng self.framecho hình elip. Giá trị đúng là self.bounds. Ôi! :)
Olie

31

Đây là một cách khác bằng cách sử dụng UIBezierPath (có lẽ đã quá muộn ^^) Tạo một vòng tròn và che dấu UIView với nó, như sau:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
view.backgroundColor = [UIColor blueColor];

CAShapeLayer *shape = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:view.center radius:(view.bounds.size.width / 2) startAngle:0 endAngle:(2 * M_PI) clockwise:YES];
shape.path = path.CGPath;
view.layer.mask = shape;

1
Không thực sự cần phải biến lớp hình dạng đó thành mặt nạ; bạn chỉ có thể sử dụng lớp hình dạng trực tiếp làm lớp của khung nhìn và tô màu cho nó. Mặt nạ có lẽ đắt hơn đáng kể.
Jesse Rusak

Lớp của UIView là CALayer vì vậy làm thế nào chúng ta có thể vẽ một hình trên lớp này. Tôi cho rằng chúng ta thêm lớp hình dạng để xem lớp mà không che giấu nó ??
Gintama

1
Bạn có thể phân lớp UIView và ghi đè layerClassphương thức lớp để biến nó thành một lớp hình dạng.
Jesse Rusak

@JlieRusak, vấn đề tôi gặp phải với đề xuất của bạn (để đặt hình dạng trên chính lớp của UIView) là bạn không thể sử dụng nềnColor đúng cách. Bạn sẽ cần phải áp dụng fillColor và đặt backgroundColor thành ClearColor, điều đó có nghĩa là người dùng của UIView sẽ không thể thiết lập nềnColor một cách tự nhiên.
Richard Venable

25

Đóng góp của tôi với tiện ích mở rộng Swift:

extension UIView {
    func asCircle() {
        self.layer.cornerRadius = self.frame.width / 2;
        self.layer.masksToBounds = true
    }
}

Chỉ cần gọi myView.asCircle()


thiết lập masksToBoundsthành đúng và sử dụng selfđều là tùy chọn trong câu trả lời này, nhưng đây vẫn là giải pháp ngắn nhất và tốt nhất
Max Desiatov

17

Swift 3 - lớp tùy chỉnh, dễ sử dụng lại. Nó sử dụng backgroundColorthiết lập trong trình xây dựng giao diện người dùng

import UIKit

@IBDesignable
class CircleBackgroundView: UIView {

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.size.width / 2
        layer.masksToBounds = true
    }

}

1
Thông minh. Đây là cách tiếp cận chính xác, thích ứng.
Womble

14

Lớp 3 Swift :

import UIKit

class CircleView: UIView {

    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else {return}

        context.addEllipse(in: rect)
        context.setFillColor(.blue.cgColor)
        context.fillPath()
    }           
}

6

Một cách khác để tiếp cận bản vẽ hình tròn (và các hình dạng khác) là sử dụng mặt nạ. Bạn vẽ các vòng tròn hoặc các hình dạng khác bằng cách, đầu tiên, tạo các mặt nạ của các hình dạng bạn cần, thứ hai, cung cấp các ô vuông màu của bạn và thứ ba, áp dụng các mặt nạ cho các ô vuông màu đó. Bạn có thể thay đổi mặt nạ hoặc màu sắc để có được một vòng tròn tùy chỉnh mới hoặc hình dạng khác.

#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *area1;
@property (weak, nonatomic) IBOutlet UIView *area2;
@property (weak, nonatomic) IBOutlet UIView *area3;
@property (weak, nonatomic) IBOutlet UIView *area4;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.area1.backgroundColor = [UIColor blueColor];
    [self useMaskFor: self.area1];

    self.area2.backgroundColor = [UIColor orangeColor];
    [self useMaskFor: self.area2];

    self.area3.backgroundColor = [UIColor colorWithRed: 1.0 green: 0.0 blue: 0.5 alpha:1.0];
    [self useMaskFor: self.area3];

    self.area4.backgroundColor = [UIColor colorWithRed: 1.0 green: 0.0 blue: 0.5 alpha:0.5];
    [self useMaskFor: self.area4];        
}

- (void)useMaskFor: (UIView *)colorArea {        
    CALayer *maskLayer = [CALayer layer];
    maskLayer.frame = colorArea.bounds;
    UIImage *maskImage = [UIImage imageNamed:@"cirMask.png"];
    maskLayer.contents = (__bridge id)maskImage.CGImage;
    colorArea.layer.mask = maskLayer;
}

@end

Đây là đầu ra của mã ở trên:

bốn vòng tròn


2

Có một lựa chọn khác cho những người lười biếng. Bạn có thể đặt layer.cornerRadius đường dẫn chính cho chế độ xem của mình trong Trình tạo giao diện . Ví dụ: nếu chế độ xem của bạn có chiều rộng = chiều cao là 48 , hãy đặt layer.cornerRadius = 24:

nhập mô tả hình ảnh ở đây

Tuy nhiên, điều này chỉ hoạt động nếu bạn có kích thước tĩnh của chế độ xem (width/height is fixed)và nó không hiển thị vòng tròn trong trình tạo giao diện.


1

Swift 3 - Xcode 8.1

@IBOutlet weak var myView: UIView!

override func viewDidLoad() {
    super.viewDidLoad() 

    let size:CGFloat = 35.0
    myView.bounds = CGRect(x: 0, y: 0, width: size, height: size)
    myView.layer.cornerRadius = size / 2
    myView.layer.borderWidth = 1
    myView.layer.borderColor = UIColor.Gray.cgColor        
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.