Я собираюсь создать книжную полку в одном из моих проектов. Основное требование заключается в следующем:
- похож на книжную полку iBooks
- хорошо поддерживает обе ориентации
- хорошо поддерживает все виды устройств iOS (разные разрешения)
- поддерживает удаление и вставку элементов
- поддерживает переупорядочение элементов длинным нажатием
- показывает скрытый логотип, когда первый ряд опущен
UICollectionView - первая опция, которая пришла мне в голову. Он легко поддерживает ячейки сетки. Я нашел его в Google и нашел несколько очень полезных уроков:
Брайан Хансен UICollectionПросмотр учебника по пользовательскому макету
Mark Pospesel Как добавить декоративный вид в UICollectionView
LXReorderableCollectionViewFlowLayout
И вот результат: (Пожалуйста, не обращайте внимания на проблему несоответствия цвета, поскольку выбранная графика еще не идеальна.)
Что я сделал:
- Создал пользовательский макет, создав класс, унаследованный от
LXReorderableCollectionViewFlowLayout
(для целей переупорядочения), который унаследован от UICollectionFlowLayout - Добавлен вид оформления для отображения логотипа
- Добавлен вид оформления для отображения книжных полок
Но я столкнулся с несколькими проблемами:
1. Я не могу прокручивать вообще, если элементы могут быть показаны на одном экране
Затем я добавил следующий код, чтобы увеличить размер содержимого
- (CGSize)collectionViewContentSize
{
return CGSizeMake(self.collectionView.bounds.size.width, self.collectionView.bounds.size.height+100);
}
Тогда я могу прокрутить сейчас. Здесь я опускаю первый ряд:
Вы можете увидеть, как работает декоративный вид логотипа.
2. Но я получил второй набор проблем, когда подтягиваю последний ряд:
Вы можете видеть, что декоративный вид не добавлен в зеленой части окна.
3. Фон оформления для книжной полки становится все темнее и темнее. (Пожалуйста, обратитесь к той же проблеме здесь
4. Когда я переупорядочиваю элементы, панель книжной полки иногда сдвигается
Я перечислю некоторые важные коды здесь:
- (void)prepareLayout
{
// call super so flow layout can do all the math for cells, headers, and footers
[super prepareLayout];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSMutableDictionary *shelfLayoutInfo = [NSMutableDictionary dictionary];
// decoration view - emblem
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
UICollectionViewLayoutAttributes *emblemAttributes =
[UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[EmblemView kind]
withIndexPath:indexPath];
emblemAttributes.frame = [self frameForEmblem:YES];
dictionary[[EmblemView kind]] = @{indexPath: emblemAttributes};
// Calculate where shelves go in a vertical layout
int sectionCount = [self.collectionView numberOfSections];
CGFloat y = 0;
CGFloat availableWidth = self.collectionViewContentSize.width - (self.sectionInset.left + self.sectionInset.right);
int itemsAcross = floorf((availableWidth + self.minimumInteritemSpacing) / (self.itemSize.width + self.minimumInteritemSpacing));
for (int section = 0; section < sectionCount; section++)
{
y += self.headerReferenceSize.height;
//y += self.sectionInset.top;
int itemCount = [self.collectionView numberOfItemsInSection:section];
int rows = ceilf(itemCount/(float)itemsAcross)+1; // add 2 more empty row which does not have any data
for (int row = 0; row < rows; row++)
{
indexPath = [NSIndexPath indexPathForItem:row inSection:section];
shelfLayoutInfo[indexPath] = [NSValue valueWithCGRect:CGRectMake(0,y, self.collectionViewContentSize.width, self.itemSize.height + DECORATION_HEIGHT)];
y += self.itemSize.height;
if (row < rows - 1)
y += self.minimumLineSpacing;
}
y += self.sectionInset.bottom;
y += self.footerReferenceSize.height;
}
dictionary[[ShelfView kind]] = shelfLayoutInfo;
self.shelfLayoutInfo = dictionary;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributesArrayInRect = [super layoutAttributesForElementsInRect:rect];
// cell layout info
for (BookShelfLayoutAttributes *attribs in attributesArrayInRect)
{
attribs.zIndex = 1;
CATransform3D t = CATransform3DIdentity;
t = CATransform3DTranslate(t, 0, 0, 40);
attribs.transform3D = CATransform3DRotate(t, 15 * M_PI / 180, 1, 0, 0);
}
// Add our decoration views (shelves)
NSMutableDictionary* shelfDictionary = self.shelfLayoutInfo[[ShelfView kind]];
NSMutableArray *newArray = [attributesArrayInRect mutableCopy];
[shelfDictionary enumerateKeysAndObjectsUsingBlock:^(id key, NSValue* obj, BOOL *stop) {
if (CGRectIntersectsRect([obj CGRectValue], rect))
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:[ShelfView kind] withIndexPath:key];
attributes.frame = [obj CGRectValue];
NSLog(@"decorationView rect = %@",NSStringFromCGRect(attributes.frame));
attributes.zIndex = 0;
//attributes.alpha = 0.5; // screenshots
[newArray addObject:attributes];
}
}];
attributesArrayInRect = [NSArray arrayWithArray:newArray];
NSMutableDictionary* emblemDictionary = self.shelfLayoutInfo[[EmblemView kind]];
NSMutableArray *newArray2 = [attributesArrayInRect mutableCopy];
[emblemDictionary enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *innerStop) {
if (CGRectIntersectsRect(rect, attributes.frame)) {
[newArray2 addObject:attributes];
}
}];
attributesArrayInRect = [NSArray arrayWithArray:newArray2];
return attributesArrayInRect;
}
Я буду признателен, если вы достаточно терпеливы, чтобы прочитать этот пост и дать какие-либо советы или предложения. И я опубликую полный исходный код, если смогу решить все проблемы. Заранее спасибо.