美文网首页
iOS 圆角'几'字形按钮

iOS 圆角'几'字形按钮

作者: 沉船无数 | 来源:发表于2023-09-18 16:34 被阅读0次

前言

新项目UI很喜欢这种类型的按钮,还设计了动画,只能绘制,问了一圈,没有现成的,只能自己手搓一个,话不多说,先看效果图。


效果图1 效果图2
3.jpg 4.jpg

准备工作

1、会贝塞尔曲线,能画圆弧和直线;
2、理解奇偶、非零填充填充规则;
项目中用的是JXCategoryView,因此,本次封装的indicatorView继承JXCategoryIndicatorComponentView。
下面直接上源码。

代码

//
//  WMSpaceIndicatorView.h
//  demo
//
//  Created by jing on 2023/9/4.
//  Copyright © 2023 jing. All rights reserved.
//

#import <JXCategoryView/JXCategoryView.h>

NS_ASSUME_NONNULL_BEGIN

@interface WMSpaceIndicatorView : JXCategoryIndicatorComponentView

///是否显示底部指示器
@property (nonatomic, assign) BOOL isShowBottomIndicator;

@property (nonatomic, weak) JXCategoryTitleView *categoryView;

@end

NS_ASSUME_NONNULL_END

//
//  WMSpaceIndicatorView.m
//  demo
//
//  Created by jing on 2023/9/4.
//  Copyright © 2023 jing. All rights reserved.
//

#import "WMSpaceIndicatorView.h"

@interface WMSpaceIndicatorView ()

@property (nonatomic, strong) CAShapeLayer *pathLayer;
@property (nonatomic, strong) CALayer *indicatorLayer;
@property (nonatomic, assign) NSInteger selectIndex;

@end

static CGFloat const radius = 12;
@implementation WMSpaceIndicatorView

- (instancetype)init {
    self = [super init];
    if (self) {
        self.isShowBottomIndicator = YES;
    }
    return self;
}


- (void)drawLayerPath {
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, self.height)];
    
    if (self.selectIndex == 0) {
        [path addLineToPoint:CGPointMake(0, radius)];
        [path addArcWithCenter:CGPointMake(radius, radius) radius:radius startAngle:M_PI endAngle:M_PI * 3 / 2 clockwise:YES];
        
        [path moveToPoint:CGPointMake(radius, 0)];
        [path addLineToPoint:CGPointMake(self.width - radius * 2, 0)];
        
        [path addArcWithCenter:CGPointMake(self.width - radius * 2, radius) radius:radius startAngle:M_PI * 3 / 2 endAngle:M_PI * 2 clockwise:YES];
        
        [path moveToPoint:CGPointMake(self.width - radius, radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];
        
        [path moveToPoint:CGPointMake(self.width, self.height)];
        [path addArcWithCenter:CGPointMake(self.width, self.height - radius) radius:radius startAngle:M_PI * 0.5 endAngle:M_PI clockwise:YES];
        
        [path moveToPoint:CGPointMake(0, self.height)];
        [path addLineToPoint:CGPointMake(radius, 0)];
        [path addLineToPoint:CGPointMake(self.width - radius, radius)];

        [path moveToPoint:CGPointMake(0, self.height)];
        [path addLineToPoint:CGPointMake(self.width - radius, radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];

        [path moveToPoint:CGPointMake(0, self.height)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width, self.height)];
    } else if (self.selectIndex == self.categoryView.titles.count - 1) {
        [path addArcWithCenter:CGPointMake(0, self.height - radius) radius:radius startAngle:M_PI * 2 endAngle:M_PI * 0.5 clockwise:YES];
        [path moveToPoint:CGPointMake(0, self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height - radius)];
        
        [path moveToPoint:CGPointMake(radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(radius, radius)];
        
        [path addArcWithCenter:CGPointMake(radius * 2, radius) radius:radius startAngle:M_PI endAngle:M_PI * 3 / 2 clockwise:YES];
        
        [path moveToPoint:CGPointMake(radius * 2, 0)];
        [path addLineToPoint:CGPointMake(self.width - radius, 0)];
        
        [path addArcWithCenter:CGPointMake(self.width - radius, radius) radius:radius startAngle:M_PI * 3 / 2 endAngle:M_PI * 2 clockwise:YES];
        
        
        [path moveToPoint:CGPointMake(radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(radius * 2, 0)];
        [path addLineToPoint:CGPointMake(self.width, radius)];

        [path moveToPoint:CGPointMake(radius , self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width, radius)];
        [path addLineToPoint:CGPointMake(self.width, self.height - radius)];

        [path moveToPoint:CGPointMake(radius , self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width, self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width, self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height)];
    } else {
        [path addArcWithCenter:CGPointMake(0, self.height - radius) radius:radius startAngle:M_PI * 2 endAngle:M_PI * 0.5 clockwise:YES];
        [path moveToPoint:CGPointMake(0, self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height - radius)];
        
        [path moveToPoint:CGPointMake(radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(radius, radius)];
        
        [path addArcWithCenter:CGPointMake(radius * 2, radius) radius:radius startAngle:M_PI endAngle:M_PI * 3 / 2 clockwise:YES];
        
        [path moveToPoint:CGPointMake(radius * 2, 0)];
        [path addLineToPoint:CGPointMake(self.width - radius * 2, 0)];
        
        [path addArcWithCenter:CGPointMake(self.width - radius * 2, radius) radius:radius startAngle:M_PI * 3 / 2 endAngle:M_PI * 2 clockwise:YES];
        
        [path moveToPoint:CGPointMake(self.width - radius, radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];
        
        [path moveToPoint:CGPointMake(self.width, self.height)];
        [path addArcWithCenter:CGPointMake(self.width, self.height - radius) radius:radius startAngle:M_PI * 0.5 endAngle:M_PI clockwise:YES];
        
        [path moveToPoint:CGPointMake(self.width, self.height)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];
        
        [path moveToPoint:CGPointMake(radius * 2, 0)];
        [path addLineToPoint:CGPointMake(radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, radius)];

        [path moveToPoint:CGPointMake(radius , self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];
        
        [path moveToPoint:CGPointMake(radius , self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height - radius)];
        [path addLineToPoint:CGPointMake(self.width - radius, self.height)];
        [path addLineToPoint:CGPointMake(radius, self.height)];
    }
    
    [self.pathLayer removeFromSuperlayer];
    self.pathLayer = nil;
    
    self.pathLayer = CAShapeLayer.new;
    self.pathLayer.borderWidth = 0.f;
    self.pathLayer.fillColor = UIColor.whiteColor.CGColor;
    self.pathLayer.strokeColor = UIColor.clearColor.CGColor;
    self.pathLayer.fillRule = kCAFillRuleEvenOdd;
    [self.layer insertSublayer:self.pathLayer atIndex:0];
    self.pathLayer.path = path.CGPath;
    
    if (self.isShowBottomIndicator) [self createIndicatorLayerPath];
}


- (void)createIndicatorLayerPath {
    [self.indicatorLayer removeFromSuperlayer];
    self.indicatorLayer = nil;
    self.indicatorLayer = CALayer.new;
    self.indicatorLayer.frame = CGRectMake(self.width * 0.5 - 11, self.height - 9, 22, 7);
    [self.layer addSublayer:self.indicatorLayer];
    
    //6 mid:11
    UIBezierPath *linePath = [UIBezierPath bezierPath];
    linePath.lineCapStyle = kCGLineCapRound;
    linePath.lineJoinStyle = kCGLineJoinRound;
    [linePath moveToPoint:CGPointMake(0, self.indicatorLayer.frame.size.height - 1)];
    [linePath addLineToPoint:CGPointMake(8, self.indicatorLayer.frame.size.height - 1)];
    [linePath addLineToPoint:CGPointMake(11, 0)];
    [linePath addLineToPoint:CGPointMake(14, self.indicatorLayer.frame.size.height - 1)];
    [linePath addLineToPoint:CGPointMake(22, self.indicatorLayer.frame.size.height - 1)];
    
    CAShapeLayer *lineLayer = [CAShapeLayer new];
    lineLayer.path = linePath.CGPath;
    lineLayer.lineWidth = 1.0f;
    lineLayer.strokeColor = [UIColor colorWithHexString:@"#247CFC" alpha:0.3].CGColor;
    lineLayer.fillColor = UIColor.clearColor.CGColor;
    [self.indicatorLayer addSublayer:lineLayer];
    
    UIBezierPath *trianglePath = [UIBezierPath bezierPath];
    [trianglePath moveToPoint:CGPointMake(9, self.indicatorLayer.frame.size.height)];
    [trianglePath addLineToPoint:CGPointMake(11, 3)];
    [trianglePath addLineToPoint:CGPointMake(13, self.indicatorLayer.frame.size.height)];
    [trianglePath addLineToPoint:CGPointMake(9, self.indicatorLayer.frame.size.height)];
    
    CAShapeLayer *triangleLayer = CAShapeLayer.new;
    triangleLayer.path = trianglePath.CGPath;
    triangleLayer.lineWidth = 1.0f;
    triangleLayer.fillColor = [UIColor colorWithHexString:@"#247CFC" alpha:1].CGColor;
    [self.indicatorLayer addSublayer:triangleLayer];
}


- (CGRect)getIndicatorFrameWithIndex:(NSInteger)selectedIndex {
    self.selectIndex = selectedIndex;
    CGRect selectedFrame = [self.categoryView getTargetCellFrame:selectedIndex];
    NSString *title = self.categoryView.titles[selectedIndex];
    CGFloat textW = [self getWidthBaseOnHeight:22 Font:[UIFont boldSystemFontOfSize:16] text:title] + 20 + radius * 4;
    CGFloat leftW = radius;
    CGFloat rightW = radius * 3;
    CGRect indicatorFrame = CGRectZero;
    CGFloat totoalW = 0;
    if (selectedIndex == 0) {
        totoalW = leftW + textW + rightW ;
        indicatorFrame = CGRectMake(0, 0, totoalW, selectedFrame.size.height);
    } else if (selectedIndex == self.categoryView.titles.count - 1) {
        totoalW = leftW + textW + rightW;
        indicatorFrame = CGRectMake(self.categoryView.collectionView.contentSize.width - totoalW, 0, totoalW, selectedFrame.size.height);
    } else {
        rightW = leftW = radius * 2;
        totoalW = leftW + textW + rightW;
        CGFloat x = CGRectGetMidX(selectedFrame) - totoalW / 2;
        indicatorFrame = CGRectMake(x, 0, totoalW, selectedFrame.size.height);
    }
    
    return indicatorFrame;
}


- (CGFloat)getWidthBaseOnHeight:(CGFloat)height Font:(UIFont *)stringFont text:(NSString *)str {
    CGSize textSize = CGSizeMake(CGFLOAT_MAX, height);
    CGRect calSize = [str boundingRectWithSize:textSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: stringFont} context:nil];
    return ceil(calSize.size.width);
}


#pragma mark - JXCategoryIndicatorProtocol

- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model {
    self.frame = [self getIndicatorFrameWithIndex:model.selectedIndex];
    if (self.selectIndex == 0) {
        [self drawLayerPath];
    }
}


- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model {
    CGRect toFrame = [self getIndicatorFrameWithIndex:model.selectedIndex];
    if (self.isScrollEnabled) {
        [UIView animateWithDuration:self.scrollAnimationDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
            self.frame = toFrame;
            self.pathLayer.frame = toFrame;
            [self drawLayerPath];
        } completion:^(BOOL finished) {
        }];
    } else {
        self.frame = toFrame;
        self.pathLayer.frame = toFrame;
        [self drawLayerPath];
    }
}

@end

暂时先这样,以后有时间再优化吧。

相关文章

  • iOS Button圆角,阴影,渐变色

    iOS给按钮增加阴影,圆角,渐变色。

  • Flutter笔记 - Switch/MaterialButto

    iOS样式的Switch按钮 按钮的简单应用MaterialButton,加圆角、边框、去阴影等 全局主题 - 在...

  • iOS 圆角优化-上

    圆角是iOS系统中常见的视觉样式,从系统图标到导航栏按钮,圆角无处不在。因为圆角是符合人类视觉安全体验的,圆角让人...

  • iOS 圆角优化-下

    圆角是iOS系统中常见的视觉样式,从系统图标到导航栏按钮,圆角无处不在。因为圆角是符合人类视觉安全体验的,圆角让人...

  • Bootstrap-按钮、图片、辅助类、响应式实用工具

    一、按钮.btn 的元素都会继承圆角灰色按钮的默认外观;.btn-default 默认/标准按钮 圆角白色外观;....

  • 圆角风格Button

    圆角风格的按钮实际山就是一个带有圆角的背景,可以通过设置按钮的背景图片来实现 画一个圆角的矩形 设置按钮的背景为圆...

  • 按钮圆角

    //设置为圆角 [<#name#>.layer setMasksToBounds:YES]; //设置圆角弧度 [...

  • day11-购物车02-圆角按钮处理

    购物车01-搭建基本骨架 是什么? 思路: 怎么将普通按钮,改变为有圆角的按钮?直接叫美工,做圆角按钮图片。自定义...

  • iOS 绘制圆角

    级别: ★☆☆☆☆标签:「iOS切圆角」「layer圆角」「CAShapeLayer圆角」作者: Xs·H审校: ...

  • iOS高效添加圆角效果实战讲解

    iOS高效添加圆角效果实战讲解 iOS高效添加圆角效果实战讲解

网友评论

      本文标题:iOS 圆角'几'字形按钮

      本文链接:https://www.haomeiwen.com/subject/ocpgvdtx.html