谈谈iOS标尺的实现

2018-08-31  本文已影响91人  大神风格化X

挺长时间没有撰写技术文章了,今天给大家介绍的虽然不是常用到的标尺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给外面。

上一篇下一篇

猜你喜欢

热点阅读