zoukankan      html  css  js  c++  java
  • 瀑布流

    LWTWaterFlowView.h

     1 //
     2 //  LWTWaterFlowView.h
     3 //  瀑布流
     4 //
     5 //  Created by apple on 14-7-29.
     6 //  Copyright (c) 2014年 lwt. All rights reserved.
     7 //
     8 
     9 #import <UIKit/UIKit.h>
    10 
    11 typedef enum {
    12     LWTWaterFlowViewMarginTypeTop, //
    13     LWTWaterFlowViewMarginTypeLeft, //
    14     LWTWaterFlowViewMarginTypeBotton, //
    15     LWTWaterFlowViewMarginTypeRight, //
    16     LWTWaterFlowViewMarginTypeRow, //
    17     LWTWaterFlowViewMarginTypeColumn, //
    18 } LWTWaterFlowViewMarginType;
    19 
    20 @class LWTWaterFlowView, LWTWaterFlowViewCell;
    21 /**
    22  *  瀑布流数据源
    23  */
    24 @protocol LWTWaterFlowViewDataSource <NSObject>
    25 
    26 /**
    27  *  有多少个数据
    28  */
    29 - (NSUInteger)numberOfCellInWaterFlowView:(LWTWaterFlowView *)waterFlowView;
    30 
    31 /**  返回index位置对应的cell */
    32 - (LWTWaterFlowViewCell *)waterFlowView:(LWTWaterFlowView *)waterFlowView cellAtIndex:(NSUInteger)index;
    33 @optional
    34 /**  一共有多少列 */
    35 - (NSUInteger)numberOfColumnsInWaterFlowView:(LWTWaterFlowView *)waterFlowView;
    36 @end
    37 
    38 /**
    39  *  瀑布流代理
    40  */
    41 @protocol LWTWaterFlowViewDelegate <UIScrollViewDelegate>
    42 @optional
    43 /**  第index位置cell对应的高度 */
    44 - (CGFloat)waterFlowView:(LWTWaterFlowView *)waterFlowView heightForCellAtIndex:(NSUInteger)index;
    45 
    46 /**  选中第index位置的cell */
    47 - (void)waterFlowView:(LWTWaterFlowView *)waterFlowView didSelectForCellAtIndex:(NSUInteger)index;
    48 /**
    49  *  间距
    50  */
    51 - (CGFloat)waterFlowView:(LWTWaterFlowView *)waterFlowView marginForType:(LWTWaterFlowViewMarginType)type;
    52 @end
    53 
    54 @interface LWTWaterFlowView : UIScrollView
    55 /**
    56  *  数据源
    57  */
    58 @property (nonatomic, weak) id<LWTWaterFlowViewDataSource> dataSource;
    59 
    60 /**
    61  *  代理
    62  */
    63 @property (nonatomic, weak) id<LWTWaterFlowViewDelegate> delegate;
    64 
    65 /**
    66  *  刷新数据(只要调用这个方法,会重新向数据源和代理发送请求,请求数据)
    67  */
    68 - (void)reloadData;
    69 
    70 /**
    71  *  cell的宽度
    72  */
    73 - (CGFloat)cellWidth;
    74 
    75 /**
    76  *  根据标识去缓存池查找可循环利用的cell
    77  */
    78 - (id) dequeueReusableCellWithIdentifier:(NSString *)identifier;
    79 
    80 @end
    View Code

    LWTWaterFlowView.m

      1 //
      2 //  LWTWaterFlowView.m
      3 //  瀑布流
      4 //
      5 //  Created by apple on 14-7-29.
      6 //  Copyright (c) 2014年 lwt. All rights reserved.
      7 //
      8 
      9 #import "LWTWaterFlowView.h"
     10 #import "LWTWaterFlowViewCell.h"
     11 
     12 #define KWaterflowViewDefaultCellH 70
     13 #define KWaterflowViewDefaultMargin 8
     14 #define KWaterflowViewDefaultNumberOfColumns 3
     15 
     16 @interface LWTWaterFlowView ()
     17 /**
     18  *  所有cell的frame数据
     19  */
     20 @property (nonatomic, strong) NSMutableArray *cellFrames;
     21 /**
     22  *  正在展示的cell
     23  */
     24 @property (nonatomic, strong) NSMutableDictionary *displayCells;
     25 /**
     26  *  缓存池(用Set,存放离开屏幕的cell)
     27  */
     28 @property (nonatomic, strong) NSMutableSet *reusableCells;
     29 @end
     30 
     31 @implementation LWTWaterFlowView
     32 #pragma mark - 初始化
     33 - (NSMutableArray *)cellFrames
     34 {
     35     if (nil == _cellFrames) {
     36         _cellFrames = [NSMutableArray array];
     37     }
     38     return _cellFrames;
     39 }
     40 
     41 - (NSMutableDictionary *)displayCells
     42 {
     43     if (nil == _displayCells) {
     44         _displayCells = [NSMutableDictionary dictionary];
     45     }
     46     return _displayCells;
     47 }
     48 
     49 - (NSMutableSet *)reusableCells
     50 {
     51     if (nil == _reusableCells) {
     52         _reusableCells = [NSMutableSet set];
     53     }
     54     return _reusableCells;
     55 }
     56 
     57 - (void)willMoveToSuperview:(UIView *)newSuperview
     58 {
     59     [self reloadData];
     60 }
     61 
     62 #pragma mark - 公共接口
     63 
     64 - (void)reloadData
     65 {
     66     // 清空之前的所有数据
     67     // 移除正在正在显示cell
     68     [self.displayCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)];
     69     [self.displayCells removeAllObjects];
     70     [self.cellFrames removeAllObjects];
     71     [self.reusableCells removeAllObjects];
     72     
     73     // cell的总数
     74     int numbersOfCell = [self.dataSource numberOfCellInWaterFlowView:self];
     75     
     76     // 总列数
     77     int numberOfColumns = [self numberOfColumns];
     78     // 间距
     79     CGFloat topMargin = [self marginForType:LWTWaterFlowViewMarginTypeTop];
     80     CGFloat leftMargin = [self marginForType:LWTWaterFlowViewMarginTypeLeft];
     81     CGFloat bottomMargin = [self marginForType:LWTWaterFlowViewMarginTypeBotton];
     82     CGFloat rowMargin = [self marginForType:LWTWaterFlowViewMarginTypeRow];
     83     CGFloat columnMargin = [self marginForType:LWTWaterFlowViewMarginTypeColumn];
     84     
     85     // cell的宽度
     86     CGFloat cellWidth = [self cellWidth];
     87     
     88     // 用一个C语言数组存放所有列的最大Y值
     89     CGFloat maxYOfColumns[numberOfColumns];
     90     for (int i = 0; i<numberOfColumns; i++) {
     91         maxYOfColumns[i] = 0.0;
     92     }
     93     
     94     // 计算所有cell的frame
     95     for (int i = 0; i < numbersOfCell ; i++) {
     96         // cell的高度
     97         CGFloat cellHeight = [self heightAtIndex:i];
     98         
     99         // cell处在第几列(最短的一列)
    100         NSUInteger cellColumn = 0;
    101         // cell所处那列的最大的Y值(最短那一列的最大的Y值)
    102         NSUInteger maxYOfCellColumn = maxYOfColumns[cellColumn];
    103         // 求出最短的一列
    104         for (int j = 1 ; j < numberOfColumns; j++) {
    105             if (maxYOfColumns[j] < maxYOfCellColumn) {
    106                 cellColumn = j;
    107                 maxYOfCellColumn = maxYOfColumns[j];
    108             }
    109         }
    110         
    111         CGFloat cellX = leftMargin + (cellWidth + columnMargin) * cellColumn;
    112         
    113         CGFloat cellY = 0;
    114         if (maxYOfCellColumn == 0.0) {  // 首行
    115             cellY = topMargin;
    116         } else {
    117             cellY = maxYOfCellColumn + rowMargin;
    118         }
    119         
    120         CGRect cellFrame = CGRectMake(cellX, cellY, cellWidth, cellHeight);
    121         [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]];
    122         
    123         maxYOfColumns[cellColumn] = CGRectGetMaxY(cellFrame);
    124     }
    125     
    126     // 设置contentSize
    127     CGFloat contentH = maxYOfColumns[0];
    128     for (int j = 1 ; j < numberOfColumns; j++) {
    129         if (maxYOfColumns[j] > contentH) {
    130             contentH = maxYOfColumns[j];
    131         }
    132     }
    133     self.contentSize = CGSizeMake(0, contentH + bottomMargin);
    134     
    135     
    136 }
    137 
    138 /**
    139  *  当UIScrollView滚动的时候也会调用这个方法
    140  */
    141 - (void)layoutSubviews
    142 {
    143     [super layoutSubviews];
    144     
    145     int numberOfCell = self.cellFrames.count;
    146     
    147     // 向数据源索要对应位置的cell
    148     for (int i = 0; i<numberOfCell; i++) {
    149         // 取出i位置的frame
    150         CGRect cellFrame = [self.cellFrames[i] CGRectValue];
    151         
    152         // 优先从字典中取出i位置的cell
    153         LWTWaterFlowViewCell *cell = self.displayCells[@(i)];
    154         
    155         // 判断i位置对应的frame在不在屏幕上(能否看见)
    156         if ([self isInScreen:cellFrame]) {
    157             if (cell == nil) {  // 在屏幕上
    158                 cell = [self.dataSource waterFlowView:self cellAtIndex:i];
    159                 cell.frame = cellFrame;
    160                 [self addSubview:cell];
    161                 
    162                 // 存放到字典中
    163                 [self.displayCells setObject:cell forKey:@(i)];
    164             }
    165         } else {   // 不在屏幕上
    166             if (cell) {
    167                 // 存放进缓存池
    168                 [self.reusableCells addObject:cell];
    169                 
    170                 // 从scrollView和字典中移除
    171                 [self.displayCells removeObjectForKey:@(i)];
    172                 [cell removeFromSuperview];
    173             }
    174         }
    175     }
    176 }
    177 
    178 /**
    179  *  cell的宽度
    180  */
    181 - (CGFloat)cellWidth
    182 {
    183     // 总列数
    184     int numberOfColumns = [self numberOfColumns];
    185     CGFloat leftMargin = [self marginForType:LWTWaterFlowViewMarginTypeLeft];
    186     CGFloat rightMargin = [self marginForType:LWTWaterFlowViewMarginTypeRight];
    187     CGFloat columnMargin = [self marginForType:LWTWaterFlowViewMarginTypeColumn];
    188     
    189     return (self.bounds.size.width - leftMargin - rightMargin - (numberOfColumns - 1) * columnMargin) / numberOfColumns;
    190 }
    191 
    192 - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
    193 {
    194     __block LWTWaterFlowViewCell *reusableCell = nil;
    195     [self.reusableCells enumerateObjectsUsingBlock:^(LWTWaterFlowViewCell *cell, BOOL *stop) {
    196         if ([cell.identifier isEqualToString:identifier]) {
    197             reusableCell = cell;
    198             *stop = YES;
    199         }
    200     }];
    201     
    202     if (reusableCell) {  // 从缓存池中移除
    203         [self.reusableCells removeObject:reusableCell];
    204     }
    205     
    206     return reusableCell;
    207 }
    208 #pragma mark - 私有方法
    209 - (BOOL)isInScreen:(CGRect)frame
    210 {
    211     return (CGRectGetMaxY(frame) > self.contentOffset.y) && (CGRectGetMinY(frame) < (self.contentOffset.y + self.bounds.size.height));
    212 }
    213 
    214 /**
    215  *  获取总列数
    216  */
    217 - (NSUInteger)numberOfColumns
    218 {
    219     if ([self.dataSource respondsToSelector:@selector(numberOfColumnsInWaterFlowView:)]) {
    220         return [self.dataSource numberOfColumnsInWaterFlowView:self];
    221     } else {
    222         return KWaterflowViewDefaultNumberOfColumns;
    223     }
    224 }
    225 
    226 /**
    227  *  获取间距
    228  */
    229 - (CGFloat)marginForType:(LWTWaterFlowViewMarginType)type
    230 {
    231     if ([self.delegate respondsToSelector:@selector(waterFlowView:marginForType:)]) {
    232         return [self.delegate waterFlowView:self marginForType:type];
    233     } else {
    234         return KWaterflowViewDefaultMargin;
    235     }
    236 }
    237 
    238 /**
    239  *  index位置对应cell的高度
    240  */
    241 - (CGFloat)heightAtIndex:(NSUInteger)index
    242 {
    243     if ([self.delegate respondsToSelector:@selector(waterFlowView:heightForCellAtIndex:)]) {
    244         return [self.delegate waterFlowView:self heightForCellAtIndex:index];
    245     } else {
    246         return KWaterflowViewDefaultCellH;
    247     }
    248 }
    249 
    250 
    251 #pragma mark - 事件处理
    252 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    253 {
    254     if (![self.delegate respondsToSelector:@selector(waterFlowView:didSelectForCellAtIndex:)]) return;
    255     
    256     // 获得触摸点
    257     UITouch *touch = [touches anyObject];
    258     CGPoint point = [touch locationInView:self];
    259     
    260     __block NSNumber *selectedIndex = nil;
    261     [self.displayCells enumerateKeysAndObjectsUsingBlock:^(id key, LWTWaterFlowViewCell *cell, BOOL *stop) {
    262         if (CGRectContainsPoint(cell.frame, point)) {
    263             selectedIndex = key;
    264             *stop = YES;
    265         }
    266     }];
    267     
    268     if (selectedIndex) {
    269         NSUInteger number = selectedIndex.unsignedIntegerValue;
    270         [self.delegate waterFlowView:self didSelectForCellAtIndex:number];
    271     }
    272 }
    273 
    274 @end
    View Code

    LWTWaterFlowViewCell.h

    //
    //  LWTWaterFlowViewCell.h
    //  瀑布流
    //
    //  Created by apple on 14-7-29.
    //  Copyright (c) 2014年 lwt. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface LWTWaterFlowViewCell : UIView
    @property (nonatomic, copy) NSString *identifier;
    
    - (instancetype)initWithIdentifier:(NSString *)identifier;
    
    @end
    View Code

    LWTWaterFlowViewCell.m

    //
    //  LWTWaterFlowViewCell.m
    //  瀑布流
    //
    //  Created by apple on 14-7-29.
    //  Copyright (c) 2014年 lwt. All rights reserved.
    //
    
    #import "LWTWaterFlowViewCell.h"
    
    @implementation LWTWaterFlowViewCell
    
    - (id)initWithIdentifier:(NSString *)identifier
    {
        self = [super init];
        if (self) {
            self.identifier = identifier;
        }
        return self;
    }
    @end
    View Code
  • 相关阅读:
    地图瓦片PNG8格式理解
    python gdal3.0安装记录
    gdal------坐标转换记录
    地图切片(加载)原理资料收集与整理
    cesium学习笔记001
    设计模式学习——观察者模式(c++)
    javascript的数组方法
    git的基本使用
    keep-alive
    防抖函数
  • 原文地址:https://www.cnblogs.com/wentianblog/p/3878752.html
Copyright © 2011-2022 走看看