美文网首页IT好文iOSiOS开发深度好文
iOS 自定义工具---环形菜单

iOS 自定义工具---环形菜单

作者: 小白进城 | 来源:发表于2017-11-22 15:24 被阅读31次

    效果演示

    效果演示

    自定义部分
    1、支持文字、图片
    2、填充色可自定义
    3、文字大小可自定义
    4、多种show动画,并且可自定义动画
    5、圆弧宽度可控


    使用

    self.pieView = [[LLPieView alloc] initWithFrame:CGRectMake(0, 0, pieViewSize.width, pieViewSize.height) andClickBlock:^(NSInteger index) {
        // 点击回调
        NSLog(@"点击了%ld个", index+1);
    }];
    self.pieView.style = LLPieViewRoate_Z;   // 动画风格
    self.pieView.dataArray = @[@"LOLITA",[UIImage imageNamed:@"ss"]]; // 数据组
    [self.pieView show];
    

    设置部分

    /**
     数据数组,文字或者图片
     */
    @property (nonatomic, copy) NSArray *dataArray;
    /**
     填充色,默认为Alpha0.5的紫色
     */
    @property (nonatomic, strong) UIColor *fillColor;
    /**
     半径,最小半径默认为最大半径的一半,最大默认为父视图宽度的一半,当minRadius为0时,样式为圆盘
     */
    @property (nonatomic, assign) CGFloat minRadius, maxRadius;
    /**
     文字大小,默认为13.0
     */
    @property (nonatomic, assign) CGFloat fontSize;
    /**
     出现动画,如果设置了该属性,style则不会生效
     */
    @property (nonatomic, strong) CAAnimation *animation;
    /**
     动画风格
     */
    @property (nonatomic, assign) LLPieViewShowStyle style;
    

    适当使用这些属性时,产生的效果如下

    1、数量、圆环大小、出现的样式

    样式1

    2、圆盘、颜色、出现样式、字体大小

    样式2

    另外,如果你对提供的出现样式不满意,完全可以自定义animation,又或者不想要出现动画,就不设置style


    设计思路

    由于系统的控件正常状态下都是规则的,需要不规则的时候我们通常会去改变控件的Layer层,绘制出我们想要的形状,但是如果用系统的控件可能很难做到上面的演示图的效果,所以不如直接从Layer层下手

    1、重写CAShapeLayer,绘制出我们想要的形状添加到View上

    2、在自定义View中,布局好各个Layer的位置

    3、在触摸事件中,找到被点击的Layer,重新设置颜色并返回索引


    核心代码

    1、绘制不规则图形,已经填充文字和图片

    // 绘制路径
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.centerPoint radius:self.minRadius startAngle:self.startAngle endAngle:self.endAngle clockwise:YES]; // 绘制内弧度
    path = [path bezierPathByReversingPath];    // 反转路径
    [path addArcWithCenter:self.centerPoint radius:self.maxRadius startAngle:self.startAngle endAngle:self.endAngle clockwise:YES]; // 绘制外弧度
    [path closePath];   // 封闭路径
    self.path = path.CGPath;
    self.fillColor = [self.fullColor colorWithAlphaComponent:0.5].CGColor;  // 设置shapeLayer的填充色
    self.lineWidth = 0.5;   //
    self.strokeColor = [UIColor whiteColor].CGColor;    // 设置shapeLayer的描边色
    
    // 为了获取不规则图形中心点而创建的临时路径
    UIBezierPath *pathTmp = [UIBezierPath bezierPathWithArcCenter:self.centerPoint radius:(self.minRadius+self.maxRadius)/2.0 startAngle:self.startAngle endAngle:(self.startAngle+self.endAngle)/2.0 clockwise:YES];
    
    // 绘制文字
    if (self.text) {
        // 获取中心点
        CGSize sizeNew = [self.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:self.fontSize]}];
        CATextLayer *textLayer = [CATextLayer layer];
        textLayer.frame = CGRectMake(pathTmp.currentPoint.x-sizeNew.width/2.0, pathTmp.currentPoint.y-sizeNew.height/2.0, sizeNew.width, sizeNew.height);
        textLayer.string = self.text;
        textLayer.fontSize = self.fontSize;
        textLayer.contentsScale = 3;
        textLayer.alignmentMode = kCAAlignmentCenter;
        textLayer.foregroundColor = [UIColor whiteColor].CGColor;
        [self addSublayer:textLayer];
    }
    // 绘制图像
    if (self.image) {
        CALayer *layer = [CALayer new];
        layer.position = pathTmp.currentPoint;
        layer.bounds = CGRectMake(0, 0, self.image.size.width, self.image.size.height);
        layer.contents = (id)self.image.CGImage;
        [self addSublayer:layer];
    }
    
    // 设置阴影
    self.shadowColor = self.fullColor.CGColor;//shadowColor阴影颜色
    self.shadowOffset = CGSizeMake(2,2);//shadowOffset阴影偏移
    self.shadowOpacity = 1;//阴影透明度,默认0
    

    2、触摸事件的处理

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        CGPoint touchPoint = [[touches anyObject] locationInView:self];
        for (LLShapeLayer *shaperLayer in self.shapeLayerArray) {
            if (CGPathContainsPoint(shaperLayer.path, 0, touchPoint, YES)&&self.clickBlock) {   // 寻找触摸的形状
                [shaperLayer selectedState];    // 设置为选中状态
                self.isSelected = YES;  //
                self.clickIndex = shaperLayer.tag;  // 记录下选择的索引tag
            }
        }
    }
    
    // 触摸结束时回调
    -(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        for (LLShapeLayer *shaperLayer in self.shapeLayerArray) {
            [shaperLayer unSelectedState];  // 恢复为正常状态
        }
        if (self.isSelected&&self.clickBlock) {
            self.clickBlock(self.clickIndex);   // 回调
        }else{
            self.clickBlock(-1);    // 非区域的触摸
        }
        self.isSelected = NO;
    }
    
    // 触摸取消时,考虑到手势问题
    -(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        for (LLShapeLayer *shaperLayer in self.shapeLayerArray) {
            [shaperLayer unSelectedState];  // 恢复为正常状态
        }
        self.isSelected = NO;
    }
    

    Demo地址


    体会

    1、CAShapeLayer和UIView的结合使用,我们可以方便的定义出不规则形状的控件(UIView还是规则的)

    2、使用CGPathContainsPoint方法查找触点是否包含在路径中可以让我们知道哪个形状被触摸

    相关文章

      网友评论

        本文标题:iOS 自定义工具---环形菜单

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