GithubHelp home page GithubHelp logo

xkcornerradius's Introduction

俗话说UI有三宝,边框阴影加圆角。目前移动开发基本都是扁平化风格,很多UI设计都是边框阴影加圆角的套路,正常我们使用系统的layer就可以满足要求,虽然性能有些问题,但是始终能解决问题。但是如果涉及到某个角切圆角,或者在切指定某个圆角的同时加边框或者加阴影就比较蛋疼了。

1 先介绍一下切圆角的场景

切圆角的方式一般有两种。

第一种,使用 UIView 内嵌的 layer,直接来切圆角,方便快捷。
UIImageView *userHeaderImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"header"]];
userHeaderImgView.layer.cornerRadius = 39;
userHeaderImgView.layer.masksToBounds = YES;

好处:方便快捷,2个属性就能搞定 UIView 的圆角切割。 坏处:切的圆角会产生混合图层,影响效率。尤其对于collectionView的cell上使用复用时,会很影响帧数

第二种,使用 CAShaperLayer 搭配 UIBezierPath 路径设置切割路径,然后把 layer 设置到 UIView 的 mask 属性上。
  UIImageView *userHeaderImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"header"]];
  CAShapeLayer *cornerLayer = [CAShapeLayer layer];
  UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:userHeaderImgView.bounds cornerRadius:39];
  cornerLayer.path = cornerPath.CGPath;
  cornerLayer.frame = userHeaderImgView.bounds;
  userHeaderImgView.layer.mask = cornerLayer;

好处:切割的圆角不会产生混合图层,提高效率,并且可以分别控制四个角的圆角。 坏处:代码量偏多, 该方式API都必须使用frame,所以对于使用使用约束布局的view就需要事先写死高度。不方便。


实际运用

项目中有时常用到卡片风格,首尾cell需要分别切上圆角和下圆角,cell也几乎是不定高度。所以针对第二种方式封装了适用于frame,约束布局的cell,提供了像系统切圆角的api,并且能指定切割圆角。

原理:view在layoutSubviews方法中的frame确定了,所以在该方法中进行layer的mask设置。通过runtime交换了方法,并且添加了相关的参数。

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class targetClass = [self class];
        SEL originalSelector = @selector(layoutSubviews);
        SEL swizzledSelector = @selector(sy_layoutSubviews);
        [self swizzleMethod:targetClass orgSel:originalSelector swizzSel:swizzledSelector];
    });
}
- (void)sy_layoutSubviews {
    [self sy_layoutSubviews];
    if (self.xk_openClip) {
        if (self.xk_clipType == XKCornerClipTypeNone) {
            self.layer.mask = nil;
        } else {
            UIRectCorner rectCorner = [self getRectCorner];
            if (self.maskLayer == nil) {
                self.maskLayer = [[CAShapeLayer alloc] init];
            }

            UIBezierPath *maskPath;
            maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(self.xk_radius, self.xk_radius)];
            self.maskLayer.frame = self.bounds;
            self.maskLayer.path = maskPath.CGPath;
            self.layer.mask = self.maskLayer;
        }
    }
}


以下是详细使用

   self.view.backgroundColor = [UIColor whiteColor];
    _frameView = [[UILabel alloc] init];
    _frameView.backgroundColor = [UIColor redColor];
    _frameView.text = @"frame";
    _frameView.frame = CGRectMake(20, 100, 200, 100);
    
    _frameView.xk_openClip = YES;
    _frameView.xk_radius = 20;
    _frameView.xk_clipType = XKCornerClipTypeTopRight|XKCornerClipTypeBottomLeft;
    
    [self.view addSubview:_frameView];
    
    _masonryView = [[UILabel alloc] init];
    _masonryView.text = @"autoLayout";
    _masonryView.xk_openClip = YES;
    _masonryView.xk_radius = 20;
    _masonryView.backgroundColor = [UIColor orangeColor];
    _masonryView.xk_clipType = XKCornerClipTypeTopRight|XKCornerClipTypeTopLeft;
    
    [self.view addSubview:_masonryView];
    
    [_masonryView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.frameView.mas_bottom).offset(40);
        make.left.equalTo(self.frameView);
        make.size.mas_equalTo(CGSizeMake(100, 100));
    }];

切圆角实例

2 切圆角场景下加边框或者是加阴影

第一种 对于加边框和加阴影的情况,不过不涉及指定切圆角,那么可以使用
    UIView *aa1 = [[UIView alloc] init];
    [KEY_WINDOW addSubview:aa1];
    aa1.backgroundColor = [UIColor redColor];
    aa1.frame = CGRectMake(100, 300, 100, 50);
  // 圆角
    aa1.layer.cornerRadius = 10;
// 边框
    aa1.layer.borderColor = [UIColor orangeColor].CGColor;
    aa1.layer.borderWidth = 5;
// 阴影
    aa1.layer.shadowColor = [UIColor blackColor].CGColor;
    aa1.layer.shadowOffset = CGSizeMake(2, 2);
    aa1.layer.shadowRadius = 10;
    aa1.layer.shadowOpacity = 0.5;
第二种, 同样使用 CAShaperLayer 搭配 UIBezierPath 路径实现,不同的是不能设置在UIView.layer的mask属性,因为会导致阴影被切掉。使用addSublayer

原理同上交换方法。

- (void)sy_borderlayoutSubviews {
    [self sy_borderlayoutSubviews];
    if (self.xk_openBorder) {
//        if (self.borderStatusChange == NO) return;
        self.borderStatusChange = NO;
        if (self.xk_openBorder == XKBorderTypeNone) {
            [self.subBorderLayer removeFromSuperlayer];
        } else {
            UIRectCorner rectCorner = [self getRectCornerForBorder];
            if (self.subBorderLayer == nil) {
                self.subBorderLayer = [[CAShapeLayer alloc] init];
            }
            UIBezierPath *maskPath;
            maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.width -  self.xk_borderWidth, self.height - self.xk_borderWidth) byRoundingCorners:rectCorner cornerRadii:CGSizeMake(self.xk_borderRadius, self.xk_borderRadius)];
            self.subBorderLayer.frame = CGRectMake(self.xk_borderWidth / 2, self.xk_borderWidth / 2,self.width - self.xk_borderWidth,self.height - self.xk_borderWidth);
            self.subBorderLayer.path = maskPath.CGPath;
            self.subBorderLayer.fillColor = self.xk_borderFillColor.CGColor;
            self.subBorderLayer.strokeColor = self.xk_borderColor.CGColor;
            self.subBorderLayer.lineWidth = self.xk_borderWidth;
            
            if (!self.subBorderLayer.superlayer) {
                [self.layer addSublayer:self.subBorderLayer];
            }
        }
    }
}

使用

 UIView *aa = [[UIView alloc] init];
 [KEY_WINDOW addSubview:aa];
 aa.frame = CGRectMake(20, 300, 100, 50);
 aa.xk_openBorder = YES; // 开启功能
 aa.xk_borderFillColor = [UIColor redColor]; // 视图背景颜色这样设置
 aa.xk_borderType = XKBorderTypeTopLeft; // 指定下方圆角
 aa.xk_borderRadius = 20; // 圆角大小
 aa.xk_borderColor = [UIColor orangeColor]; // 边框颜色
 aa.xk_borderWidth = 2; // 边框宽度
 // 阴影还是系统的方法
 aa.layer.shadowColor = [UIColor blackColor].CGColor;
 aa.layer.shadowOffset = CGSizeMake(2, 2);
 aa.layer.shadowRadius = 10;
 aa.layer.shadowOpacity = 0.5;

效果


以上的方法通过组合基本可以应对所有的情况了。上述两个分类在这里

https://github.com/sy5075391/XKCornerRadius

为了方便使用也可以使用pod安装

Installation

pod 'XKCornerRadius'

Author

Jamesholy, [email protected],https://www.jianshu.com/u/2df38653a8d4

xkcornerradius's People

Stargazers

Emily Anderson avatar Mason Fu avatar jyouli avatar isaac_gang avatar Michael avatar 我就叫土豆 avatar zhangzhihua avatar Daadididooo avatar  avatar 屋檐上的猫 avatar  avatar  avatar 一念丶归途 avatar DwyaneZZZ avatar  avatar  avatar  avatar Sol avatar

Watchers

James Cloos avatar Sol avatar

xkcornerradius's Issues

uibutton 圆角和边框不行

self.btnShopDistace.xk_openBorder = YES; // 开启功能
self.btnShopDistace.xk_borderFillColor = [UIColor redColor]; // 视图背景颜色这样设置
self.btnShopDistace.xk_borderType = XKBorderTypeTopLeft; // 指定下方圆角
self.btnShopDistace.xk_borderRadius = 20; // 圆角大小
self.btnShopDistace.xk_borderColor = [UIColor orangeColor]; // 边框颜色
self.btnShopDistace.xk_borderWidth = 5; // 边框宽度

按钮没有任何效果

开启切圆角,不加边框,加阴影,阴影还是不出现,该怎么设置呢?

作者你好,这里有个问题不解。

self.footView.xk_openBorder = YES; // 开启功能
self.footView.xk_borderFillColor = [UIColor blueColor]; // 视图背景颜色这样设置
self.footView.xk_borderType = XKBorderTypeBottomLeft | XKBorderTypeBottomRight; // 指定下方圆角
self.footView.xk_borderRadius = 10; // 圆角大小
self.footView.xk_borderColor = [UIColor orangeColor]; // 边框颜色
self.footView.xk_borderWidth = 1; // 边框宽度

// 以上,配上下面的阴影方法,是可以有效果的,但是没有圆角。

// self.footView.xk_openClip = true;
// self.footView.xk_clipType = XKCornerClipTypeBottomBoth;
// self.footView.xk_radius = 10;

// 放开以上 3 行的注释后,阴影就无效了。

// 阴影还是系统的方法

self.footView.layer.shadowColor = [UIColor blackColor].CGColor;
self.footView.layer.shadowOffset = CGSizeMake(2, 2);
self.footView.layer.shadowRadius = 10;
self.footView.layer.shadowOpacity = 0.5;

我不需要边框,只要圆角和阴影,我该如何搭配使用呢?
谢谢抽空回答。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.