可以自定義的直方圖

直方圖主要用在數據圖表,作為對比數據,用柱體高度的高低,形象直觀地表達出來,往往與折線圖配合使用,而折線圖便于從眾多數據,在時間長度上看出,觀察對象發展的趨勢。下面直接上代碼,

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容