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
  • 相关阅读:
    spring mvc给参数起别名
    聊聊分布式定时任务中间件架构及其实现--转
    Batch Normalization的算法本质是在网络每一层的输入前增加一层BN层(也即归一化层),对数据进行归一化处理,然后再进入网络下一层,但是BN并不是简单的对数据进行求归一化,而是引入了两个参数λ和β去进行数据重构
    终端安全工具 gartner 排名
    When Cyber Security Meets Machine Learning 机器学习 安全分析 对于安全领域的总结很有用 看未来演进方向
    DNS隧道之DNS2TCP实现——dns2tcpc必须带server IP才可以,此外ssh可以穿过墙的,设置代理上网
    DNS隧道之DNS2TCP使用心得教程——是可以用来穿透qiang的,ubuntu下直接apt install dns2tcp
    DNS隧道工具汇总——补充,还有IP over DNS的工具NSTX、Iodine、DNSCat
    Data Mining and Machine Learning in Cybersecurity PDF
    ES failed to notify ClusterStateListener java.lang.IllegalStateException: environment is not locked
  • 原文地址:https://www.cnblogs.com/wentianblog/p/3878752.html
Copyright © 2011-2022 走看看