• iOS日历控件


    项目需要,前一阵子重构了下iPad工程,添加了一个滚动无缝日历。

    当时没有头绪,网上找了一个源码改吧改吧就上线了(参考链接),这个功能很多而且流畅性也特别好,推荐不会写的可以参考下。

    这几天,活不太忙就把日历控件裁剪了下,做个最简单的滚动无缝日历。效果如下图:

    日历可以左右滚动,点击某个日期后会变色,并且有回调。橘色的是标记日期,蓝色的是选择日期,蓝边的是当前日期,可以根据需要自行更改。

    这个日历控件有两个比较复杂的地方:

    • UICollectionView默认情况下,横滚cell竖排竖滚cell横排,所以我们先要修改下cell的位置,自定义FlowLayout继承于UICollectionViewFlowLayout,重写它的prepareLayout方法。
      #import "EXCalendarCollectionViewFlowLayout.h"
      
      @interface EXCalendarCollectionViewFlowLayout ()
      
      @property (nonatomic, strong) NSMutableArray *allAttributes;
      
      @end
      
      
      @implementation EXCalendarCollectionViewFlowLayout
      
      - (void)prepareLayout {
          [super prepareLayout];
          
          self.allAttributes = [NSMutableArray array];
          
          NSInteger sections = [self.collectionView numberOfSections];
          for (int i = 0; i < sections; i++) {
              
              // setup one section attributes.
              NSMutableArray *tmpArray = [NSMutableArray array];
              
              NSInteger count = [self.collectionView numberOfItemsInSection:i];
              
              for (NSInteger j = 0; j < count; j++) {
                  NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:i];
                  UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
                  [tmpArray addObject:attributes];
              }
              
              [self.allAttributes addObject:tmpArray];
          }
      }
      
      
      - (CGSize)collectionViewContentSize {
          return [super collectionViewContentSize];
      }
      
      
      - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
          NSInteger item = indexPath.item;
          NSInteger x;
          NSInteger y;
          
          // 根据item的序号计算出item的行列位置
          [self targetPositionWithItem:item resultX:&x resultY:&y];
          
          // 根据已得出的item的行列位置,将item放入indexPath中对应的位置。
          NSInteger item2 =  [self orignItemAtX:x y:y];
          NSIndexPath *theNewIndexPath = [NSIndexPath indexPathForItem:item2 inSection:indexPath.section];
          
          UICollectionViewLayoutAttributes *theNewAttr = [super layoutAttributesForItemAtIndexPath:theNewIndexPath];
          theNewAttr.indexPath = indexPath;
          return theNewAttr;
      }
      
      
      - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
          NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
          
          NSMutableArray *tmp = [NSMutableArray array];
          
          for (UICollectionViewLayoutAttributes *attr in attributes) {
              for (NSMutableArray *attributes in self.allAttributes)
              {
                  for (UICollectionViewLayoutAttributes *attr2 in attributes) {
                      if (attr.indexPath.item == attr2.indexPath.item) {
                          [tmp addObject:attr2];
                          break;
                      }
                  }
                  
              }
          }
          return tmp;
      }
      
      
      // 根据item计算目标item的位置。
      - (void)targetPositionWithItem:(NSInteger)item
                             resultX:(NSInteger *)x
                             resultY:(NSInteger *)y {
          //    NSInteger page = item / (self.itemCountPerRow * self.rowCountPerPage);
          
          NSInteger theX = item % self.itemCountPerRow;
          NSInteger theY = item / self.itemCountPerRow;
          
          if (x != NULL) {
              *x = theX;
          }
          
          if (y != NULL) {
              *y = theY;
          }
      }
      
      
      - (NSInteger)orignItemAtX:(NSInteger)x
                              y:(NSInteger)y {
          NSInteger item = x * self.rowCountPerPage + y;
          return item;
      }
      
      
      @end
      View Code

    • 当你在当前月份点击了一个日期,滑到其他月份,然后要对刚才选择的月份的效果进行更改时,比较麻烦。刚开始我在didSelectItemAtIndexPath委托方法中用cellForItemAtIndexPath进行获取时,不可见的cell获取不到返回的是空,然后在如何获取不可见的cell问题上纠结了两天,最终换了个解决方案,在cellForItemAtIndexPath中进行了判断,解决了这个问题,当然点击后直接有响应跳转的话,刚才这个功能就很鸡肋了。具体看代码吧。

    源码地址:https://github.com/zhanghua0926/EXCalendar

  • 相关阅读:
    JSON的一个例子(代码来源于网上)
    浅谈Event Flow、Process、Method及其Applications
    JS中object与constructor的分析
    浅谈for...in与for....of
    浅谈语言的过去与未来
    正则表达式的四个小应用
    初步了解DOM与BOM
    String Method的字符串变换的一个例子
    update 批量更新
    一个 Tomcat下两个项目。
  • 原文地址:https://www.cnblogs.com/xuanyishare/p/10615624.html
Copyright © 2020-2023  润新知