应该使用什么方法在选择时动态更改 UICollectionViewCell 的大小?
What method should be used to dynamically change the size of UICollectionViewCell on selection?
我需要做的是加宽一个单元格的宽度 selected 并同时缩短其余未 selected 的单元格的宽度,以便所有单元格都是显示一次。
我现在拥有的是:
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
}
我在子类 UIView 中有一个 水平 UICollectionView 设置,有 30 个单元格,它们被平均分配。
为了 select 通过检测手势的单元格,我将 UIPanGestureRecognizer 添加到 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
}
}
此外,我有 UICollectionViewCell 的子类,我实际上可以通过以下代码更改 selected 单元格的宽度:
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
})
}
}
}
当然,它只能更改一个单元格 selected。我需要做的是改变一个单元格selected的宽度,然后根据selected单元格重新计算其他单元格的宽度。
为了再次澄清我的问题,我想做的是:
- 假设 UICollectionView.width 是 300
- 它有 30 个单元格,Cell.width 是 300/30 = 10
- 所有单元格必须一次显示,UICollectionView 不滚动。
- select编辑单元格时,其宽度将为 20。
- 因此其他单元格的宽度将为 (300-20)/29。
我应该hook什么方法或函数?最好是简单的示例代码,在此先感谢。
我觉得子类化 UICollectionViewFlowLayout 会更 suitable/scalable 解决您的问题。
下面我分享了子类化时的小代码UICollectionViewLayout
所以你会得到一般的想法。
将 totalItem 添加到您的子类中。
以及指示正在选择哪个单元格的索引路径。
在您的 collectionview
上选择一个单元格调用后 invalidatelayout
在您的情况下,您希望每次都计算单元格的所有属性。
这是粗略的草图,未经测试可能有一些计算错误
- (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;
}
我需要做的是加宽一个单元格的宽度 selected 并同时缩短其余未 selected 的单元格的宽度,以便所有单元格都是显示一次。
我现在拥有的是:
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
}
我在子类 UIView 中有一个 水平 UICollectionView 设置,有 30 个单元格,它们被平均分配。
为了 select 通过检测手势的单元格,我将 UIPanGestureRecognizer 添加到 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
}
}
此外,我有 UICollectionViewCell 的子类,我实际上可以通过以下代码更改 selected 单元格的宽度:
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
})
}
}
}
当然,它只能更改一个单元格 selected。我需要做的是改变一个单元格selected的宽度,然后根据selected单元格重新计算其他单元格的宽度。
为了再次澄清我的问题,我想做的是:
- 假设 UICollectionView.width 是 300
- 它有 30 个单元格,Cell.width 是 300/30 = 10
- 所有单元格必须一次显示,UICollectionView 不滚动。
- select编辑单元格时,其宽度将为 20。
- 因此其他单元格的宽度将为 (300-20)/29。
我应该hook什么方法或函数?最好是简单的示例代码,在此先感谢。
我觉得子类化 UICollectionViewFlowLayout 会更 suitable/scalable 解决您的问题。
下面我分享了子类化时的小代码UICollectionViewLayout
所以你会得到一般的想法。
将 totalItem 添加到您的子类中。 以及指示正在选择哪个单元格的索引路径。 在您的 collectionview
上选择一个单元格调用后invalidatelayout
在您的情况下,您希望每次都计算单元格的所有属性。
这是粗略的草图,未经测试可能有一些计算错误
- (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;
}