What method should be used to dynamically change t

2019-09-07 21:02发布

问题:

What I need to do is to widen the width of a cell selected and at the same time shorten widths of the rest of the cells not selected so that all the cells are shown in one time.

What I have now are:

  func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 30
  }
  func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: collectionView.bounds.width / 30, height: collectionView.bounds.height)
  }
  func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell: UIDateSliderCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as UIDateSliderCell
    return cell
  }

I have a horizontal UICollectionView setup in subclassed UIView, with 30 cells and they're divided equally.

To select a cell by detecting gestures, I have UIPanGestureRecognizer added to collectionView.

  func pan(sender: UIPanGestureRecognizer) {
    switch sender.state {
    case .Began:
      fallthrough
    case .Changed:
    _collectionView.selectItemAtIndexPath(_collectionView.indexPathForItemAtPoint(CGPointMake(sender.locationInView(_collectionView).x, 0.0)), animated: true, scrollPosition: nil)
    case .Ended:
      break
    default:
      break
    }
  }

Additionally, I have UICollectionViewCell subclassed and I can actually change the width of selected cell by this code:

  override var selected: Bool {
    didSet {

      if selected {        
        UIView.animateWithDuration(1.0,
          delay: 0.0,
          usingSpringWithDamping: 0.5,
          initialSpringVelocity: 1.0,
          options: .CurveEaseIn,
          animations: { () -> Void in
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width*2, self.frame.size.height)
          },
          completion: { (finished: Bool) -> Void in
        })
      }
    }
  } 

But of course with this it can only change a cell selected. What I need to do is to change the width of one cell selected and recalculate the widths of other cells according to the selected cell.

To clarify my question again, what I'd like to do is this:

  1. Let's say UICollectionView.width is 300
  2. It has 30 cells and Cell.width is 300/30 = 10
  3. All the cells have to be shown at one time, UICollectionView doesn't scroll.
  4. When a cell is selected its width will be 20.
  5. Therefore other cells' width will be (300-20)/29.

What method or functions should I hook? Preferbly simple sample codes please, thanks a lot in advance.

回答1:

I feel like subclassing UICollectionViewFlowLayout would be a more suitable/scalable solution for your problem.

Below I shared small code when subclassing UICollectionViewLayout So you'll get the general Idea.

add totalItem to your subclass. and a indexpath that indicates which cell is being selected. after selecting a cell call invalidatelayout on your collectionview

in your case you want to calculate all the cell's attributes every time.

This is rough sketch and have not been tested probably has some calculation mistakes

    - (void)prepareLayout {

        self.totalItems = (int)[self.collectionView numberOfItemsInSection:0];

    }

    - (CGSize)collectionViewContentSize
    {
        return self.collectionView.frame.size;
    }



    -(CGRect) rectForIndex:(int) index {
        //Here you should calculate the sizes of all the cells
        // The ones before the selected one , the selected one, and the ones after the selected
        if (index<selected) {
           //Regular calculating
           frame=CGRectMake(0, height * index, width, height)
        } else if (index>selected) {
          //here the tricky part is the origin you ( assuming one is seleceted) you calculate the accumulated height of index-1 regular cells and 1 selected cell  
           frame=CGRectMake(0, (height* (selected-1) + sizeOfSelectedCell) +height * (index-selected), width, height)
        } else {
           frame=CGRectMake(0, (height* (index-selected)) , width, selectedHeight)
}
        return frame;
    }
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {

        NSMutableArray *attributes = [NSMutableArray array];
        for (int i = 0; i<  self.totalItems; i++) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
            [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
        }
    return attributes;
    }




    -(UICollectionViewLayoutAttributes *) layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
        UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

        attributes.frame = [self rectForIndex:(int)indexPath.row];


        return attributes;
    }