web-dev-qa-db-de.com

Abgerundete Ecken nur auf einer UIView

Hallo, ich suche eine saubere Lösung, ohne drawRect oder ähnliches zu überschreiben, um eine UIView mit abgerundeten Ecken oben in der Ansicht zu erstellen. Mein Hauptproblem hier ist das Erstellen einer variablen Lösung, wenn die Größe der Ansicht geändert wird oder ähnliches. Gibt es eine saubere Lösung? Apple tut dies auch beim ersten Tabellenelement. Das kann nicht so schwer sein.

43
mariusLAN

Sie können dies tun, indem Sie auf der Ebene Ihrer Ansicht eine mask setzen:

CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath;

self.layer.mask = maskLayer;

WICHTIG: Sie sollten dies in der layoutSubviews() -Methode Ihrer Ansicht tun, sodass die Ansicht bereits im Storyboard verkleinert wurde


In Swift <= 1,2

let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: .TopLeft | .TopRight, cornerRadii: CGSize(width: 10.0, height: 10.0)).CGPath

layer.mask = maskLayer

Swift 2.x

let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: UIRectCorner.TopLeft.union(.TopRight), cornerRadii: CGSizeMake(10, 10)).CGPath
layer.mask = maskLayer

Swift 3.x

let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10)).cgPath
layer.mask = maskLayer
150
Ashley Mills

Nur mit Swift 3.0 Versucht, Xcode 8.0:

[~ # ~] Denken Sie daran, [~ # ~] , um Ihre Schaltfläche in viewDidLayoutSubviews() oder layoutSubViews als @ festzulegen. rob beschrieb hier .

Und wenn Sie Ihren Schaltflächenhintergrund ändern möchten, müssen Sie nur anrufen:

yourButton.backgroundColor = UIColor.someColour

Quelle:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    yourButton.layer.masksToBounds = true
    yourButton.roundCorners(corners: [.topLeft,.topRight], radius: 5)
}

extension UIButton
{
    func roundCorners(corners:UIRectCorner, radius: CGFloat)
    {
        let maskLayer = CAShapeLayer()
        maskLayer.path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)).cgPath
        self.layer.mask = maskLayer
    }
}
  • Hier ist das Ergebnis:

Standardzustand:

enter image description here

Ausgewählter Zustand:

enter image description here

Ich hoffe das hilft!!

14
Nhat Dinh

Ich habe das mit Hilfe von Ashley herausgefunden.

Zunächst einmal habe ich einen UIView untergeordnet. Erstellen eines eigenen Konstruktors für meine Klasse namens - (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath;. In diesem Konstruktor bestimme ich, welche Art von Tabellenzelle ich gestalten möchte.

Dann überschreibe ich l - (void)layoutSubviews, um die CAShapeLayer zu erstellen und die Ebenenmaske anzuwenden.

.h-Dateicode

typedef enum {
    tableCellMiddle,
    tableCellTop,
    tableCellBottom,
    tableCellSingle
} tableCellPositionValue;

@interface TableCellBackgrounds : UIView
{
    tableCellPositionValue position;
}

- (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath;

@end

.m File Code

- (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath
{
    self = [super initWithFrame:aView.frame];

    [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];

    if(self)
    {
        [self setBackgroundColor:[UIColor colorWithRed:(float)230/255 green:(float)80/255 blue:(float)70/255 alpha:1]];

        if(table.style == UITableViewStyleGrouped)
        {
            int rows = [table numberOfRowsInSection:indexPath.section];


            if(indexPath.row == 0 && rows == 1)
            {
                self.layer.cornerRadius = 11;
                position = tableCellSingle;
            }
            else if (indexPath.row == 0)
                position = tableCellTop;
            else if (indexPath.row != rows - 1) 
                position = tableCellMiddle;
            else 
                position = tableCellBottom;
        }
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    if(position == tableCellTop)
    {
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:(CGSize){10.0, 10.0}].CGPath;
        self.layer.mask = maskLayer;
    }
    else if (position == tableCellBottom)
    {
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:(CGSize){10.0, 10.0}].CGPath;
        self.layer.mask = maskLayer;
    } 
}
4
mariusLAN

Eine Erweiterung für UIView, die ausgewählte Ecken rundet (Swift 4):

extension UIView {

    /// Round UIView selected corners
    ///
    /// - Parameters:
    ///   - corners: selected corners to round
    ///   - radius: round amount
    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }
}

beispiel:

ratingView.roundCorners([.topLeft, .topRight, .bottomRight], radius: 6)
3

Für iOS11 und höher können Sie die Ansichtseigenschaft verwenden:

@property CACornerMask maskedCorners

Dadurch wird festgelegt, welche der vier Ecken bei Verwendung von cornerRadius property maskiert wird. Standardeinstellung für alle vier Ecken. (Apple-Dokument)

2
Fede Henze

Mit Swift 3.0 klappte das unten für mich

let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10)).cgPath
(imageView.)layer.mask = maskLayer

Wichtig: Stellen Sie sicher, dass es sich bei 'layoutSubviews' nicht um 'awakeFromNib' (wenn Sie eine TableViewCell verwenden) oder ähnliche für UIView oder um die obere linke Ecke.

2
nlapham21

Moderne & einfache Lösung

iOS 11 +

Jetzt haben wir die Eigenschaft maskedCorners auf der Ebene der Ansicht und das macht das Leben viel einfacher.

Stellen Sie einfach Ihren gewünschten Eckenradius ein und legen Sie fest, welche Ecken maskiert werden sollen. Das Beste daran ist, dass dies gut mit Rändern funktioniert - der Ebenenrand folgt dem Rand der Ebene, unabhängig davon, ob er abgerundet ist oder nicht! Probieren Sie den folgenden Code auf einem Spielplatz aus (denken Sie daran, die Live-Ansicht durch Drücken von command+option+return Zu öffnen, damit Sie sehen können, wie sie aussieht.)

import UIKit
import PlaygroundSupport

let wrapperView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 160))
wrapperView.backgroundColor = .lightGray

let roundedCornerView = UIView(frame: CGRect(x: 50, y: 50, width: 300, height: 60))
roundedCornerView.backgroundColor = .white

wrapperView.addSubview(roundedCornerView)

roundedCornerView.layer.cornerRadius = 10
roundedCornerView.layer.borderColor = UIColor.red.cgColor
roundedCornerView.layer.borderWidth = 1


// this is the key part - try out different corner combinations to achieve what you need
roundedCornerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]


PlaygroundPage.current.liveView = wrapperView

So sieht es aus:

enter image description here

1
Trev14
 CAShapeLayer * maskLayer = [CAShapeLayer layer];
    maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: registerbtn.bounds byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii: (CGSize){9.0, 12.0}].CGPath;

    registerbtn.layer.mask = maskLayer;

dadurch wird nur eine abgerundete Ecke ausgeführt

0
user7305997