谈谈iOS标尺的实现

挺长时间没有撰写技术文章了,今天给大家介绍的虽然不是常用到的标尺demo,但是从这个demo中我们可以学习到别人的绘图是怎么实现的。。。

和以往一样,首先我要强调的是思路。

1.我们要考虑标尺中长短线段不一的实现,还有数字的显示.

先上代码:

(.h)

#import

typedefNS_ENUM(NSUInteger, RulerDirection) {

    RulerDirectionHorizontal,  //横向

    RulerDirectionVertical,    //纵向

};

typedefNS_ENUM(NSUInteger, RulerFace) {

    RulerFace_up_left,//横向朝上,纵向朝左

    RulerFace_down_right,//横向朝下,纵向朝右

};

typedef struct LineColor {


    CGFloat R;

    CGFloat G;

    CGFloat B;


} CustomeColor;

//c 函数构造结构体

CustomeColorcustomColorMake(CGFloatR,CGFloatG,CGFloatB);

typedef void(^Handler)(void);

@interfaceRullerView :UIView

/**

 长刻度的长度 默认 fit(24)

 */

@property (nonatomic,assign) float h_height;

/**

 短刻度的长度 默认 fit(12)

 */

@property (nonatomic,assign) float m_height;

/**

 标尺显示的最小值,默认 0

 */

@property (nonatomic,assign) NSInteger lockMin;

/**

 标尺显示的最大值,默认 360

 */

@property (nonatomic,assign) NSInteger lockMax;

/**

 一个刻度代表的值是多少,默认 1

 */

@property (nonatomic,assign) NSInteger unitValue;

/**

 默认横向滚动

 */

@property (nonatomic,assign) RulerDirection rulerDirection;

/**

 默认朝上,朝左

 */

@property (nonatomic,assign) RulerFace rulerFace;

/**

 是否显示刻度值

 */

@property (nonatomic,assign)BOOL isShowRulerValue;

/**

 标尺数字颜色

 */

@property (nonatomic,strong) UIColor *txtColor;//标尺上数字的颜色

/**

 标尺线的颜色

 */

@property (nonatomic) CustomeColor lineColor;//标尺线的颜色

/**

 指针位置,默认居中

 */

@property (nonatomic,assign) CGRect pointerFrame;

/**

 标尺视图的背景颜色 默认白色

 */

@property(nonatomic,strong)UIColor*rulerBackgroundColor;

- (void)drawRuler:(Handler)block;

#pragma 自定义的宏

//屏幕尺寸

#define cy_ScreenW [UIScreen mainScreen].bounds.size.width

#define cy_ScreenH [UIScreen mainScreen].bounds.size.height

//视图尺寸

#define cy_selfWidth self.bounds.size.width

#define cy_selfHeight self.bounds.size.height

//px宏除2

#define cy_px(value) (value)/2.0

//按宽度适配

#define cy_fit(value) (cy_px(value))*cy_ScreenW/375.0

// RGB颜色转换(16进制->10进制)

#define UIColorFromRGB(rgbValue)\

\

[UIColor colorWithRed:((float)((rgbValue &0xFF0000) >>16))/255.0\

green:((float)((rgbValue &0xFF00) >>8))/255.0\

blue:((float)(rgbValue &0xFF))/255.0\

alpha:1.0]

@end

(.m)

#import "RullerView.h"

@interface RullerView()

{

    float_unitPX;//标尺单位长度

    float_coarseness;//标尺粗


    float_num_height;//数字高度

    float_num_top;//数字头部位置


    float_mark_bottom;//刻度尾部位置

    float_short_mark_top;//短刻度头部位置

    float_long_mark_top;//长刻度头部位置

}

@end

@implementation RullerView

- (instancetype)initWithFrame:(CGRect)frame {


    self= [superinitWithFrame:frame];

    if(self) {


    }

    return self;

}

- (void)start {

    self.backgroundColor = _rulerBackgroundColor?_rulerBackgroundColor:[UIColor whiteColor];

    _unitPX=cy_fit(14);

    _coarseness = cy_fit(1);

    _num_height = cy_fit(24);

    _txtColor = UIColorFromRGB(0xDDDDDD);

    _lineColor = customColorMake(221, 221, 221);


    if (_rulerDirection == RulerDirectionHorizontal) {


        if (_rulerFace == RulerFace_up_left) {


            _mark_bottom=cy_selfHeight/2.0;

            _short_mark_top = _mark_bottom-_m_height;

            _long_mark_top = _mark_bottom-_h_height;

            _num_top=_mark_bottom+cy_fit(10);

//            _long_mark_top-_num_height-cy_fit(10);


        }else if (_rulerFace == RulerFace_down_right) {


            _mark_bottom=cy_selfHeight/2.0;

            _short_mark_top = _mark_bottom+_m_height;

            _long_mark_top = _mark_bottom+_h_height;

            _num_top = _long_mark_top+_num_height-cy_fit(10);


        }else{

            NSAssert(NO,@"error");

        }


    }else if (_rulerDirection == RulerDirectionVertical) {


        if (_rulerFace == RulerFace_up_left) {


            _mark_bottom=cy_selfWidth/2.0;

            _short_mark_top = _mark_bottom-_m_height;

            _long_mark_top = _mark_bottom-_h_height;

            _num_top = _long_mark_top-_unitPX*8+cy_fit(10);


        }else if (_rulerFace == RulerFace_down_right) {


            _mark_bottom=cy_selfWidth/2.0;

            _short_mark_top = _mark_bottom+_m_height;

            _long_mark_top = _mark_bottom+_h_height;

            _num_top = _long_mark_top-cy_fit(10);


        }else{

            NSAssert(NO,@"error");

        }


    }else{

        NSAssert(NO,@"error");

    }

}

- (void)drawRuler:(Handler)block {

    [selfstart];

    if(block) {

        block();

    }

    [self setNeedsDisplay];

}

//绘制方法

- (void)drawRect:(CGRect)rect {

    [superdrawRect:rect];


    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetRGBStrokeColor(context,self.lineColor.R,self.lineColor.G,self.lineColor.B,1.0);

    CGContextSetLineWidth(context, _coarseness);

    //画轴

    CGPointaPoints[2];//X轴

    if (_rulerDirection == RulerDirectionHorizontal) {


        aPoints[0] =CGPointMake(0,_mark_bottom);//起始点

        aPoints[1] =CGPointMake(cy_selfWidth,_mark_bottom);//终点


    }else if (_rulerDirection == RulerDirectionVertical) {


        aPoints[0] =CGPointMake(_mark_bottom,0);//起始点

        aPoints[1] =CGPointMake(_mark_bottom,cy_selfHeight);//终点


    }else{

        NSAssert(NO,@"error");

    }

    CGContextAddLines(context, aPoints,2);//添加线

    CGContextDrawPath(context, kCGPathStroke); //根据坐标绘制路径


    //画刻度

    for (NSInteger i=_lockMin/_unitValue; i<(_lockMax/_unitValue+1); i++) {

        CGContextSetRGBStrokeColor(context,self.lineColor.R,self.lineColor.G,self.lineColor.B,1.0);

        CGContextSetLineWidth(context, _coarseness);

        CGPointaPoints[2];//X轴

        if (_rulerDirection == RulerDirectionHorizontal) {


            aPoints[0] =CGPointMake(_pointerFrame.origin.x+_pointerFrame.size.width/2.0+_unitPX*i, i%10==0?_long_mark_top:_short_mark_top);//起始点

            aPoints[1] =CGPointMake(_pointerFrame.origin.x+_pointerFrame.size.width/2.0+_unitPX*i, _mark_bottom);//终点


        }else if (_rulerDirection == RulerDirectionVertical) {


            aPoints[0] =CGPointMake(i%10==0?_long_mark_top:_short_mark_top,_pointerFrame.origin.y+_pointerFrame.size.height/2.0+_unitPX*i);//起始点

            aPoints[1] =CGPointMake(_mark_bottom,_pointerFrame.origin.y+_pointerFrame.size.height/2.0+_unitPX*i);//终点


        }else{

            NSAssert(NO,@"error");

        }


        CGContextAddLines(context, aPoints,2);//添加线

        CGContextDrawPath(context, kCGPathStroke); //根据坐标绘制路径


        if(_isShowRulerValue&& i%10==0) {

            NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];

            textStyle.lineBreakMode = NSLineBreakByWordWrapping;

            textStyle.alignment = NSTextAlignmentCenter;

            UIFont  *font = [UIFont systemFontOfSize:_num_height];

            NSDictionary *attributes = @{NSForegroundColorAttributeName:self.txtColor,NSFontAttributeName:font, NSParagraphStyleAttributeName:textStyle};

            if (_rulerDirection == RulerDirectionHorizontal) {


                [@(i*_unitValue).stringValue drawInRect:CGRectMake(_pointerFrame.origin.x+_pointerFrame.size.width/2.0+_unitPX*(i-4), _num_top, _unitPX*8, _num_height) withAttributes:attributes];


            }else if (_rulerDirection == RulerDirectionVertical) {


                [@(i*_unitValue).stringValue drawInRect:CGRectMake(_num_top, _pointerFrame.origin.y+_pointerFrame.size.height/2.0+_unitPX*(i-1), _unitPX*8, _num_height) withAttributes:attributes];


            }else{

                NSAssert(NO,@"error");

            }


        }

    }

}

//c 函数构造结构体

CustomeColorcustomColorMake(CGFloatR,CGFloatG,CGFloatB) {


    CustomeColorl;l.R= R/255.0;l.G= G/255.0;l.B= B/255.0;returnl;

}

@end

这里面着重强调的两个点:一个是自定义标尺绘图视图类要暴露一个绘图回调block给外面。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351