gpt4 book ai didi

ios - 在 iOS 7 上创建类似 Evernote 的弹性 UICollectionView

转载 作者:可可西里 更新时间:2023-11-01 04:46:53 24 4
gpt4 key购买 nike

我一直在尝试重新创建 Evernote 在 iOS 7 中使用的弹性 Collection View ,我真的很接近让它正常工作。我设法创建了一个自定义 Collection View 流布局,当内容偏移 y 值位于 Collection View 边界之外时,它修改了布局属性转换。我正在修改 layoutAttributesForElementsInRect 方法中的布局属性,它的行为符合预期,只是当您点击 ScrollView 底部时底部单元格会消失。您将内容偏移量拉得越远,就会有更多的单元格消失。我认为细胞基本上被剪掉了。虽然它不会发生在顶部,但我希望在这两个地方看到相同的行为。这是我的流布局实现现在的样子。

@implementation CNStretchyCollectionViewFlowLayout
{
BOOL _transformsNeedReset;
CGFloat _scrollResistanceDenominator;
}

- (id)init
{
self = [super init];
if (self)
{
// Set up the flow layout parameters
self.minimumInteritemSpacing = 10;
self.minimumLineSpacing = 10;
self.itemSize = CGSizeMake(320, 44);
self.sectionInset = UIEdgeInsetsMake(10, 0, 10, 0);

// Set up ivars
_transformsNeedReset = NO;
_scrollResistanceDenominator = 800.0f;
}

return self;
}

- (void)prepareLayout
{
[super prepareLayout];
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
// Set up the default attributes using the parent implementation
NSArray *items = [super layoutAttributesForElementsInRect:rect];

// Compute whether we need to adjust the transforms on the cells
CGFloat collectionViewHeight = self.collectionViewContentSize.height;
CGFloat topOffset = 0.0f;
CGFloat bottomOffset = collectionViewHeight - self.collectionView.frame.size.height;
CGFloat yPosition = self.collectionView.contentOffset.y;

// Update the transforms if necessary
if (yPosition < topOffset)
{
// Compute the stretch delta
CGFloat stretchDelta = topOffset - yPosition;
NSLog(@"Stretching Top by: %f", stretchDelta);

// Iterate through all the visible items for the new bounds and update the transform
for (UICollectionViewLayoutAttributes *item in items)
{
CGFloat distanceFromTop = item.center.y;
CGFloat scrollResistance = distanceFromTop / 800.0f;
item.transform = CGAffineTransformMakeTranslation(0, -stretchDelta + (stretchDelta * scrollResistance));
}

// Update the ivar for requiring a reset
_transformsNeedReset = YES;
}
else if (yPosition > bottomOffset)
{
// Compute the stretch delta
CGFloat stretchDelta = yPosition - bottomOffset;
NSLog(@"Stretching bottom by: %f", stretchDelta);

// Iterate through all the visible items for the new bounds and update the transform
for (UICollectionViewLayoutAttributes *item in items)
{
CGFloat distanceFromBottom = collectionViewHeight - item.center.y;
CGFloat scrollResistance = distanceFromBottom / 800.0f;
item.transform = CGAffineTransformMakeTranslation(0, stretchDelta + (-stretchDelta * scrollResistance));
}

// Update the ivar for requiring a reset
_transformsNeedReset = YES;
}
else if (_transformsNeedReset)
{
NSLog(@"Resetting transforms");
_transformsNeedReset = NO;
for (UICollectionViewLayoutAttributes *item in items)
item.transform = CGAffineTransformIdentity;
}

return items;
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
// Compute whether we need to adjust the transforms on the cells
CGFloat collectionViewHeight = self.collectionViewContentSize.height;
CGFloat topOffset = 0.0f;
CGFloat bottomOffset = collectionViewHeight - self.collectionView.frame.size.height;
CGFloat yPosition = self.collectionView.contentOffset.y;

// Handle cases where the layout needs to be rebuilt
if (yPosition < topOffset)
return YES;
else if (yPosition > bottomOffset)
return YES;
else if (_transformsNeedReset)
return YES;

return NO;
}

@end

我还压缩了项目供人们试用。任何帮助将不胜感激,因为我对创建自定义 Collection View 布局还很陌生。这是它的链接:

https://dl.dropboxusercontent.com/u/2975688/StackOverflow/stretchy_collection_view.zip

谢谢大家!

最佳答案

我能够解决问题。我不确定 iOS 中是否真的存在错误,但问题是单元格实际上是在 Collection View 的内容 View 之外进行翻译的。一旦细胞被翻译得足够远,它就会被剪掉。我发现有趣的是,这不会发生在非视网膜显示器的模拟器中,但会发生在视网膜显示器上,这就是为什么我觉得这实际上可能是一个错误。

考虑到这一点,目前的解决方法是通过覆盖 collectionViewContentSize 方法向 Collection View 的顶部和底部添加填充。执行此操作后,如果在顶部添加填充,则还需要调整单元格的布局属性,以便它们位于正确的位置。最后一步是在 Collection View 本身上设置 contentInset 以调整填充。单独留下滚动指示器插图,因为它们很好。这是我最终的 Collection View Controller 和自定义流布局的实现。

CNStretchyCollectionViewController.m

@implementation CNStretchyCollectionViewController

static NSString *CellIdentifier = @"Cell";

- (void)viewDidLoad
{
// Register the cell
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:CellIdentifier];

// Tweak out the content insets
CNStretchyCollectionViewFlowLayout *layout = (CNStretchyCollectionViewFlowLayout *) self.collectionViewLayout;
self.collectionView.contentInset = layout.bufferedContentInsets;

// Set the delegate for the collection view
self.collectionView.delegate = self;
self.collectionView.clipsToBounds = NO;

// Customize the appearance of the collection view
self.collectionView.backgroundColor = [UIColor whiteColor];
self.collectionView.indicatorStyle = UIScrollViewIndicatorStyleDefault;
}

#pragma mark - UICollectionViewDataSource Methods

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 20;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
if ([indexPath row] % 2 == 0)
cell.backgroundColor = [UIColor orangeColor];
else
cell.backgroundColor = [UIColor blueColor];

return cell;
}

@end

CNStretchyCollectionViewFlowLayout.m

@interface CNStretchyCollectionViewFlowLayout ()

- (CGSize)collectionViewContentSizeWithoutOverflow;

@end

#pragma mark -

@implementation CNStretchyCollectionViewFlowLayout
{
BOOL _transformsNeedReset;
CGFloat _scrollResistanceDenominator;
UIEdgeInsets _contentOverflowPadding;
}

- (id)init
{
self = [super init];
if (self)
{
// Set up the flow layout parameters
self.minimumInteritemSpacing = 10;
self.minimumLineSpacing = 10;
self.itemSize = CGSizeMake(320, 44);
self.sectionInset = UIEdgeInsetsMake(10, 0, 10, 0);

// Set up ivars
_transformsNeedReset = NO;
_scrollResistanceDenominator = 800.0f;
_contentOverflowPadding = UIEdgeInsetsMake(100.0f, 0.0f, 100.0f, 0.0f);
_bufferedContentInsets = _contentOverflowPadding;
_bufferedContentInsets.top *= -1;
_bufferedContentInsets.bottom *= -1;
}

return self;
}

- (void)prepareLayout
{
[super prepareLayout];
}

- (CGSize)collectionViewContentSize
{
CGSize contentSize = [super collectionViewContentSize];
contentSize.height += _contentOverflowPadding.top + _contentOverflowPadding.bottom;
return contentSize;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
// Set up the default attributes using the parent implementation (need to adjust the rect to account for buffer spacing)
rect = UIEdgeInsetsInsetRect(rect, _bufferedContentInsets);
NSArray *items = [super layoutAttributesForElementsInRect:rect];

// Shift all the items down due to the content overflow padding
for (UICollectionViewLayoutAttributes *item in items)
{
CGPoint center = item.center;
center.y += _contentOverflowPadding.top;
item.center = center;
}

// Compute whether we need to adjust the transforms on the cells
CGFloat collectionViewHeight = [self collectionViewContentSizeWithoutOverflow].height;
CGFloat topOffset = _contentOverflowPadding.top;
CGFloat bottomOffset = collectionViewHeight - self.collectionView.frame.size.height + _contentOverflowPadding.top;
CGFloat yPosition = self.collectionView.contentOffset.y;

// Update the transforms if necessary
if (yPosition < topOffset)
{
// Compute the stretch delta
CGFloat stretchDelta = topOffset - yPosition;
NSLog(@"Stretching Top by: %f", stretchDelta);

// Iterate through all the visible items for the new bounds and update the transform
for (UICollectionViewLayoutAttributes *item in items)
{
CGFloat distanceFromTop = item.center.y - _contentOverflowPadding.top;
CGFloat scrollResistance = distanceFromTop / _scrollResistanceDenominator;
item.transform = CGAffineTransformMakeTranslation(0, -stretchDelta + (stretchDelta * scrollResistance));
}

// Update the ivar for requiring a reset
_transformsNeedReset = YES;
}
else if (yPosition > bottomOffset)
{
// Compute the stretch delta
CGFloat stretchDelta = yPosition - bottomOffset;
NSLog(@"Stretching bottom by: %f", stretchDelta);

// Iterate through all the visible items for the new bounds and update the transform
for (UICollectionViewLayoutAttributes *item in items)
{
CGFloat distanceFromBottom = collectionViewHeight + _contentOverflowPadding.top - item.center.y;
CGFloat scrollResistance = distanceFromBottom / _scrollResistanceDenominator;
item.transform = CGAffineTransformMakeTranslation(0, stretchDelta + (-stretchDelta * scrollResistance));
}

// Update the ivar for requiring a reset
_transformsNeedReset = YES;
}
else if (_transformsNeedReset)
{
NSLog(@"Resetting transforms");
_transformsNeedReset = NO;
for (UICollectionViewLayoutAttributes *item in items)
item.transform = CGAffineTransformIdentity;
}

return items;
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}

#pragma mark - Private Methods

- (CGSize)collectionViewContentSizeWithoutOverflow
{
return [super collectionViewContentSize];
}

@end

CNStretchyCollectionViewFlowLayout.h

@interface CNStretchyCollectionViewFlowLayout : UICollectionViewFlowLayout

@property (assign, nonatomic) UIEdgeInsets bufferedContentInsets;

@end

实际上,我将把它放到 Github 上,一旦它启动,我会发布一个指向该项目的链接。再次感谢大家!

关于ios - 在 iOS 7 上创建类似 Evernote 的弹性 UICollectionView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19759770/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com