可以自定义的直方图

直方图主要用在数据图表,作为对比数据,用柱体高度的高低,形象直观地表达出来,往往与折线图配合使用,而折线图便于从众多数据,在时间长度上看出,观察对象发展的趋势。下面直接上代码,

1. 创建直方图FangBarChart类。在FangBarChart.h中

#import "FangBarChart.h"

//#import "BGSDashLine.h"

#import "UILabel+verticalPlaceExtention.h"

#define HEXCOLOR(hexString) [UIColor colorWithRed:((float)((hexString & 0xFF0000) >> 16))/255.0 green:((float)((hexString & 0xFF00) >> 8))/255.0 blue:((float)(hexString & 0xFF))/255.0 alpha:1.0]

#define barWidth (BigBlank-xFirstSpace-xEndSpace)/(legendTextArray.count *2-1)

#define LeftSpaceY 40

#define BottomSpaceX 10

#define BigBlank (self.bounds.size.width-LeftSpaceY-BottomSpaceX)/roomNameArray.count

#define BigKeduHeight 5

#define bigBlankY (orginPoint.y-20)/(bxDataArrayY.count)//y轴每个大刻度实际值

#define LegendSpaceHorital 10

//#define legendLabelHeight 15

//#define YKedubxValue  maxYValue/(bxDataArrayY.count+1) //y轴每个大刻度表现值

@interface FangBarChart () {

NSMutableArray *bxDataArrayY;//客户对该户型房源关注度数据的显示数据数组 y轴方向

NSMutableArray *rawDataArrayY;//客户对该户型房源关注度数据的绘画数据数组  y轴方向

NSMutableArray *bxDataArrayX;//客户对该户型房源关注度数据的显示数据数组  x轴方向

NSMutableArray *rawDataArrayX;//客户对该户型房源关注度数据的绘画数据数组  x轴方向

NSMutableArray *fbBxDataArrayY;//经纪人对该户型房源发布数据的显示数据数组 y轴方向

NSMutableArray *myFbBXDatayArrayY;//您发布该户型房源的情况

NSMutableArray *roomNameArray;//居室名字数组

BOOL showRectBoundary;//是否显示当前视图的矩形边界

CGFloat YKedubxValue;//纵轴每个刻度值

CGPoint orginPoint;//原点

CGFloat xFirstSpace;//x轴上单个大刻度内的直方图前面空余宽度

CGFloat xEndSpace;//x轴上单个大刻度内的直方图最后面空余宽度

CGFloat legendVSpace; //图例间的行间距

NSMutableArray *legendTextArray;//图例提示文字数组

UIFont * xLabelFont;//横轴直方图label字体

UIColor *xLabelTextColor;//横轴直方图label字体颜色

UIFont *legendFont;//图例文本字体

CGFloat legendLabelHeight;//图例文本高度

LegendViewType legendPlaceType;//图例放置方式

NSMutableArray *colorArray;//图例和直方图背景颜色数组,类型为uicolor

BOOL isShowYAsix; //

BOOL isShowXkedu;//是否显示x轴刻度

BOOL isShowOrginXLabel;//是否显示坐标原点x方向texLabel

CGFloat  maxYValue;//y轴 bar 数组展示数据最大值

CGFloat perPartbxValue;//y轴每个大刻度表现值

NSNumber *zhiDingMaxValue;//由接口指定的最大直方图值 //y轴

XLabelPlaceType  xtextType; 

}

@property (nonatomic,strong)UIView *downLegendView;//图例view

@property (nonatomic,strong)UIView *bgLineView;//barchart 背景横线

property (nonatomic,strong)FangBarChartDataModel *dataModel;//设置直方图相关自定义数据model

/**

直方图利用数据model自定义方法

@param frame chartview 的frame

@param temModel 数据源model

@return 整个直方图

*/

- (instancetype)initWithFrame:(CGRect)frame  withDataModel:(FangBarChartDataModel *)temModel;

/**

barchart 的刷新方法

@param nModel 提供新数据源的newmode

*/

- (void)refreshBarViewWithNewModel:(FangBarChartDataModel *)nModel;

@end

2.  在FangBarChart.m中,主要 实现直方图的初始化方法,以及刷新方法,初始化方法主要用于第一次初始设置一些数据,对直方图,对每一组柱体 初始宽度设置。具体看代码

@implementation FangBarChart

//先调用这个

- (instancetype)initWithFrame:(CGRect)frame  withDataModel:(FangBarChartDataModel *)temModel{

if (self=[super initWithFrame:frame]) {

//custom code here

//初始化客户对该户型房源关注度数据的显示数据数组

//        [self numberToStringWithNumber:[NSNumber numberWithInt:1]];

self.dataModel=[[FangBarChartDataModel alloc]init];

if (temModel) {

self.dataModel=temModel;

}

self.dataModel.xtextType=XLabelPlaceTypeVertical;

[self getDataWithDataModel:self.dataModel];

if (legendTextArray>0) {

//创建图例view

[self createLegendView];

}

}

return self;

}

(1)在这个方法中用到,数据源model,这个model 的属性,作为自定义直方图的各个参数。后面会讲到这个FangBarChartDataModel。getDataWithDataModel:self.dataMode 中主要用self.dataModel 的属性,初始化直方图用到的各个数据。为了演示直方图,我们使用了一些默认数据 。

- (void)getDataWithDataModel:(FangBarChartDataModel *)dataModel {

if (dataModel.xtextType==XLabelPlaceHorizital) {

xtextType=XLabelPlaceHorizital;

}else{

xtextType=XLabelPlaceTypeVertical;

}

CGFloat orginPointY=self.bounds.size.height-CGRectGetHeight(self.downLegendView.frame)-40;

orginPoint=CGPointMake(LeftSpaceY, orginPointY);

dataModel.xFirstSpace?xFirstSpace=dataModel.xFirstSpace:30;

dataModel.xEndSpace?xEndSpace=dataModel.xEndSpace:0;

NSLog(@"xfirst:%f,xend:%f",xFirstSpace,xEndSpace);

dataModel.legendVSpace?legendVSpace=dataModel.legendVSpace:7;

if (dataModel.fbBxDataArrayY) {

fbBxDataArrayY=dataModel.fbBxDataArrayY;

}else{

fbBxDataArrayY=[NSMutableArray arrayWithObjects:[NSNumber numberWithFloat:21.2],[NSNumber numberWithFloat:21.2],[NSNumber numberWithFloat:21.2],[NSNumber numberWithFloat:21.2],[NSNumber numberWithFloat:21.2],[NSNumber numberWithFloat:17], nil];

}

if (dataModel.myFbBXDatayArrayY) {

myFbBXDatayArrayY= dataModel.myFbBXDatayArrayY;

}else{

myFbBXDatayArrayY=[NSMutableArray arrayWithObjects:[NSNumber numberWithFloat:10],[NSNumber numberWithFloat:18],[NSNumber numberWithFloat:10],[NSNumber numberWithFloat:3],[NSNumber numberWithFloat:10],[NSNumber numberWithFloat:10] ,nil];//ceshi data

}

if (dataModel.roomNameArray) {

roomNameArray=dataModel.roomNameArray;

}else{

roomNameArray=[NSMutableArray arrayWithObjects:@"4:00",@"8:00",@"12:00",@"16:00",@"20:00",@"23:00", nil];

}

if (dataModel.bxDataArrayY) {

bxDataArrayY=dataModel.bxDataArrayY;

}else{

bxDataArrayY=[[NSMutableArray alloc]initWithObjects:[NSNumber numberWithFloat:13],[NSNumber numberWithFloat:12.9],[NSNumber numberWithFloat:23],[NSNumber numberWithFloat:19],[NSNumber numberWithFloat:18],[NSNumber numberWithFloat:5.5], nil];

}

rawDataArrayX=[[NSMutableArray alloc]initWithObjects:[NSNumber numberWithFloat:orginPoint.x+xFirstSpace+barWidth/2],[NSNumber numberWithFloat:orginPoint.x+BigBlank*1+xFirstSpace+barWidth/2],[NSNumber numberWithFloat:orginPoint.x+BigBlank*2+xFirstSpace+barWidth/2],[NSNumber numberWithFloat:orginPoint.x+BigBlank*3+xFirstSpace+barWidth/2],[NSNumber numberWithFloat:orginPoint.x+BigBlank*4+xFirstSpace+barWidth/2],[NSNumber numberWithFloat:orginPoint.x+BigBlank*5+xFirstSpace+barWidth/2], nil];

bxDataArrayX=[NSMutableArray arrayWithObjects:@"",@"",@"",@"",@"",@"", nil];

if (dataModel.legendTextArray) {

legendTextArray=dataModel.legendTextArray;

}else{

legendTextArray=[NSMutableArray arrayWithObjects:@"客户关注",@"其他经纪人的发布",@"您的发布", nil];

}

if (dataModel.xLabelFont) {

xLabelFont=dataModel.xLabelFont;

}else{

xLabelFont=[UIFont systemFontOfSize:12];

}

if (dataModel.xLabelTextColor) {

xLabelTextColor=dataModel.xLabelTextColor;

}else{

xLabelTextColor=HEXCOLOR(0xbbbbbb);

}

if (dataModel.legendFont) {

legendFont=dataModel.legendFont;

}else{

legendFont=[UIFont systemFontOfSize:12];

}

if (dataModel.legendPlaceType) {

legendPlaceType=dataModel.legendPlaceType;

}else{

legendPlaceType=LegendViewTypeHorizital;

}

if (dataModel.colorArray) {

colorArray=dataModel.colorArray;

}else{

colorArray=[NSMutableArray arrayWithObjects:HEXCOLOR(0x7c8ec0),HEXCOLOR(0x78c5f1),HEXCOLOR(0xdbdbdb), nil];

}

//寻找数组最大值

if (dataModel.zhiDingMaxValue!=nil) {

maxYValue=[dataModel.zhiDingMaxValue floatValue];

}else{

CGFloat maxYValue0=[self lookforMaxValueWithArray:bxDataArrayY];

CGFloat maxYvalue1=[self lookforMaxValueWithArray:fbBxDataArrayY];

CGFloat maxYvalue2=[self lookforMaxValueWithArray:myFbBXDatayArrayY];

CGFloat tempMax=MAX(MAX(maxYValue0, maxYvalue1), maxYvalue2);

maxYValue=tempMax+0.5*(tempMax/bxDataArrayY.count);

NSLog(@"maxyvalue:%f",maxYValue);

}

perPartbxValue=maxYValue/(bxDataArrayY.count);

dataModel.showRectBoundary?showRectBoundary=dataModel.showRectBoundary:YES;

isShowYAsix=dataModel.isShowYAsix;

isShowXkedu=dataModel.isShowXkedu;

isShowOrginXLabel=YES;

}

在这个获取初始化数据源的过程中,我们默认使用六组数据,也就是六组直方图来初始化这个这个直方图。我们默认是不显示纵轴的,只显示刻度label及其文本数据。请看图

(2)在这个获取数据源的数据中,看上图,我们需要用到 定位 每个刻度 实际高度,

perPartbxValue=maxYValue/(bxDataArrayY.count);,其中maxvalue ,这些柱体y坐标代表数据的最大值转化为实际绘图高度的最大值,bxDataArrayY.coun,表示三个柱体为一组,这个直方图共有多少组数。这个最大值如何寻找出来,我们封装一个方法。

- (CGFloat)lookforMaxValueWithArray:(NSMutableArray *)marray {   

 CGFloat  temMaxYValue=0;  

  if (marray.count>0) {    

    for (int k=0; ktvalue) ?(temMaxYValue=temMaxYValue) :(temMaxYValue=tvalue);

}

NSLog(@"temMaxYValue:%f",temMaxYValue);

}

return temMaxYValue;

}

这个方法便是从一个数组中寻找最大值。按上述方法从三组数组中寻求最大值,来作为直方图上线。

(4)还有一个,如何把纵轴代表的值,转化为实际绘图的高度,我们也封装了一个方法

- (CGFloat)rawYValue:(NSNumber *)yNum {

CGFloat yValue=(yNum.floatValue/perPartbxValue)*bigBlankY;

return yValue;

}

3.现在初始化数据准备的差不多,我们现在开始绘图吧,为了每次在addsubuview 时候调用,我们把绘图方法放在drawrect中,也便于更新数据再次调用。

//后addsubview 时候调用

- (void)drawRect:(CGRect)rect {     

   if (legendTextArray>0) {  

      // Drawing code    

    //获取当前环境    

    CGContextRef context=UIGraphicsGetCurrentContext();        //save context        CGContextSaveGState(context);    

          if (showRectBoundary) {     

       //画出矩形区域    

        CGRect rectAngle=rect;      

      //定义一个矩形路径     

       UIBezierPath * rectPath=[UIBezierPath bezierPathWithRect:rectAngle]; 

           //把矩形区域画出来      

                  [rectPath stroke];   

     }       

 //开始画x轴     

   UIColor *strokeColor=HEXCOLOR(0xd4d4d5);   

     [strokeColor set];  

  CGFloat orginPointY=self.bounds.size.height-CGRectGetHeight(self.downLegendView.frame)-40;        orginPoint=CGPointMake(LeftSpaceY, orginPointY);        //定义一个开始路径        UIBezierPath *xStartPath=[UIBezierPath bezierPath];        [xStartPath setLineWidth:1.0];        [xStartPath moveToPoint:orginPoint];        [xStartPath addLineToPoint:CGPointMake(orginPoint.x, orginPoint.y+BigKeduHeight)];        //标注x轴原点label        if (isShowOrginXLabel) {            [self createOrginXLabel];        }                        for (int i=0; i0) {

//

[self createBarWithIndex:p Color:colorArray[0] FromArray:bxDataArrayY orginx:xCenterValue-barWidth/2];

}

//画其他经纪人对该户型房源发布情况直方图

NSString *agent=legendTextArray[1];

if (agent.length>0) {

[self createBarWithIndex:p Color:colorArray[1] FromArray:fbBxDataArrayY orginx:xCenterValue+barWidth*1.5];

}

//创建x轴线下居室提示label

[self createPromtLableWithOrginx:xCenterValue+(barWidth*2) index:p];

//画您发布该户型房源的情况直方图

NSString *myFb=legendTextArray[2];

if (myFb.length>0) {

[self createBarWithIndex:p Color:colorArray[2] FromArray:myFbBXDatayArrayY orginx:xCenterValue+barWidth*3.5];

}

}

}

}

(1)在这个方法中首先用图例文本数组legendTextArray,来定义是否会直方图,legendTextArray 的count是否大于零,来定义是否绘图,在图例文本数组有数据的画图。而且count数目来代表,一组柱体到底画几组柱体。我们是根据UIgraphics 来获取当前绘图环境,并存储,以供下次取用。并绘制一个矩形区域作为绘图范围,当然这个区域是我们绘图方便需要,而不是项目需求,我们用showrect 这个Bool值来控制,yes 显示这个区域,否则不显示。请看代码

//获取当前环境

CGContextRef context=UIGraphicsGetCurrentContext();

//save context

CGContextSaveGState(context);

if (showRectBoundary) {

//画出矩形区域

CGRect rectAngle=rect;

//定义一个矩形路径

UIBezierPath * rectPath=[UIBezierPath bezierPathWithRect:rectAngle];

//把矩形区域画出来

[rectPath stroke];

}

(2)下面是绘画x轴线,并设置线条颜色,使用贝斯尔曲线作为绘制path

//开始画x轴

UIColor *strokeColor=HEXCOLOR(0xd4d4d5);

[strokeColor set];

CGFloat orginPointY=self.bounds.size.height-CGRectGetHeight(self.downLegendView.frame)-40;

orginPoint=CGPointMake(LeftSpaceY, orginPointY);

//定义一个开始路径

UIBezierPath *xStartPath=[UIBezierPath bezierPath];

[xStartPath setLineWidth:1.0];

[xStartPath moveToPoint:orginPoint];

[xStartPath addLineToPoint:CGPointMake(orginPoint.x, orginPoint.y+BigKeduHeight)];

//标注x轴原点label

if (isShowOrginXLabel) {

[self createOrginXLabel];

}

同样的方法绘制y轴线 ,详情请看drawret方法中的代码。

(3)然后我们画背景横线,这里使用的实线的方法,也可以使用画虚线的方法。

//画背景横线

for(int n=0; n<bxDataArrayY.count;n++ {

NSLog(@"n=%d",n);

UIView *lineView=[[UIView alloc]initWithFrame:CGRectMake(orginPoint.x, orginPoint.y-bigBlankY*(n+1)-0.5, rawDataArrayX.count *BigBlank, 1)];

lineView.backgroundColor=[UIColor lightGrayColor];

[self addSubview:lineView];

}

(4)画6组直方图,每一组直方图中有三个柱体。

for (int p=0; p<rawDataArrayX.count;p++ {

//画关注度直方图

NSString *gz=legendTextArray[0];

NSNumber *xNum=rawDataArrayX[p];

CGFloat xCenterValue=xNum.floatValue;

if (gz.length>0) {

//

[self createBarWithIndex:p Color:colorArray[0] FromArray:bxDataArrayY orginx:xCenterValue-barWidth/2];

}

//画其他经纪人对该户型房源发布情况直方图

NSString *agent=legendTextArray[1];

if (agent.length>0) {

[self createBarWithIndex:p Color:colorArray[1] FromArray:fbBxDataArrayY orginx:xCenterValue+barWidth*1.5];

}

//创建x轴线下居室提示label

[self createPromtLableWithOrginx:xCenterValue+(barWidth*2) index:p];

//画您发布该户型房源的情况直方图

NSString *myFb=legendTextArray[2];

if (myFb.length>0) {

[self createBarWithIndex:p Color:colorArray[2] FromArray:myFbBXDatayArrayY orginx:xCenterValue+barWidth*3.5];

}

}




}

(5) 在drawrect中我们封装创建原点xlabel,并封装方法

- (void)createOrginXLabel{

NSString *text=@"0:00";

CGSize textSize;

if (text.length>0) {

textSize=[text sizeWithAttributes:@{NSFontAttributeName:xLabelFont}];

}

UILabel *xlabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, textSize.width,20)];

xlabel.center=CGPointMake(orginPoint.x, orginPoint.y+10);

xlabel.backgroundColor=[UIColor clearColor];

xlabel.font=xLabelFont;

[xlabel setTextColor:xLabelTextColor];

xlabel.text=text;

xlabel.textAlignment=NSTextAlignmentCenter;

xlabel.numberOfLines=0;

[xlabel setLineBreakMode:NSLineBreakByCharWrapping];

[self addSubview:xlabel];

}

其他非原点xlabel 我们也封装了一个方法,并根据文字方向是横向还是纵向,

- (void)createPromtLableWithOrginx:(CGFloat)orginx  index:(NSInteger)index{

NSString *text=roomNameArray[index];

CGSize textSize;

if (self.dataModel.xtextType==XLabelPlaceHorizital) {

//文字方向横向排列

if (text.length>0) {

textSize=[text sizeWithAttributes:@{NSFontAttributeName:xLabelFont}];

}

UILabel *xlabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, textSize.width,20)];

xlabel.center=CGPointMake(orginx, orginPoint.y+10);

xlabel.backgroundColor=[UIColor clearColor];

xlabel.font=xLabelFont;

[xlabel setTextColor:xLabelTextColor];

xlabel.text=roomNameArray[index];

xlabel.textAlignment=NSTextAlignmentCenter;

xlabel.numberOfLines=0;

[xlabel setLineBreakMode:NSLineBreakByCharWrapping];

[self addSubview:xlabel];

}else{

if (text.length>0) {

if ([text containsString:@"-"])

{

NSArray *arr=[text componentsSeparatedByString:@"-"];

NSLog(@"array:%@",arr);

NSString *targetStr=@"";

if (arr.count==2)

{

targetStr=[targetStr stringByAppendingString:arr[0]];

targetStr=[targetStr stringByAppendingString:@"\n"];

targetStr=[targetStr stringByAppendingString:@"|"];

targetStr=[targetStr stringByAppendingString:@"\n"];

targetStr=[targetStr stringByAppendingString:arr[1]];

NSLog(@"targetstr:%@",targetStr);

//文字方向纵向排列

UILabel *xlabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, BigBlank,100)];

xlabel.center=CGPointMake(orginx, orginPoint.y+10+30);

xlabel.backgroundColor=[UIColor clearColor];

xlabel.font=xLabelFont;

[xlabel setTextColor:xLabelTextColor];

xlabel.text=targetStr;

xlabel.textAlignment=NSTextAlignmentCenter;

xlabel.numberOfLines=0;

[xlabel setLineBreakMode:NSLineBreakByCharWrapping];

[self addSubview:xlabel];

NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc]initWithString:xlabel.text];

NSRange range = [xlabel.text rangeOfString:targetStr];                              //范围

[attStr addAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor],

NSVerticalGlyphFormAttributeName:[NSNumber numberWithFloat:1]} range:range];//添加属性

[xlabel setAttributedText:attStr];

CGSize targetSize=[text sizeWithAttributes:@{NSFontAttributeName:xLabelFont,NSVerticalGlyphFormAttributeName:[NSNumber numberWithFloat:1]}];

NSLog(@"textwidth:%f,textHeight:%f",targetSize.width,targetSize.height);

}

}

else{

//文字方向纵向排列

UILabel *xlabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, BigBlank,100)];

xlabel.center=CGPointMake(orginx, orginPoint.y+10+50);

xlabel.backgroundColor=[UIColor redColor];

xlabel.font=xLabelFont;

[xlabel setTextColor:xLabelTextColor];

xlabel.text=text;

xlabel.textAlignment=NSTextAlignmentCenter;

xlabel.numberOfLines=0;

[xlabel sizeToFit];

[xlabel setLineBreakMode:NSLineBreakByCharWrapping];

[self addSubview:xlabel];

NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc]initWithString:xlabel.text];

NSRange range = [xlabel.text rangeOfString:text];                              //范围

[attStr addAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor],

NSVerticalGlyphFormAttributeName:[NSNumber numberWithFloat:1]} range:range];//添加属性

[xlabel setAttributedText:attStr];

}

}

if (text.length>0) {

textSize=[text sizeWithAttributes:@{NSFontAttributeName:xLabelFont}];

}

;

}

}

(6)同样我们绘画但个柱体,我们也封装了方法,封装这些方法,就是便于逻辑表达和方法调用,降低代码耦合性。在绘画柱体的过程中,我们同样适用动画,是柱体匀速增长

-  (void)createBarWithIndex:(NSInteger)index Color:(UIColor *)bgColor FromArray:(NSMutableArray *)array orginx:(CGFloat)orginx  {

NSNumber *yNum=array[index];

CGFloat yCenterValue=[self rawYValue:yNum];

CGRect barRect=CGRectMake(orginx,orginPoint.y-yCenterValue , barWidth, yCenterValue);

__block  float barH=0;

UIView *barView=[[UIView alloc]initWithFrame:CGRectMake(orginx,orginPoint.y-barH , barWidth, barH)];

barView.backgroundColor=bgColor;

[self addSubview:barView];

[UIView animateWithDuration:0.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{

if (barH<=yCenterValue) {

barH+=5;

}

barView.frame=CGRectMake(orginx,orginPoint.y-barH , barWidth, barH);

} completion:^(BOOL finished){

barView.frame=barRect;

} ];

}

5.我们回到初始化方法,我们需要创建图例view ,这个图例,一般横向图例放置方式,当然也有纵向放置,我们默认使用横向图例。

- (void)createLegendView {

[self addSubview:self.downLegendView];

//客户对该户型房源的关注度 图例

NSString*guzhu=legendTextArray[0];

UILabel *guzhuLabel;

if (guzhu.length>0) {

CGSize size=[guzhu sizeWithAttributes:@{NSFontAttributeName:legendFont}];

legendLabelHeight=size.height;

if (legendPlaceType==LegendViewTypeVertical) {

[self createLegendWithColor:colorArray[0] AndPromtLabelWithText:guzhu OnSuperView:self.downLegendView orginY:0];

}else{

guzhuLabel=[self createHoritalLegendWithColor:colorArray[0] AndPromtLabelWithText:guzhu OnSuperView:self.downLegendView orginX:(CGRectGetWidth(self.downLegendView.frame)-240)/2];

[self.downLegendView addSubview:guzhuLabel];

}

}

//其他经纪人对户型房源的发布情况 图例

NSString *qita=legendTextArray[1];

UILabel *agentLabel;

if (qita.length>0) {

if (legendPlaceType==LegendViewTypeVertical) {

[self createLegendWithColor:colorArray[1] AndPromtLabelWithText:qita OnSuperView:self.downLegendView orginY:legendLabelHeight+legendVSpace];

}else{

agentLabel=[self createHoritalLegendWithColor:colorArray[1] AndPromtLabelWithText:qita OnSuperView:self.downLegendView orginX:CGRectGetMaxX(guzhuLabel.frame)+LegendSpaceHorital];

[self.downLegendView addSubview:agentLabel];

}

}

//您发布该户型房源的情况

NSString *fabu=legendTextArray[2];

UILabel *myFbLabel;

if (fabu.length>0) {

if (legendPlaceType==LegendViewTypeVertical) {

[self createLegendWithColor:colorArray[2] AndPromtLabelWithText:fabu OnSuperView:self.downLegendView orginY:(legendLabelHeight+legendVSpace)*2];

}else{

myFbLabel=[self createHoritalLegendWithColor:colorArray[2] AndPromtLabelWithText:fabu OnSuperView:self.downLegendView orginX:CGRectGetMaxX(agentLabel.frame)+LegendSpaceHorital];

[self.downLegendView addSubview:myFbLabel];

}

//        CGFloat legendVWidth=CGRectGetMaxX(myFbLabel.frame)-CGRectGetMinX(guzhuLabel.frame);

//        NSLog(@"legendvwidth:%f",legendVWidth);

}

}

(1)首先使用懒加载的方法创建总图例view,看代码

- (UIView *)downLegendView {

if (_downLegendView==nil) {

if (legendPlaceType==LegendViewTypeVertical) {

_downLegendView=[[UIView alloc]initWithFrame:CGRectMake(10, self.bounds.size.height-70, self.bounds.size.width-20, 60)];

}

else if (legendPlaceType==LegendViewTypeHorizital){

_downLegendView=[[UIView alloc]initWithFrame:CGRectMake(10, self.bounds.size.height-30, self.bounds.size.width-20, 20)];

}

//        _downLegendView.backgroundColor=[UIColor greenColor];

}

return _downLegendView;

}

(2)看图,我们知道,每组图例,有图例和图例文本组成。这样我们封装了一个方法

- (void)createLegendWithColor:(UIColor *)bgColor  AndPromtLabelWithText:(NSString *)text OnSuperView:(UIView *)spView  orginY:(CGFloat)y  {

//前面颜色图标

CGSize size=[text sizeWithAttributes:@{NSFontAttributeName:legendFont}];

legendLabelHeight=size.height;

UIImageView *guzhuLegend=[[UIImageView  alloc]initWithFrame:CGRectMake(orginPoint.x, y, legendLabelHeight, legendLabelHeight)];

guzhuLegend.image=[self createLegendPointImageWithRadius:3 color:bgColor];

//    guzhuLegend.backgroundColor=bgColor;

[spView addSubview:guzhuLegend];

//后面解释文字label

UILabel *promtLabel=[[UILabel alloc]initWithFrame:CGRectMake(CGRectGetMaxX(guzhuLegend.frame)+5, y,CGRectGetWidth(spView.frame)-CGRectGetMaxX(guzhuLegend.frame)-5, legendLabelHeight)];

promtLabel.text=text;

promtLabel.font=legendFont;

promtLabel.textAlignment=NSTextAlignmentLeft;

[spView addSubview:promtLabel];

}

其中,我们采用UIgraphics方法,自己绘制图例,再生成图片,而不是直接采用图片的方式,见代码如下

- (UIImage *)createLegendPointImageWithRadius:(CGFloat)radius color:(UIColor *)color {

UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius * 2,radius * 2), NO, 0);

UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, radius * 2, radius * 2) cornerRadius:radius];

[color setFill];

[path fill];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return image;

}

上面是画图例竖直放置,当然也有水平放置图例的,也封装了一个 方法。

- (UILabel *)createHoritalLegendWithColor:(UIColor *)bgColor  AndPromtLabelWithText:(NSString *)text OnSuperView:(UIView *)spView  orginX:(CGFloat)x  {

//前面颜色图标

CGSize size=[text sizeWithAttributes:@{NSFontAttributeName:legendFont}];

legendLabelHeight=size.height;

UIImageView *guzhuLegend=[[UIImageView  alloc]initWithFrame:CGRectMake(x, 0, 6, 6)];

guzhuLegend.center=CGPointMake(x+3, legendLabelHeight/2);

guzhuLegend.image=[self createLegendPointImageWithRadius:3 color:bgColor];

//    guzhuLegend.backgroundColor=bgColor;

[spView addSubview:guzhuLegend];

//后面解释文字label

UILabel *promtLabel=[[UILabel alloc]initWithFrame:CGRectMake(CGRectGetMaxX(guzhuLegend.frame)+5, 0,size.width, legendLabelHeight)];

promtLabel.text=text;

promtLabel.font=legendFont;

promtLabel.textAlignment=NSTextAlignmentLeft;

//    [spView addSubview:promtLabel];

return promtLabel;

}

6. 最后我们看一下数据源model,在FangBarChartDataModel.h中

#import <Foundation/Foundation.h>

#import <UIkit/UIkit.h>

typedef enum {

LegendViewTypeHorizital=10,//图例水平放置

LegendViewTypeVertical,//图例竖直放置

} LegendViewType;

typedef enum {

XLabelPlaceHorizital=10,//x 轴下label文字水平放置

XLabelPlaceTypeVertical,//x 轴下label文字竖直放置

} XLabelPlaceType;

@interface FangBarChartDataModel : NSObject

@property (nonatomic)CGFloat xFirstSpace;//x轴大刻度内bar前空白距离

@property (nonatomic)CGFloat  xEndSpace;//x轴大刻度内bar前空白距离

@property (nonatomic)CGFloat legendVSpace;//bar 之间空白距离

@property (nonatomic,strong)NSMutableArray *fbBxDataArrayY;//经纪人对该户型房源发布数据的显示数据数组 y轴方向

@property (nonatomic,strong)NSMutableArray *myFbBXDatayArrayY;//您发布该户型房源的情况

@property (nonatomic,strong)NSMutableArray *roomNameArray;//bar下标题数据源数组

@property (nonatomic,strong)NSMutableArray *bxDataArrayY;//客户对该户型房源关注度数据的显示数据数组 y轴方向

@property (nonatomic)BOOL showRectBoundary;//是否显示整个直方图矩形边缘

@property (nonatomic,strong)NSMutableArray *legendTextArray;//图例提示文字数组

@property (nonatomic,strong)UIFont *xLabelFont;//bar下标题font

@property (nonatomic,strong)UIColor *xLabelTextColor;//bar下标题文本颜色

@property (nonatomic,strong)UIFont *legendFont;//图例字体@property (nonatomic)LegendViewType legendPlaceType;//图例放置方向,

@property (nonatomic,strong)NSMutableArray *colorArray;//图例和直方图bar填充yanse

@property (nonatomic)BOOL isShowYAsix;//是否显示y轴

@property (nonatomic)BOOL isShowXkedu;//是否显示x轴刻度

@property (nonatomic) BOOL isShowOrginXLabel;//是否显示坐标原点x方向texLabel

@property (nonatomic,strong)  NSNumber *zhiDingMaxValue;//接口指定最大值;y轴

@property (nonatomic) LegendViewType legendPlaceType;

@property (nonatomic) XLabelPlaceType  xtextType;

@end

在import "FangBarChartDataModel.m"中

@implementation FangBarChartDataModel

@end

7.在代码中使用自己封装的 uilabel 文字,数字英文竖直排版的类别方法,在这个类别方法中采用在每个单词间,单词与数字或汉语间插入回车键,基本能达到数字排列文本的目的

先分享如下

@interface UILabel (verticalPlaceExtention)

@property (nonatomic) NSString *verticalText;

@end

#import "UILabel+verticalPlaceExtention.h"

#import "objc/Runtime.h"

@implementation UILabel (verticalPlaceExtention)

- (NSString *)verticalText{

// 利用runtime添加属性

return objc_getAssociatedObject(self, @selector(verticalText));

}

- (void)setVerticalText:(NSString *)verticalText{

objc_setAssociatedObject(self, &verticalText, verticalText, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

NSMutableString *str = [[NSMutableString alloc] initWithString:verticalText];

NSInteger count = str.length;

for (int i = 1; i < count; i ++) {

[str insertString:@"\n" atIndex:i*2-1];

}

self.text = str;

self.numberOfLines = 0;

}

@end



本项目源码地址:https://github.com/bianguangshengFang/FangBarScrollView.git

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

推荐阅读更多精彩内容