Как нарисовать пользовательский интерфейс UIView в виде круга - приложение для iPhone

129

Как мне нарисовать пользовательский интерфейс UIView, который буквально представляет собой просто мяч (2D-круг)? Мог бы я просто переопределить метод drawRect? А может кто-нибудь подскажет код рисования синего круга?

Кроме того, можно ли изменить рамку этого представления в самом классе? Или мне нужно сменить фрейм из другого класса?

(просто пытаюсь заставить мяч подпрыгивать)

StanLe
источник

Ответы:

209

Вы можете использовать QuartzCore и сделать что-нибудь вот такое -

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
К вашему сведению, для того, чтобы ваше представление было кругом с использованием QuartCore, ваш угловой радиус должен составлять половину высоты / ширины вашего кадра. Это самый простой способ сделать круг, но не обязательно самый эффективный. Если производительность жизненно важна, drawRect, вероятно, даст лучшие результаты.
Benjamin Mayo
4
И это. 100 - это высота / ширина.
Kal
3
Да, извини, что не направил это на тебя, Кэл. Я говорил об этом StanLe на случай, если он захочет использовать виды разного размера.
Бенджамин Мэйо
Если размер вашего circleView не равен 100X100, значение cornerRadius должно быть (новый размер) / 2
gran33
Но я заметил, что круг с радиусом угла иногда имеет слегка «плоские» / обрезанные края. По крайней мере, с бордюром. Есть идеи, почему? Радиус составляет ровно половину размера изображения. Я подумал, что это может быть проблема с обрезкой, но похоже, что это не так, пробовал даже с меньшим подслоем - все равно имеет тот же эффект.
Ixx
135

Мог бы я просто переопределить метод drawRect?

Да:

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

Кроме того, можно ли изменить рамку этого представления в самом классе?

В идеале нет, но можно.

Или мне нужно сменить фрейм из другого класса?

Я позволю родителям контролировать это.

Стив
источник
1
Как установить собственные цвета, а не только синий? Я пытаюсь использовать белый и синий вот так: ([self.colorOfCircle CGColor]), но ничего не происходит: \
gaussblurinc
@loldop - это self.colorOfCircle UIColor? Это установлено? Если вы установите точку останова на этой строке и посмотрите на значение, ожидаете ли вы этого? ЕСЛИ вы установите это постфактум, вам придется аннулировать часть вашего представления, содержащую круг.
Стив
9
@gaussblurinc CGContextSetFillColorWithColor(ctx, self.colorOfCircle.CGColor);, метод, предложенный в решении, CGColorGetComponentsработает только с некоторыми цветами, см. stackoverflow.com/questions/9238743/…
yonilevy
Обратите внимание на всех, кто застрял на этом. Вместо rectэтого я случайно использовал self.frameдля эллипса. Правильное значение self.bounds. D'о! :)
Olie
31

Вот еще один способ, используя UIBezierPath (возможно, уже слишком поздно ^^). Создайте круг и замаскируйте им UIView, как показано ниже:

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;
Gintama
источник
1
На самом деле нет необходимости делать этот слой-фигуру маской; вы можете просто использовать слой-фигуру непосредственно как слой представления и задать ему цвет заливки. Маска, вероятно, значительно дороже.
Джесси Русак
Слой UIView - это CALayer, поэтому как мы можем нарисовать фигуру на этом слое. Я полагаю, что мы добавляем слой формы к слою представления, не маскируя его ??
Gintama
1
Вы можете создать подкласс UIView и переопределить layerClassметод класса, чтобы сделать его слоем формы.
Джесси Русак
@JesseRusak, проблема, с которой я столкнулся с вашим предложением (установить форму на самом слое UIView), заключается в том, что вы не можете правильно использовать backgroundColor. Вам нужно будет применить fillColor и установить для backgroundColor значение clearColor, что означает, что пользователь UIView не сможет естественным образом установить backgroundColor.
Ричард Венейбл
25

Мой вклад с расширением Swift:

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

Просто позвони myView.asCircle()

Кевин АБРИОУКС
источник
установка значения masksToBoundstrue и использование selfявляются необязательными в этом ответе, но это все еще самое короткое и лучшее решение
Макс Десятов
17

Swift 3 - кастомный класс, легко использовать повторно. Он использует backgroundColorнабор в UI Builder

import UIKit

@IBDesignable
class CircleBackgroundView: UIView {

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

}
Маца
источник
1
Превосходно. Это правильный адаптивный подход.
Уомбл,
14

Swift 3 класс:

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

Другой способ приблизиться к рисованию круга (и других фигур) - использовать маски. Вы рисуете круги или другие формы, во-первых, создавая маски нужных вам форм, во-вторых, создавая квадраты своего цвета и, в-третьих, применяя маски к этим квадратам цвета. Вы можете изменить маску или цвет, чтобы получить новый собственный круг или другую форму.

#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

Вот результат выполнения кода выше:

четыре круга

matrix3003
источник
2

Есть еще одна альтернатива для ленивых. Вы можете установить layer.cornerRadius ключевой путь для вашего представления в Интерфейсном Разработчике . Например, если у вашего представления ширина = высота 48 , установите layer.cornerRadius = 24:

введите описание изображения здесь

Однако это работает только в том случае, если у вас есть статический размер представления, (width/height is fixed)и он не показывает круг в построителе интерфейса.

user8675
источник
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        
}
Мохаммад Разипур
источник