web-dev-qa-db-ja.com

迅速に2つの丸い角を持つ長方形を作成しますか?

Swift(Objective Cコードでも大丈夫です)に丸い角が2つだけある長方形を作成する必要があります。

現時点では、私のコードは2つの長方形を作成しています

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil);

そして

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 0, 0, nil);

そしてそれらをマージします(2つの直角の角と2つの丸い角を持っています)が、私はコードに満足しておらず、それを行うためのはるかに良い方法があるはずです。

私はiOSとグラフィカル開発とSwiftが初めてです。

37
Maralc

Swift 2.では、そうすることができます

let maskPath = UIBezierPath(roundedRect: anyView.bounds,
            byRoundingCorners: [.BottomLeft, .BottomRight],
            cornerRadii: CGSize(width: 10.0, height: 10.0))

let shape = CAShapeLayer()
shape.path = maskPath.CGPath
view.layer.mask = shape

Objective-Cでは、UIBezierPathクラスメソッドを使用できます

bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:

実装例

// set the corner radius to the specified corners of the passed container
- (void)setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
    UIBezierPath *rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                                  byRoundingCorners:corners
                                                        cornerRadii:CGSizeMake(10.0, 10.0)];
    CAShapeLayer *shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];
    view.layer.mask = shape;
}

上記のメソッドをas-

[self setMaskTo:anyView byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight];
45
Sanjay Mohnani

簡単なSwift 3の拡張機能を使用して、丸めやオプションの境界線を作成できます。

注:自動レイアウトを使用している場合、ビューが制約された後、viewDidLayoutSubviewslayoutSubviewsなどのビューライフサイクルコールバックのいずれかでこれを呼び出す必要があります。

import UIKit

extension UIView {

    /**
     Rounds the given set of corners to the specified radius

     - parameter corners: Corners to round
     - parameter radius:  Radius to round to
     */
    func round(corners: UIRectCorner, radius: CGFloat) {
        _ = _round(corners: corners, radius: radius)
    }

    /**
     Rounds the given set of corners to the specified radius with a border

     - parameter corners:     Corners to round
     - parameter radius:      Radius to round to
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        let mask = _round(corners: corners, radius: radius)
        addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
    }

    /**
     Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border

     - parameter diameter:    The view's diameter
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        layer.masksToBounds = true
        layer.cornerRadius = diameter / 2
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor;
    }

}

private extension UIView {

    @discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
        return mask
    }

    func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
        let borderLayer = CAShapeLayer()
        borderLayer.path = mask.path
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = borderColor.cgColor
        borderLayer.lineWidth = borderWidth
        borderLayer.frame = bounds
        layer.addSublayer(borderLayer)
    }

}
65
iwasrobbed

Swift 4 +、iOS 11 +

UIViewとして参照されるmyViewという名前のIBOutletが既にある場合は、ViewDidLoad()またはロードする場所に次の2行を追加してみてください。

myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]

配列を変更できます[]MinXMinYMaxX、およびMaxYの任意の組み合わせで、目的のコーナーを選択します。上記の例では、下の2つの角を丸めています。

これは単なる別のアプローチであり、設計によっては少し単純化することもできます。

29
wcarhart

Swift-一部のビューの特定の角を丸くする必要がある場合に便利なUIView拡張機能:

extension UIView {
  func round(corners: UIRectCorner, radius: CGFloat) {
    let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
  }
}

次のように使用します:

someView.round(corners: [.topLeft, .topRight], radius: 5)
21
budidino

Sanjayの優れた答えに基づいて、Swift 2.3のCALayer拡張機能を簡単に作成しました。

extension CALayer {
  func roundCorners(corners: UIRectCorner, radius: CGFloat) {
    let maskPath = UIBezierPath(roundedRect: bounds,
                                byRoundingCorners: corners,
                                cornerRadii: CGSize(width: radius, height: radius))

    let shape = CAShapeLayer()
    shape.path = maskPath.CGPath
    mask = shape
  }
}

使用法:

myView.layer.roundCorners([.TopLeft, .TopRight], radius: myCornerRadius)

Swift 3.0(この例では、境界はレイヤーからではなくビューから取得されました。ビューからの境界を使用すると、このコードがUITableViewCellのビューで動作するようになります。):

func roundCorners(corners: UIRectCorner, radius: CGFloat, viewBounds: CGRect) {

    let maskPath = UIBezierPath(roundedRect: viewBounds,
                                byRoundingCorners: corners,
                                cornerRadii: CGSize(width: radius, height: radius))

    let shape = CAShapeLayer()
    shape.path = maskPath.cgPath
    mask = shape
}

使用法:

myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
11
Eric

Swift 2.で行うことは次のとおりです。

var maskPath = UIBezierPath(roundedRect: anyView.bounds,
        byRoundingCorners: [.BottomLeft, .BottomRight],
        cornerRadii: CGSize(width: 10.0, height: 10.0))
8
Andy

2017年...

enter image description here

@IBDesignable
class RoundedEnds: UIView {

    override func layoutSubviews() { setup() } // "layoutSubviews" is best

    func setup() {
        let r = self.bounds.size.height / 2
        let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:r)
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }
}

一部のコーナーのみ、次のように変更します。

enter image description here

roundedRect: self.bounds,
  byRoundingCorners: [.topLeft, .topRight],
  cornerRadii: CGSize(width: r, height: r)

いつものように、Swiftには多くの小さな変更があります。たとえば、定数の大文字化などです。

7
Fattie

Swift 4:

let maskPath = UIBezierPath(
            roundedRect: view.bounds,
            byRoundingCorners: [.allCorners],
            cornerRadii: CGSize(width: 10.0, height: 10.0)
        )

let shape = CAShapeLayer()
shape.path = maskPath.cgPath

view.layer.mask = shape
4

Swift 3.0 GMバージョン:

import UIKit

extension UIView {

    /**
     Rounds the given set of corners to the specified radius

     - parameter corners: Corners to round
     - parameter radius:  Radius to round to
     */
    func round(corners: UIRectCorner, radius: CGFloat) {
        _round(corners: corners, radius: radius)
    }

    /**
     Rounds the given set of corners to the specified radius with a border

     - parameter corners:     Corners to round
     - parameter radius:      Radius to round to
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        let mask = _round(corners: corners, radius: radius)
        addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
    }

    /**
     Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border

     - parameter diameter:    The view's diameter
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        layer.masksToBounds = true
        layer.cornerRadius = diameter / 2
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor;
    }

}

private extension UIView {

    @discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
        return mask
    }

    func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
        let borderLayer = CAShapeLayer()
        borderLayer.path = mask.path
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = borderColor.cgColor
        borderLayer.lineWidth = borderWidth
        borderLayer.frame = bounds
        layer.addSublayer(borderLayer)
    }

}
3
cjnevin

iOS 11以降のみ| iOSの使用状況を確認できます こちら

説明

CACornerMask rawValueはUIntであるため、CACornerMaskrawValueは各_CACornerMask.Element_の合計であることがわかります。 rawValue

すなわち:

  • TopLeft(layerMinXMinYCorner)= 1
  • TopRight(layerMaxXMinYCorner)= 2
  • BottomLeft(layerMinXMaxYCorner)= 4
  • BottomRight(layerMaxXMaxYCorner)= 8

たとえば、左上および右上コーナーが必要な場合は、 CACornerMask(rawValue: 3)と入力するだけです。


UIViewの単純な拡張の下

_extension UIView {
    enum Corner:Int {
        case bottomRight = 0,
        topRight,
        bottomLeft,
        topLeft
    }

    private func parseCorner(corner: Corner) -> CACornerMask.Element {
        let corners: [CACornerMask.Element] = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]
        return corners[corner.rawValue]
    }

    private func createMask(corners: [Corner]) -> UInt {
        return corners.reduce(0, { (a, b) -> UInt in
            return a + parseCorner(corner: b).rawValue
        })
    }

    func roundCorners(corners: [Corner], amount: CGFloat = 5) {
        layer.cornerRadius = amount
        let maskedCorners: CACornerMask = CACornerMask(rawValue: createMask(corners: corners))
        layer.maskedCorners = maskedCorners
    }
}
_

次のように使用できます。

_let myRect = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
myRect.roundCorners(corners: [.topRight, .topLeft])
_
2
rawnly

次のような簡単なハックがあります。下の例のような画像をご覧ください。 赤い表示は角が丸くなり、黄色の表示(赤い表示内)は角が丸くなるのを防ぎます

enter image description here

次に、Red Viewのコードを以下に記述します。

        self.myView.layer.cornerRadius = 15

clipsToBounds = trueまたはmasksToBounds = trueのようなコードを記述しないようにしてください。

下の画像は結果です

enter image description here

Yellow Viewの配置により、どの2つの角が丸められないかが決まります。これが実装しやすいことを願っています。

0
Teena nath Paul

IWasRobbedの回答のObjective-Cバージョン:

UIView + RoundCorners.h

#import <UIKit/UIKit.h>

@interface UIView (RoundCorners)

/**
 Rounds the given set of corners to the specified radius

 - parameter corners: Corners to round
 - parameter radius:  Radius to round to
 */
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius;

/**
 Rounds the given set of corners to the specified radius with a border

 - parameter corners:     Corners to round
 - parameter radius:      Radius to round to
 - parameter borderColor: The border color
 - parameter borderWidth: The border width
 */
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

/**
 Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border

 - parameter diameter:    The view's diameter
 - parameter borderColor: The border color
 - parameter borderWidth: The border width
 */
- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

@end

UIView + RoundCorners.m

#import "UIView+RoundCorners.h"

@implementation UIView (RoundCorners)

- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
    [self _roundCorners:corners radius:radius];
}

- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
    CAShapeLayer *mask = [self _roundCorners:corners radius:radius];
    [self addBorderWithMask:mask borderColor:borderColor borderWidth:borderWidth];
}

- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
    self.layer.masksToBounds = YES;
    self.layer.cornerRadius = diameter / 2;
    self.layer.borderWidth = borderWidth;
    self.layer.borderColor = borderColor.CGColor;
}

- (CAShapeLayer *)_roundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *mask = [CAShapeLayer layer];
    mask.path = path.CGPath;
    self.layer.mask = mask;
    return mask;
}

- (void)addBorderWithMask:(CAShapeLayer *)mask borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
    CAShapeLayer *borderLayer = [CAShapeLayer layer];
    borderLayer.path = mask.path;
    borderLayer.fillColor = UIColor.clearColor.CGColor;
    borderLayer.strokeColor = borderColor.CGColor;
    borderLayer.lineWidth = borderWidth;
    borderLayer.frame = self.bounds;
    [self.layer addSublayer:borderLayer];
}

@end
0

要約すると、次のようなきれいな拡張子を作成できます。

extension UIView {

    func roundCorners(_ corners: UIRectCorner, radius: Double) {
        let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let shape = CAShapeLayer()
        shape.path = maskPath.cgPath
        layer.mask = shape
    }

}

次のように使用します。

view.roundCorners([.topRight, .bottomRight], radius: 10)

すべてのコーナーの値は次のとおりです。

  • 。左上
  • 。右上
  • 。左下の
  • 。右下
0
Archi Stepanov