私のアプリケーションでは、次の4つのボタンがあります。
ボタンの上には、画像ビュー(またはUIView)があります。
ここで、ユーザーが-上-左ボタンをタップしたとします。上記の画像/ビューは、その特定の角で丸くする必要があります。
UIViewに丸い角を適用するのに多少の困難があります。
現在、次のコードを使用して、丸い角を各ビューに適用しています。
// imgVUserImg is a image view on IB.
imgVUserImg.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"any Url Here"];
CALayer *l = [imgVUserImg layer];
[l setMasksToBounds:YES];
[l setCornerRadius:5.0];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor darkGrayColor] CGColor]];
上記のコードは、提供されたビューの各コーナーに丸みを適用しています。代わりに、上/上+左/下+右などのように、選択した角に丸みを付けたいだけです.
出来ますか?どうやって?
iPhoneで角の丸いUILabelを作成するにはどうすればよいですか? および iphoneで透明度のある丸い四角形のビューをどのように作成しますか? で答えを使用しましたこのコード。
その後、間違った質問に答えていることに気付きました(UIImageの代わりに丸いUILabelを使用しました)ので、このコードを使用して変更しました。
http://discussions.Apple.com/thread.jspa?threadID=1683876
Viewテンプレートを使用してiPhoneプロジェクトを作成します。 View Controllerで、これを追加します:
- (void)viewDidLoad
{
CGRect rect = CGRectMake(10, 10, 200, 100);
MyView *myView = [[MyView alloc] initWithFrame:rect];
[self.view addSubview:myView];
[super viewDidLoad];
}
MyView
は、単にUIImageView
サブクラスです。
@interface MyView : UIImageView
{
}
これまでグラフィックコンテキストを使用したことはありませんでしたが、このコードを一緒にまとめることができました。 2つのコーナーのコードがありません。コードを読むと、これをどのように実装したかを見ることができます(CGContextAddArc
呼び出しの一部を削除し、コード内の半径値の一部を削除します。すべてのコーナーのコードがあります。開始点として、不要なコーナーを作成する部分を削除します必要に応じて、2つまたは3つの丸いコーナーを持つ長方形を作成することもできます。
コードは完全ではありませんが、少しは片付けることができると確信しています。
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, int roundedCornerPosition)
{
// all corners rounded
// CGContextMoveToPoint(context, rect.Origin.x, rect.Origin.y + radius);
// CGContextAddLineToPoint(context, rect.Origin.x, rect.Origin.y + rect.size.height - radius);
// CGContextAddArc(context, rect.Origin.x + radius, rect.Origin.y + rect.size.height - radius,
// radius, M_PI / 4, M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.Origin.x + rect.size.width - radius,
// rect.Origin.y + rect.size.height);
// CGContextAddArc(context, rect.Origin.x + rect.size.width - radius,
// rect.Origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
// CGContextAddLineToPoint(context, rect.Origin.x + rect.size.width, rect.Origin.y + radius);
// CGContextAddArc(context, rect.Origin.x + rect.size.width - radius, rect.Origin.y + radius,
// radius, 0.0f, -M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.Origin.x + radius, rect.Origin.y);
// CGContextAddArc(context, rect.Origin.x + radius, rect.Origin.y + radius, radius,
// -M_PI / 2, M_PI, 1);
// top left
if (roundedCornerPosition == 1) {
CGContextMoveToPoint(context, rect.Origin.x, rect.Origin.y + radius);
CGContextAddLineToPoint(context, rect.Origin.x, rect.Origin.y + rect.size.height - radius);
CGContextAddArc(context, rect.Origin.x + radius, rect.Origin.y + rect.size.height - radius,
radius, M_PI / 4, M_PI / 2, 1);
CGContextAddLineToPoint(context, rect.Origin.x + rect.size.width,
rect.Origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.Origin.x + rect.size.width, rect.Origin.y);
CGContextAddLineToPoint(context, rect.Origin.x, rect.Origin.y);
}
// bottom left
if (roundedCornerPosition == 2) {
CGContextMoveToPoint(context, rect.Origin.x, rect.Origin.y);
CGContextAddLineToPoint(context, rect.Origin.x, rect.Origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.Origin.x + rect.size.width,
rect.Origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.Origin.x + rect.size.width, rect.Origin.y);
CGContextAddLineToPoint(context, rect.Origin.x + radius, rect.Origin.y);
CGContextAddArc(context, rect.Origin.x + radius, rect.Origin.y + radius, radius,
-M_PI / 2, M_PI, 1);
}
// add the other corners here
CGContextClosePath(context);
CGContextRestoreGState(context);
}
-(UIImage *)setImage
{
UIImage *img = [UIImage imageNamed:@"my_image.png"];
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, w, h);
addRoundedRectToPath(context, rect, 50, 1);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, rect, img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
return [UIImage imageWithCGImage:imageMasked];
}
代替テキストhttp://nevan.net/skitch/skitched-20100224-092237.png
これを機能させるには、QuartzCoreフレームワークをそこに入れる必要があることを忘れないでください。
IOS 3.2以降では、UIBezierPath
sの機能を使用して、すぐに使用可能な丸みのある四角形を作成できます(指定した角のみが丸みを帯びます)。次に、これをCAShapeLayer
のパスとして使用し、これをビューのレイヤーのマスクとして使用できます。
// Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds
byRoundingCorners:UIRectCornerTopLeft
cornerRadii:CGSizeMake(10.0, 10.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = imageView.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
imageView.layer.mask = maskLayer;
そしてそれだけです-Core Graphicsで手動でシェイプを定義することをいじったり、Photoshopでマスキングイメージを作成したりする必要はありません。レイヤーは無効化する必要さえありません。丸い角の適用または新しい角への変更は、新しいUIBezierPath
を定義し、そのCGPath
をマスクレイヤーのパスとして使用するのと同じくらい簡単です。 bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
メソッドのcorners
パラメーターはビットマスクであるため、複数の角をORすることで丸めることができます。
これに影を追加する場合は、もう少し作業が必要です。
「imageView.layer.mask = maskLayer
」はマスクを適用するため、通常、影はマスクの外側に表示されません。秘Theは、透明なビューを使用し、2つのサブレイヤー(CALayer
s)をビューのレイヤーに追加することです:shadowLayer
とroundedLayer
。両方ともUIBezierPath
を使用する必要があります。画像はroundedLayer
のコンテンツとして追加されます。
// Create a transparent view
UIView *theView = [[UIView alloc] initWithFrame:theFrame];
[theView setBackgroundColor:[UIColor clearColor]];
// Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:theView.bounds
byRoundingCorners:UIRectCornerTopLeft
cornerRadii:CGSizeMake(10.0f, 10.0f)];
// Create the shadow layer
CAShapeLayer *shadowLayer = [CAShapeLayer layer];
[shadowLayer setFrame:theView.bounds];
[shadowLayer setMasksToBounds:NO];
[shadowLayer setShadowPath:maskPath.CGPath];
// ...
// Set the shadowColor, shadowOffset, shadowOpacity & shadowRadius as required
// ...
// Create the rounded layer, and mask it using the rounded mask layer
CALayer *roundedLayer = [CALayer layer];
[roundedLayer setFrame:theView.bounds];
[roundedLayer setContents:(id)theImage.CGImage];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
[maskLayer setFrame:theView.bounds];
[maskLayer setPath:maskPath.CGPath];
roundedLayer.mask = maskLayer;
// Add these two layers as sublayers to the view
[theView.layer addSublayer:shadowLayer];
[theView.layer addSublayer:roundedLayer];
このコードはコードの多くの場所で使用しており、100%正しく動作します。 1つのプロパティ「byRoundingCorners:UIRectCornerBottomLeft」を変更することで、任意のコーダーを変更できます。
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerBottomLeft cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = view.bounds;
maskLayer.path = maskPath.CGPath;
view.layer.mask = maskLayer;
[maskLayer release];
IOS 11では、一部のコーナーのみをラウンドできるようになりました
let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 8
view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
特定のコーナーを丸くするためのStuartsの例はうまく機能します。あなたが左上と右のような複数の角を丸くしたい場合、これはそれを行う方法です
// Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageview
byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight
cornerRadii:CGSizeMake(10.0, 10.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = imageview.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
imageview.layer.mask = maskLayer;
共有してくれてありがとう。ここで、この問題のさらなる参照のためにSwift 2.0でソリューションを共有したいと思います。(UIRectCornerのプロトコルに準拠するため)
let mp = UIBezierPath(roundedRect: cell.bounds, byRoundingCorners: [.bottomLeft, .TopLeft], cornerRadii: CGSize(width: 10, height: 10))
let ml = CAShapeLayer()
ml.frame = self.bounds
ml.path = mp.CGPath
self.layer.mask = ml
Swift 3以降構文を使用したCALayer拡張
extension CALayer {
func round(roundedRect rect: CGRect, byRoundingCorners corners: UIRectCorner, cornerRadii: CGSize) -> Void {
let bp = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: cornerRadii)
let sl = CAShapeLayer()
sl.frame = self.bounds
sl.path = bp.cgPath
self.mask = sl
}
}
次のように使用できます。
let layer: CALayer = yourView.layer
layer.round(roundedRect: yourView.bounds, byRoundingCorners: [.bottomLeft, .topLeft], cornerRadii: CGSize(width: 5, height: 5))
ニーズに応じて機能し、シャドウでも機能する、より簡単で迅速な回答があります。スーパーレイヤーのmaskToBoundsをtrueに設定し、2つのコーナーがスーパーレイヤーの境界の外側になるように子レイヤーをオフセットし、2辺の丸いコーナーを効果的に切り取ります。
もちろん、これは同じ側に2つの丸い角だけを持ちたい場合にのみ機能し、片側から数ピクセルを切り取るとレイヤーのコンテンツは同じように見えます。棒グラフの上側のみを丸めるのに最適です。
この関連する質問 を参照してください。 some角の丸いCGPath
に独自の長方形を描画する必要があります。CGPath
をCGContext
その後、CGContextClip
を使用してクリップします。
また、アルファ値を含む丸い四角形を画像に描画し、その画像を使用して、レイヤーのmask
プロパティとして設定する新しいレイヤーを作成できます( Appleのドキュメントを参照 )。
一部のコーナーのみを丸めると、自動サイズ変更または自動レイアウトでニースが再生されません。
したがって、別のオプションは、通常のcornerRadius
を使用し、不要なコーナーを別のビューの下またはそのスーパービュー境界の外に非表示にして、コンテンツをクリップするように設定することです。
半年ほど遅れていますが、人々がこれを行う現在の方法は100%正しいとは思いません。 UIBezierPath + CAShapeLayerメソッドを使用すると、特にStoryboardで設定されている場合、自動レイアウトに干渉するという問題が多くの人にあります。これに関する答えはありませんので、自分で追加することにしました。
それを回避する非常に簡単な方法があります:drawRect(rect: CGRect)
関数に丸い角を描きます。
たとえば、UIViewの角を丸くしたい場合は、UIViewをサブクラス化し、適切な場所でそのサブクラスを使用します。
import UIKit
class TopRoundedView: UIView {
override func drawRect(rect: CGRect) {
super.drawRect(rect)
var maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: UIRectCorner.TopLeft | UIRectCorner.TopRight, cornerRadii: CGSizeMake(5.0, 5.0))
var maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds
maskLayer.path = maskPath.CGPath
self.layer.mask = maskLayer
}
}
これは問題を克服する最良の方法であり、順応するのにまったく時間をかけません。
answer および addition に追加するために、Swiftでシンプルで再利用可能なUIView
を作成しました。ユースケースに応じて、変更を加えたい場合があります(すべてのレイアウトでオブジェクトを作成するなどを避けます)が、できるだけシンプルにしたかったのです。この拡張機能を使用すると、サブクラス化が気に入らない場合に、他のビュー(例:UIImageView
)にこれを簡単に適用できます。
extension UIView {
func roundCorners(_ roundedCorners: UIRectCorner, toRadius radius: CGFloat) {
roundCorners(roundedCorners, toRadii: CGSize(width: radius, height: radius))
}
func roundCorners(_ roundedCorners: UIRectCorner, toRadii cornerRadii: CGSize) {
let maskBezierPath = UIBezierPath(
roundedRect: bounds,
byRoundingCorners: roundedCorners,
cornerRadii: cornerRadii)
let maskShapeLayer = CAShapeLayer()
maskShapeLayer.frame = bounds
maskShapeLayer.path = maskBezierPath.cgPath
layer.mask = maskShapeLayer
}
}
class RoundedCornerView: UIView {
var roundedCorners: UIRectCorner = UIRectCorner.allCorners
var roundedCornerRadii: CGSize = CGSize(width: 10.0, height: 10.0)
override func layoutSubviews() {
super.layoutSubviews()
roundCorners(roundedCorners, toRadii: roundedCornerRadii)
}
}
UIViewController
に適用する方法は次のとおりです。
class MyViewController: UIViewController {
private var _view: RoundedCornerView {
return view as! RoundedCornerView
}
override func loadView() {
view = RoundedCornerView()
}
override func viewDidLoad() {
super.viewDidLoad()
_view.roundedCorners = [.topLeft, .topRight]
_view.roundedCornerRadii = CGSize(width: 10.0, height: 10.0)
}
}
レイヤーのマスクを定義することをお勧めします。マスク自体は、専用パスを持つCAShapeLayer
オブジェクトでなければなりません。次のUIView拡張機能(Swift 4.2)を使用できます。
extension UIView {
func round(corners: UIRectCorner, with radius: CGFloat) {
let maskLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = UIBezierPath(
roundedRect: bounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius)
).cgPath
layer.mask = maskLayer
}
}
スチュアートの答えをまとめると、次のように角を丸める方法を使用できます。
@implementation UIView (RoundCorners)
- (void)applyRoundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
@end
したがって、角丸を適用するには、次のようにします。
[self.imageView applyRoundCorners:UIRectCornerTopRight|UIRectCornerTopLeft radius:10];