iOS绘制图形实战

本文结构:想看吐槽直接跳到末尾。

  • 前言
  • 正文
  • 结尾扯犊子

前言

最近做了iOS开发。

当一天和尚撞一天钟呗。身心俱疲。贼难受,没看我都不更新博客了么。

iOS的绘制,看了好多帖子,忘了都是哪些帖子了,感谢前辈们。不贴看过的链接了,因为看得太多了。

要是片的话,看过多少我都能熟记于心。那手法,那。。。不说了。

结尾扯点犊子,唠点嗑,也就行了。

正文

需求

最近接到这样一个需求。需求中有一个地方是这样的:
需求的图片这个地方没有给背景图,看了一下基本都是直线,那就自己画一个吧,iOS还不会自定义view呢,正好熟悉一下绘制。

发现他们是排着队,一个一个插着下一个人的后面吗,这样就考虑计算一下上一个图形的尖尖插了自己的pp,所带来的影响,再来画下一个图形了。

实现思路

刚开始就想着自己绘制,那就需要新建一个继承自UIview的控件,然后开始画线,然后再绘制文字。

后来动起手来发现,文字部分不如直接用UILabel,来的快,他的sizeToFit也方便我们测量他的宽高。

于是思路变成了这样:
定义一个数组变量,由外部传入,为需要的文本数组,如图中的”好友如\n何助力“、”打开分享链接“等。遍历此数组,实例化UIlabel,根据UIlabel的宽高计算出要画的线的各个坐标。

定义两个颜色,开始颜色和结束颜色,外部传入此控件中。获取颜色的rgb值,遍历数组时,设置对应的颜色。

如图所示:画6个点每一个图形都需要计算6个点,画5条线,需要特殊处理的地方就是第一个图形,他在计算的时候,不用受上一个图形的影响,只需要计算5个点,因为他不像其他的图形,有上一个的尖尖插着自己的pp。

最后一个图形,可以不画这个尖尖,也可以画出来,然后利用setMasksToBounds。

有了思路就开始做了。

代码

我的代码为什么是红色的
.h文件:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface BRStepView : UIView
@property(nonatomic,strong)NSArray *strData;
@property(nonatomic,strong)NSArray *colorArray;
@property(nonatomic,strong)UIColor *startColor;
@property(nonatomic,strong)UIColor *endColor;
@end

NS_ASSUME_NONNULL_END

.m文件:
CommonUtil 是个工具类,用它调用相关方法的作用大家可以顾名思义。

#import "BRStepView.h"
#import "CommonUtil.h"

@implementation BRStepView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
//初始化
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor colorWithRed:0.87 green:0.87 blue:0.87 alpha:1]];
    }
    return self;
}
//绘制的主要方法
- (void)drawRect:(CGRect)rect
{
    if (!self.strData) {
    //self.strData这个就是数据源,没有数据源,不进行绘制。
        return;
    }
    //定义起始、终止颜色的rgb值
    CGFloat red = 0.0;
    CGFloat green = 0.0;
    CGFloat blue = 0.0;
    CGFloat alpha = 0.0;
    CGFloat endRed = 0.0;
    CGFloat endGreen = 0.0;
    CGFloat endBlue = 0.0;
    CGFloat endAlpha = 0.0;
    if (self.startColor && self.endColor) {
    	//没设置就是0,也就是默认黑色
    	//获取rgb值:
        [self.startColor getRed:&red green:&green blue:&blue alpha:&alpha];
        [self.endColor getRed:&endRed green:&endGreen blue:&endBlue alpha:&endAlpha];
    }
    CGContextRef con = UIGraphicsGetCurrentContext();//获取绘制的上下文,每一个绘制方法都需要此参数
    CGContextSetLineWidth(con, 1.0);//设置绘制的线宽
    CGFloat pointX = 0;//label的x
    CGFloat pointTopX = 0;//顶部的点
    NSInteger count = self.strData.count;
    for (int i = 0; i < self.strData.count; i++) {
    //每个颜色的值的算法:因为是要进行平均的变色,来达到循序渐进的效果。所以用起始的rgb值-终止的gbr值。所得值除以总数,算出每两个图形之间的颜色差值,根据是第几个就乘以几。然后再加上起始颜色的rgb的值,就是当前要设置的颜色。注意,alpha不用变?。
        UIColor *color = [UIColor colorWithRed:(fabs(red-endRed)/count*(i+1) + MIN(red, endRed)) green:(fabs(green-endGreen)/count*(i+1) + MIN(green,endGreen)) blue:(fabs(blue-endBlue)/count*(i+1) + MIN(blue, endBlue)) alpha:1];
        [color set];
        UILabel *label = [[UILabel alloc]init];
        [label setFont:[CommonUtil getFontWithFontName:@"PingFangSC-Regular" andFontSize:12]];
        [label setTextColor:[CommonUtil colorWithHexString:@"#333333"]];
        NSString *text = self.strData[i];
        [label setText:text];
        [label setNumberOfLines:0];
        [label sizeToFit];//下面会利用label的frame来计算
        [self addSubview:label];
        CGContextSetFillColorWithColor(con, color.CGColor);//线颜色
        CGContextMoveToPoint(con, pointTopX, 0);//起始点
        if (i == 0) {//第一个图形,不用计算上一个图形的尖尖
            CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5, 0);//label左测留白10右侧留白5,留白就是传说中的margin
            if (i != self.strData.count - 1)//不是最后一个
            {
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15, CGRectGetHeight(self.frame)/2);
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5, CGRectGetHeight(self.frame));
            }
            else
            {//最后一个不画这个尖,直接画到头
                CGContextAddLineToPoint(con, CGRectGetWidth(self.frame) + 10 + 5, CGRectGetHeight(self.frame));
            }
            CGContextAddLineToPoint(con, pointTopX, CGRectGetHeight(self.frame));
        }else{//非第一个图形,需要计算上一个图形的尖尖,因为他插了自己pp。
            if (i != self.strData.count - 1)
            {
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15, 0);//label再加前一个尖
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15 + 15, CGRectGetHeight(self.frame)/2);
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15, CGRectGetHeight(self.frame));
            }
            else
            {//最后一个不画这个尖,直接画到头
                CGContextAddLineToPoint(con, CGRectGetWidth(self.frame), 0);//label再加前一个尖
                CGContextAddLineToPoint(con, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
            }
            CGContextAddLineToPoint(con, pointTopX, CGRectGetHeight(self.frame));
            CGContextAddLineToPoint(con, pointTopX + 15, CGRectGetHeight(self.frame)/2);
        }
        CGContextFillPath(con);//封闭,关门放狗
        //开始计算下一个图形的相关位置
        if (i != 0) {//第一个图形,不用计算上一个图形的尖尖
            pointTopX = pointTopX + CGRectGetWidth(label.frame) + 10 + 5 +15;//label左10右5 尖15
        }else{//非第一个图形,需要计算上一个图形的尖尖,因为他插了自己pp。
            pointTopX = pointTopX + CGRectGetWidth(label.frame) + 10 + 5;//label左10右5
        }
        pointX += 10;//左侧10
        //放置奇兵
        label.center = CGPointMake(pointX + CGRectGetWidth(label.frame)/2, CGRectGetHeight(self.frame)/2);
        pointX += CGRectGetWidth(label.frame) +5;
        pointX += 15;
    }
}
@end

代码写的垃圾,刷几天LeetCode吧。今天看到一个LeetCode的快速刷题的插件,想试试。真好。

扯犊子

在这扯:
https://blog.csdn.net/u014540814/article/details/87855504

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值