19

cornerRadiusのレイヤーに適用し、と を介してUIImageView境界線を追加するだけで、丸いアバターの写真を描いています。そのようです:borderWithborderColor

self.layer.masksToBounds = YES;
self.layer.cornerRadius = imageDimension / 2.f;
self.layer.borderWidth = 1.f;
self.layer.borderColor = borderColor.CGColor;

次のように、境界線の外側のコンテンツの小さな、しかし目立つ出血を除いて、これはうまく機能します。

マスクと境界線の外側にコンテンツがにじむ

境界線を数 1/10 ポイントだけアウトセットする方法、または境界線よりもコンテンツを挿入する方法はありますか?


解決

FelixLam のおかげで、私は素晴らしい解決策を思いついたので、後世のためにここに残します。

@interface MMRoundImageViewWithBorder : UIView

- (id)initWithImage:(UIImage *)image borderWidth:(CGFloat)borderWidth;

@property (strong, nonatomic) UIImageView *imageView;
@property (assign, nonatomic) CGFloat borderWidth;
@property (strong, nonatomic) UIColor *borderColor;

@end

@implementation MMRoundImageViewWithBorder

- (id)initWithImage:(UIImage *)image borderWidth:(CGFloat)borderWidth {
    if (self = [super init]) {
        self.borderWidth = borderWidth;
        self.borderColor = UIColor.whiteColor;

        self.imageView = [[UIImageView alloc] initWithImage:image];
        [self addSubview:self.imageView];

        self.imageView.layer.masksToBounds = YES;
        self.layer.masksToBounds = YES;
    }
    return self;
}

- (void)setBorderColor:(UIColor *)borderColor {
    _borderColor = borderColor;
    self.backgroundColor = borderColor;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    [self refreshDimensions];
}

- (void)refreshDimensions {
    self.layer.cornerRadius = CGRectGetWidth(self.bounds) / 2.f;

    self.imageView.frame = CGRectInset(self.bounds, _borderWidth, _borderWidth);
    self.imageView.layer.cornerRadius = CGRectGetWidth(self.imageView.bounds) / 2.f;
}

- (void)setBorderWidth:(CGFloat)borderWidth {
    _borderWidth = borderWidth;
    [self refreshDimensions];
}

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    [self refreshDimensions];
}

@end
4

7 に答える 7

0

UIImageViewこれは、この問題を解決するのサブクラスです。

受け入れられた回答が示唆するようCAShapeLayerに、境界線の幅と角の半径が「必要」よりも1px大きい丸みを追加します。そのフレームは から始まりCGPoint(x: 1, y: 1)、画像ビューの高さより 2px 大きい高さを持っています。そうすることで裏写りをカバーしてくれます。

Swift 3+ ソリューション

サブクラス:

class BorderedRoundedImageView: UIImageView {
    let borderLayer = CALayer()
    
    var borderWidth: CGFloat!
    var borderColor: UIColor!
    
    func setUp() {
        borderLayer.borderWidth = borderWidth + 1
        borderLayer.borderColor = borderColor.cgColor
        layer.addSublayer(borderLayer)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        borderLayer.cornerRadius = layer.cornerRadius + 1
        borderLayer.frame = CGRect(x: -1, y: -1, width: frame.width + 2, height: frame.height + 2)
    }
}

使用法:

@IBOutlet weak var imageView: UIImageView!

[...]

imageView.layer.cornerRadius = 20
imageView.borderWidth = 2
imageView.borderColor = .lightGray
imageView.setUp()

結果:

結果のスクリーンショット

于 2018-09-06T13:25:39.023 に答える
-1

私は同じ問題を抱えており、ストーリーボードでうまく機能するソリューションが必要でした. 私がしたことは、画像をビュー内に配置し、両方を動作を制御するカスタム クラスに設定することでした。ストーリーボードからデザインを完全に制御できるようになりました。

コードを GitHub に配置しました。

https://github.com/brennanMKE/CircleButton

それが行うことは、UIButton と通常の UIView の両方で UIView の drawRect 関数をオーバーライドして、多くのビューで動作できるようにすることです。境界線の色と幅を制御するために、ラッパー ビューも使用されます。ラップされたビューとスーパービューの間にマージンがあることを確認し、その差を境界線の幅として使用します。スーパービューの背景色が枠の色になります。これで、各インスタンスをカスタム コーディングすることなく、ストーリーボードの多くのシーンでこれらの変更をすばやく行うことができます。

- (void)drawRect:(CGRect)rect {
    // round view and superview with a border using the background color of the superview
    self.layer.cornerRadius = CGRectGetWidth(self.frame) / 2;
    self.layer.masksToBounds = YES;

    if ([self.superview isKindOfClass:[SSTCircleWrapperView class]]) {
        self.superview.layer.cornerRadius = CGRectGetWidth(self.superview.frame) / 2;
        self.superview.layer.masksToBounds = YES;
        self.superview.layer.borderColor = self.superview.backgroundColor.CGColor;
        self.superview.layer.borderWidth = (CGRectGetWidth(self.superview.frame) - CGRectGetWidth(self.frame)) / 2;
    }
}
于 2013-11-13T07:14:10.773 に答える
-1

設定してみてください:

[self setClipToBounds:YES]
于 2013-10-24T12:22:14.193 に答える