美文网首页
OC_九宫格布局工具

OC_九宫格布局工具

作者: LiYaoPeng | 来源:发表于2018-11-19 12:08 被阅读0次

    实现基于: iOS Masonry九宫格布局 - 一行代码实现九宫格

    demo点这里

    以后你可能会这样布局九宫格

    [PYLayoutSudokuViewHandler
        .create()
        .setUpFixedItemSpacing(CGSizeMake(10, 10))
        .setUpWarpCount(3)
        .setUpFixedItemSize(CGSizeMake(w, w))
        .setUpSudokuViewEdges(UIEdgeInsetsMake(15, 15, 15, 15))
        layoutSudokuViewWithViews:scrollView.subviews];
    

    注意

    • @warning item自适应宽高 itemSize == CGSizeNull、或者 CGSizeZero
    • @warning 拉伸fixedItemSpacing固定itemsize: 设置itemSize,不设置fixedItemSpacing
    • @warning 撑开superView的宽高:
      设置 itemSize 不为null,并且 fixedItemSpacing 不为null

    .h

    
    #import <Foundation/Foundation.h>
    /**
     实现基于: [iOS Masonry九宫格布局 - 一行代码实现九宫格](https://www.cnblogs.com/YHStar/p/5788896.html)
     * @warning item自适应宽高 itemSize == CGSizeNull、或者 CGSizeZero
      * @warning 拉伸fixedItemSpacing固定itemsize: 设置itemSize,不设置fixedItemSpacing
     * @warning 撑开superView的宽高:
     设置 itemSize 不为null,并且 fixedItemSpacing 不为null
     */
    @interface PYLayoutSudokuViewHandler : NSObject
    
    + (PYLayoutSudokuViewHandler *(^)(void)) create;
    /**
     * item的宽高
     * @warning 如果不设置,那么就会根据superview宽高以及fixedItemSpacing自适应
     * @warning 默认为CGSizeZero
     */
    @property (nonatomic,assign) CGSize fixedItemSize;
    /**
     * item的宽高
     * @warning 如果不设置,那么就会根据superview宽高以及fixedItemSpacing自适应
     * @warning 默认为CGSizeZero
     */
    - (PYLayoutSudokuViewHandler *(^)(CGSize fixedItemSize)) setUpFixedItemSize;
    
    
    /**
     * 宫格的间距,如果宫格只有一行,则不生效
     * @warning 如果不设置,则会根据itemSize与superviewSize被拉伸适应
     * @warning 默认为CGSize(-1,-1)
     */
    @property (nonatomic,assign) CGSize fixedItemSpacing;
    /**
     * 宫格的间距,如果宫格只有一行,则不生效
     * @warning 如果不设置,则会根据itemSize与superviewSize被拉伸适应
     * @warning 默认为CGSize(-1,-1)
     */
    - (PYLayoutSudokuViewHandler *(^)(CGSize fixedItemSpacing)) setUpFixedItemSpacing;
    
    
    /**
     * :折行的位置,
     * @warning 如果设置为3,则表示该九宫格需要布局3列
     * @warning 值得一提的是,如果NSArray本身的count如果小于warpCount,则该函数会用空的UIView填充到缺失区域。
     */
    @property (nonatomic,assign) NSInteger warpCount;
    /**
     * :折行的位置,
     * @warning 如果设置为3,则表示该九宫格需要布局3列
     * @warning 值得一提的是,如果NSArray本身的count如果小于warpCount,则该函数会用空的UIView填充到缺失区域。
     */
    - (PYLayoutSudokuViewHandler *(^)(NSInteger warpCount)) setUpWarpCount;
    
    
    
    /**
     * 九宫格顶边距,底边距,左边距以及右边距
     */
    @property (nonatomic,assign) UIEdgeInsets sudokuViewEdges;
    /**
     * 九宫格顶边距,底边距,左边距以及右边距
     */
    - (PYLayoutSudokuViewHandler *(^)(UIEdgeInsets sudokuViewEdges)) setUpSudokuViewEdges;
    
    
    
    /**
     布局
     @param viewArray 要布局的view
     */
    - (void) layoutSudokuViewWithViews: (NSArray <UIView*>*)viewArray;
    @end
    

    .m

    
    #import "PYLayoutSudokuViewHandler.h"
    #import <Masonry/Masonry.h>
    @implementation PYLayoutSudokuViewHandler
    
    
    #pragma mark - init
    + (PYLayoutSudokuViewHandler *(^)(void))create {
        return ^(void) {
            PYLayoutSudokuViewHandler *handler = [[PYLayoutSudokuViewHandler alloc]init];
            if (!handler) {
                handler = [PYLayoutSudokuViewHandler new];
            }
            handler.fixedItemSize = CGSizeZero;
            handler.fixedItemSpacing = CGSizeMake(-1, -1);
            return handler;
        };
    }
    #pragma mark - functions
    
    // MARK: handle views
    - (void) layoutSudokuViewWithViews: (NSArray <UIView*>*)viewArray {
        if (self.fixedItemSpacing.width < 0 || self.fixedItemSpacing.height < 0) {
            [self mas_distributeSudokuViews_NotFixedItemSpacing: viewArray];
        }else{
            [self mas_distributeSudokuViews_FixedItemSpacing:viewArray];
        }
    }
    
    - (UIView *)star_commonSuperviewOfViews: (NSArray *)viewArray {
        if (viewArray.count == 1) {
            return ((UIView *)viewArray.firstObject).superview;
        }
        UIView *commonSuperview = nil;
        UIView *previousView = nil;
        for (id object in viewArray) {
            if ([object isKindOfClass:[UIView class]]) {
                UIView *view = (UIView *)object;
                if (previousView) {
                    commonSuperview = [view mas_closestCommonSuperview:commonSuperview];
                } else {
                    commonSuperview = view;
                }
                previousView = view;
            }
            
        }
        
        NSAssert(commonSuperview, @"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy.");
        
        return commonSuperview;
    }
    
    - (NSArray <UIView *>*)mas_distributeSudokuViews_FixedItemSpacing: (NSArray <UIView *>*)viewArray{
        
        CGFloat fixedItemWidth = self.fixedItemSize.width;
        CGFloat fixedItemHeight = self.fixedItemSize.height;
        CGFloat fixedLineSpacing = self.fixedItemSpacing.height;
        CGFloat fixedInteritemSpacing = self.fixedItemSpacing.width;
        NSInteger warpCount = self.warpCount;
        CGFloat topSpacing = self.sudokuViewEdges.top;
        CGFloat bottomSpacing = self.sudokuViewEdges.bottom;
        CGFloat leadSpacing = self.sudokuViewEdges.left;
        CGFloat tailSpacing = self.sudokuViewEdges.right;
        if (viewArray.count < 1) {
            return viewArray.copy;
        }
        if (warpCount < 1) {
            NSAssert(false, @"warp count need to bigger than zero");
            return viewArray.copy;
        }
        
        UIView *tempSuperView = [self star_commonSuperviewOfViews: viewArray];
        
        NSArray *tempViews = viewArray.copy;
        if (warpCount > viewArray.count) {
            for (int i = 0; i < warpCount - viewArray.count; i++) {
                UIView *tempView = [[UIView alloc] init];
                [tempSuperView addSubview:tempView];
                tempViews = [tempViews arrayByAddingObject:tempView];
            }
        }
        
        NSInteger columnCount = warpCount;
        NSInteger rowCount = tempViews.count % columnCount == 0 ? tempViews.count / columnCount : tempViews.count / columnCount + 1;
        
        UIView *prev;
        for (int i = 0; i < tempViews.count; i++) {
            
            UIView *v = tempViews[i];
            NSInteger currentRow = i / columnCount;
            NSInteger currentColumn = i % columnCount;
            
            [v mas_makeConstraints:^(MASConstraintMaker *make) {
                if (prev) {
                    // 固定宽度
                    make.width.equalTo(prev);
                    make.height.equalTo(prev);
                }
                else {
                    // 如果写的item高宽分别是0,则表示自适应
                    if (fixedItemWidth) {
                        make.width.equalTo(@(fixedItemWidth));
                    }
                    if (fixedItemHeight) {
                        make.height.equalTo(@(fixedItemHeight));
                    }
                }
                
                // 第一行
                if (currentRow == 0) {
                    make.top.equalTo(tempSuperView).offset(topSpacing);
                }
                // 最后一行
                if (currentRow == rowCount - 1) {
                    // 如果只有一行
                    if (currentRow != 0 && i-columnCount >= 0) {
                        make.top.equalTo(((UIView *)tempViews[i-columnCount]).mas_bottom).offset(fixedLineSpacing);
                    }
                    make.bottom.equalTo(tempSuperView).offset(-bottomSpacing);
                }
                // 中间的若干行
                if (currentRow != 0 && currentRow != rowCount - 1) {
                    make.top.equalTo(((UIView *)tempViews[i-columnCount]).mas_bottom).offset(fixedLineSpacing);
                }
                
                // 第一列
                if (currentColumn == 0) {
                    make.left.equalTo(tempSuperView).offset(leadSpacing);
                }
                // 最后一列
                if (currentColumn == columnCount - 1) {
                    // 如果只有一列
                    if (currentColumn != 0) {
                        make.left.equalTo(prev.mas_right).offset(fixedInteritemSpacing);
                    }
                    make.right.equalTo(tempSuperView).offset(-tailSpacing);
                }
                // 中间若干列
                if (currentColumn != 0 && currentColumn != warpCount - 1) {
                    make.left.equalTo(prev.mas_right).offset(fixedInteritemSpacing);
                }
            }];
            prev = v;
        }
        return tempViews;
    }
    
    - (void)mas_distributeSudokuViews_NotFixedItemSpacing: (NSArray <UIView *> *) viewArray {
        
        CGFloat fixedItemWidth = self.fixedItemSize.width;
        CGFloat fixedItemHeight = self.fixedItemSize.height;
        NSInteger warpCount = self.warpCount;
        CGFloat topSpacing = self.sudokuViewEdges.top;
        CGFloat bottomSpacing = self.sudokuViewEdges.bottom;
        CGFloat leadSpacing = self.sudokuViewEdges.left;
        CGFloat tailSpacing = self.sudokuViewEdges.right;
        
        if (viewArray.count < 2) {
            NSAssert(viewArray.count>1,@"views to distribute need to bigger than one");
            return;
        }
        if (warpCount < 1) {
            NSAssert(false, @"warp count need to bigger than zero");
            return;
        }
        
        UIView *tempSuperView = [self star_commonSuperviewOfViews: viewArray];
        
        NSInteger rowCount = viewArray.count % warpCount == 0 ? viewArray.count / warpCount : viewArray.count / warpCount + 1;
        
        UIView *prev;
        for (int i = 0; i < viewArray.count; i++) {
            
            UIView *v = viewArray[i];
            
            // 当前行
            NSInteger currentRow = i / warpCount;
            // 当前列
            NSInteger currentColumn = i % warpCount;
            
            [v mas_makeConstraints:^(MASConstraintMaker *make) {
                // 固定宽度
                make.width.equalTo(@(fixedItemWidth));
                make.height.equalTo(@(fixedItemHeight));
                
                // 第一行
                if (currentRow == 0) {
                    make.top.equalTo(tempSuperView).offset(topSpacing);
                }
                // 最后一行
                if (currentRow == rowCount - 1) {
                    make.bottom.equalTo(tempSuperView).offset(-bottomSpacing);
                }
                // 中间的若干行
                if (currentRow != 0 && currentRow != rowCount - 1){
                    CGFloat offset = (1-(currentRow/((CGFloat)rowCount-1)))*(fixedItemHeight+topSpacing)-currentRow*bottomSpacing/(((CGFloat)rowCount-1));
                    make.bottom.equalTo(tempSuperView).multipliedBy(currentRow/((CGFloat)rowCount-1)).offset(offset);
                }
                
                // 第一列
                if (currentColumn == 0) {
                    make.left.equalTo(tempSuperView).offset(leadSpacing);
                }
                // 最后一列
                if (currentColumn == warpCount - 1) {
                    make.right.equalTo(tempSuperView).offset(-tailSpacing);
                }
                // 中间若干列
                if (currentColumn != 0 && currentColumn != warpCount - 1) {
                    CGFloat offset = (1-(currentColumn/((CGFloat)warpCount-1)))*(fixedItemWidth+leadSpacing)-currentColumn*tailSpacing/(((CGFloat)warpCount-1));
                    make.right.equalTo(tempSuperView).multipliedBy(currentColumn/((CGFloat)warpCount-1)).offset(offset);
                }
            }];
            prev = v;
        }
    }
    
    // MARK: handle event
    
    
    // MARK: properties get && set
    - (PYLayoutSudokuViewHandler *(^)(CGSize fixedItemSize)) setUpFixedItemSize {
        return ^(CGSize fixedItemSize) {
            self.fixedItemSize = fixedItemSize;
            return self;
        };
    }
    - (PYLayoutSudokuViewHandler *(^)(CGSize fixedItemSpacing)) setUpFixedItemSpacing {
        return ^(CGSize fixedItemSpacing) {
            self.fixedItemSpacing = fixedItemSpacing;
            return self;
        };
    }
    - (PYLayoutSudokuViewHandler *(^)(NSInteger warpCount)) setUpWarpCount {
        return ^(NSInteger warpCount) {
            self.warpCount = warpCount;
            return self;
        };
    }
    - (PYLayoutSudokuViewHandler *(^)(UIEdgeInsets sudokuViewEdges)) setUpSudokuViewEdges {
        return ^(UIEdgeInsets sudokuViewEdges) {
            self.sudokuViewEdges = sudokuViewEdges;
            return self;
        };
    }
    
    
    
    // MARK:life cycles
    
    @end
    
    

    相关文章

      网友评论

          本文标题:OC_九宫格布局工具

          本文链接:https://www.haomeiwen.com/subject/napofqtx.html