iOS按比例实现方块图

 更新时间:2021年06月16日 09:53:03   作者:shuzhi57  
这篇文章主要为大家详细介绍了iOS按比例实现方块图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了iOS按比例实现方块图的具体代码,供大家参考,具体内容如下

原理:二分法递归实现,就是每次“对半分”,分到只剩两个

上代码:SZBlockView 

@interface SZBlockView : UIView
@property (nonatomic, strong) NSArray *data;//数据源
@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;//黄金比例,可以自己根据需求修改
}
 
-(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 里面的每一个小的视图

@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布局此方法可不实现
    self.valueLabel.frame = self.bounds;
    self.valueLabel.adjustsFontSizeToFitWidth = YES;
}
@end

效果图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

相关文章

  • iOS中遍历的方法总结

    iOS中遍历的方法总结

    本篇文章主要介绍了iOS中遍历的方法总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • iOS中实现imageView任意角度旋转的方法

    iOS中实现imageView任意角度旋转的方法

    这篇文章主要给大家介绍了关于iOS中实现imageView任意角度旋转的方法,文中通过示例代码介绍的非常详细,对大家学习或者工作具有一定的参考学习价值,需要的朋友下面随着小编来一起学习学习吧。
    2017-12-12
  • iOS开发中UITabBarController的使用示例

    iOS开发中UITabBarController的使用示例

    这篇文章主要介绍了iOS开发中UITabBarController的使用示例,代码基于Objective-C进行演示,需要的朋友可以参考下
    2015-09-09
  • iOS把图片缓存到本地的几种方法(总结)

    iOS把图片缓存到本地的几种方法(总结)

    下面小编就为大家分享一篇iOS把图片缓存到本地的几种方法总结,具有很的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • iOS实现无限滑动效果

    iOS实现无限滑动效果

    这篇文章主要为大家详细介绍了iOS实现无限滑动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • ios设计模式--委托模式

    ios设计模式--委托模式

    这篇文章主要介绍了ios设计模式中的委托模式,希望对大家学习ios框架有所帮助,下面让我们一起来了解一下吧
    2023-03-03
  • 详解iOS应用开发中Core Data数据存储的使用

    详解iOS应用开发中Core Data数据存储的使用

    这篇文章主要介绍了iOS应用开发中Core Data数据存储的使用,Core Data可以看作是一个内嵌型数据库SQLite的iOS专用版本,需要的朋友可以参考下
    2016-02-02
  • iPhone/iPad开发通过LocalNotification实现iOS定时本地推送功能

    iPhone/iPad开发通过LocalNotification实现iOS定时本地推送功能

    这篇文章主要介绍了iPhone/iPad开发之通过LocalNotification实现iOS定时本地推送功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • iOS逆向教程之跟踪函数调用详解

    iOS逆向教程之跟踪函数调用详解

    这篇文章主要给大家介绍了关于iOS逆向教程之跟踪函数调用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-04-04
  • 个人对于异步和多线程的关系的理解分享

    个人对于异步和多线程的关系的理解分享

    异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。
    2014-08-08

最新评论