iOS按比例實(shí)現(xiàn)方塊圖
本文實(shí)例為大家分享了iOS按比例實(shí)現(xiàn)方塊圖的具體代碼,供大家參考,具體內(nèi)容如下
原理:二分法遞歸實(shí)現(xiàn),就是每次“對(duì)半分”,分到只剩兩個(gè)
上代碼:SZBlockView
@interface SZBlockView : UIView
@property (nonatomic, strong) NSArray *data;//數(shù)據(jù)源
@end
#import "SZBlockView.h"
#import "SZItemView.h"
@implementation SZBlockView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = UIColor.whiteColor;
}
return self;
}
-(void)setData:(NSArray *)data
{
_data = data;
[self removeAll];
for (NSString* value in data) {
[self addSubNode:[value intValue]];
}
[self recalcLayout];
}
-(void)addSubNode:(int)value
{
SZItemView* item = [SZItemView new];
item.value = value;
[self addSubview:item];
}
-(void)removeAll
{
//移除所有子視圖
[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
-(bool)isVertical:(double)w Height:(double) h
{
return w / h > 1.618;//黃金比例,可以自己根據(jù)需求修改
}
-(void)recalcLayout
{
if (self.subviews.count < 1) return;
[self recalcSquarifiedLayout:0 Finish:self.subviews.count - 1 Area:self.bounds];
}
-(void)recalcSliceLayout:(NSUInteger)nStart Finish:(NSUInteger)nFinish Area:(CGRect)rect IsVertical:(bool) bIsVertical
{
NSAssert(nStart < self.subviews.count, @"nStart >= self.subviews.count");
NSAssert(nFinish < self.subviews.count, @"nFinish >= self.subviews.count");
if (nStart == nFinish)
{
[self.subviews[nStart] setFrame:rect];
return;
}
double dblTotal = [self getChildrenTotal:nStart Finish:nFinish];
double x = rect.origin.x;
double y = rect.origin.y;
if (bIsVertical)
{
for (NSUInteger i = nStart; i <= nFinish; i++)
{
SZItemView* item = self.subviews[i];
double cx = rect.size.width * item.value / dblTotal;
CGRect rectSubNode = item.frame;
rectSubNode = rect;
rectSubNode.origin.x = x;
if (i == nFinish) {
rectSubNode.size.width = cx;
}else{
rectSubNode.size.width = cx-1;
}
item.frame = rectSubNode;
x += cx;
}
} else
{
for (NSUInteger i = nStart; i <= nFinish; i++)
{
SZItemView* item = self.subviews[i];
double cy = rect.size.height * item.value / dblTotal;
CGRect rectSubNode = item.frame;
rectSubNode = rect;
rectSubNode.origin.y = y;
if (i==nFinish) {
rectSubNode.size.height = cy;
}else{
rectSubNode.size.height = cy-1;
}
item.frame = rectSubNode;
y += cy;
}
}
}
-(void)recalcSquarifiedLayout:(NSUInteger)nStart Finish:(NSUInteger)nFinish Area:(CGRect) rect
{
NSAssert(nStart < self.subviews.count, @"nStart >= self.subviews.count");
NSAssert(nFinish < self.subviews.count, @"nFinish >= self.subviews.count");
if (nStart + 2 > nFinish)
{
return [self recalcSliceLayout:nStart Finish:nFinish Area:rect IsVertical:[self isVertical:rect.size.width Height:rect.size.height]];
}
double total = [self getChildrenTotal:nStart Finish:nFinish],total_left = 0.;
for (NSUInteger i = nStart; i <= nFinish; i++)
{
SZItemView* item = self.subviews[i];
double pre_dt = total_left - total / 2;
total_left += item.value;
double dt = total_left - total / 2;
if (dt > 0)
{
if (dt + pre_dt > 0)
{
total_left -= item.value;
i--;
}
if ([self isVertical:rect.size.width Height:rect.size.height])
{
CGRect rectLeft = rect;
rectLeft.size.width = rect.size.width * total_left / total - 1;
[self recalcSquarifiedLayout:nStart Finish:i Area:rectLeft];
CGRect rectRight = rect;
rectRight.origin.x = rectLeft.origin.x + rectLeft.size.width + 1;
rectRight.size.width = rect.size.width - rectLeft.size.width - 1;
[self recalcSquarifiedLayout:i + 1 Finish:nFinish Area:rectRight];
} else
{
CGRect rectTop = rect;
rectTop.size.height = rect.size.height * total_left / total - 1;
[self recalcSquarifiedLayout:nStart Finish:i Area:rectTop];
CGRect rectBottom = rect;
rectBottom.origin.y = rectTop.origin.y + rectTop.size.height + 1;
rectBottom.size.height = rect.size.height - rectTop.size.height - 1;
[self recalcSquarifiedLayout:i + 1 Finish:nFinish Area:rectBottom];
}
return;
}
}
// NSAssert(false, @"unreachable");
}
-(double)getChildrenTotal:(NSUInteger)nStart Finish:(NSUInteger) nFinish
{
double dblTotal = 0.;
for (NSUInteger i = nStart; i <= nFinish; i++)
{
SZItemView* item = self.subviews[i];
dblTotal += item.value;
}
return dblTotal;
}
@end
SZItemView 里面的每一個(gè)小的視圖
@interface SZItemView : UIView
@property (nonatomic, assign) int value;//傳入要顯示的值
@end
#import "SZItemView.h"
@interface SZItemView ()
@property (nonatomic, strong) UILabel *valueLabel;
@end
@implementation SZItemView
- (instancetype)init
{
self = [super init];
if (self) {
[self setupUI];
}
return self;
}
-(void)setupUI{
UILabel *valueLabel = [[UILabel alloc] initWithFrame:self.frame];
valueLabel.adjustsFontSizeToFitWidth = YES;
self.valueLabel = valueLabel;
valueLabel.textAlignment = NSTextAlignmentCenter;
valueLabel.textColor = UIColor.whiteColor;
[self addSubview:valueLabel];
}
- (void)setValue:(int)value{
_value = value;
self.valueLabel.text = [NSString stringWithFormat:@"%d",value];
self.backgroundColor = UIColor.orangeColor;
}
- (void)layoutSubviews{//如果用masonry布局此方法可不實(shí)現(xiàn)
self.valueLabel.frame = self.bounds;
self.valueLabel.adjustsFontSizeToFitWidth = YES;
}
@end
效果圖:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS中實(shí)現(xiàn)imageView任意角度旋轉(zhuǎn)的方法
這篇文章主要給大家介紹了關(guān)于iOS中實(shí)現(xiàn)imageView任意角度旋轉(zhuǎn)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
iOS開(kāi)發(fā)中UITabBarController的使用示例
這篇文章主要介紹了iOS開(kāi)發(fā)中UITabBarController的使用示例,代碼基于Objective-C進(jìn)行演示,需要的朋友可以參考下2015-09-09
iOS實(shí)現(xiàn)無(wú)限滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)無(wú)限滑動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
詳解iOS應(yīng)用開(kāi)發(fā)中Core Data數(shù)據(jù)存儲(chǔ)的使用
這篇文章主要介紹了iOS應(yīng)用開(kāi)發(fā)中Core Data數(shù)據(jù)存儲(chǔ)的使用,Core Data可以看作是一個(gè)內(nèi)嵌型數(shù)據(jù)庫(kù)SQLite的iOS專用版本,需要的朋友可以參考下2016-02-02
iPhone/iPad開(kāi)發(fā)通過(guò)LocalNotification實(shí)現(xiàn)iOS定時(shí)本地推送功能
這篇文章主要介紹了iPhone/iPad開(kāi)發(fā)之通過(guò)LocalNotification實(shí)現(xiàn)iOS定時(shí)本地推送功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
個(gè)人對(duì)于異步和多線程的關(guān)系的理解分享
異步和多線程并不是一個(gè)同等關(guān)系,異步是最終目的,多線程只是我們實(shí)現(xiàn)異步的一種手段。異步是當(dāng)一個(gè)調(diào)用請(qǐng)求發(fā)送給被調(diào)用者,而調(diào)用者不用等待其結(jié)果的返回而可以做其它的事情。2014-08-08

