调整大小时,使用自定义UICollectionViewLayout进行奇怪的“拆分”

时间:2012-10-08 15:23:36

标签: objective-c ios ios6 uicollectionview

before after

我有一个自定义UICollectionViewLayout类,它表现出一个奇怪的问题。以上屏幕截图演示。由于键盘会模糊较低的字段,因此它们被编辑,我想缩短UICollectionView,以便在键盘出现时不会被键盘遮挡。问题是我得到的结果是正确的图片。橙色边框是托管UICollectionView的视图的背景,红色是UICollectionView的背景颜色。具有橙色背景的视图是视图控制器的根视图,并使用以下内容调整大小(自身是视图控制器)。

    CGRect frame = self.view.frame;
    frame.size.height -= 300;
    self.view.frame = frame;

它表示视图根据需要调整大小,但由于某种原因,UICollectionView认为它不需要在下部绘制单元格。它分裂的地方似乎是一致的但却是随意的。如果原始视图向下滚动,则不一定会在节标题处拆分。

在布局类中,如果我返回YES - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds它正确绘制但完全重绘,所以它看起来像地狱,因为它改变/褪色的东西。调整视图大小并不会使布局无效,没有理由不能使用相同的布局。

寻找有关可能发生的事情的任何想法。布局代码如下:

//
//  MyLayout.h
//  uicontroller
//
//  Created by Guy Umbright on 8/1/12.
//  Copyright (c) 2012 Guy Umbright. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SFNativeLayout.h"
#import "SFLayoutView.h"

@class SFLayout;


@interface SFLayout : UICollectionViewLayout

@property (readonly, strong) SFNativeLayout* sfLayout;
@property (assign) BOOL deferRowsColsToCollectionView;
@property (strong) SFLayoutView* layoutView;

- (id) initWithDictionary:(NSDictionary*) dict;

- (NSInteger) numberOfSections;
- (NSInteger) numberOfItemsInSection:(NSInteger)section;

@end


//
//  MyLayout.m
//  uicontroller
//
//  Created by Guy Umbright on 8/1/12.
//  Copyright (c) 2012 Guy Umbright. All rights reserved.
//

#import "SFLayout.h"

#define ROW_HEIGHT 81 //79 with one pixel top bottom
#define HEADER_HEIGHT 30

@interface SFLayout ()

@property (strong) SFNativeLayout* sfLayout;
@property (nonatomic, strong) NSMutableArray* sectionMetrics;
@end

@implementation SFLayout

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (id) initWithDictionary:(NSDictionary*) dict
{
    if (self = [super init])
    {
        self.sfLayout = [[SFNativeLayout alloc] initWithDictionary:dict];
    }

    return self;
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (NSInteger) numberOfSections
{
    if (self.deferRowsColsToCollectionView)
    {
        return [self.layoutView numberOfSections];
    }
    else
    {
        return self.sfLayout.sectionCount;
    }
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (BOOL) sectionHasHeader:(NSInteger) section
{
    BOOL result = YES;

    if (self.deferRowsColsToCollectionView)
    {
        result = [self.layoutView sectionHasHeader:section];
    }
    return  result;
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (NSInteger) numberOfColumnsInSection:(NSInteger) section
{
    if (self.deferRowsColsToCollectionView)
    {
        return [self.layoutView numberOfColumnsInSection:section];
    }
    else
    {
        SFNativeLayoutSection* layoutSection = [self.sfLayout.sections objectAtIndex:section];
        NSInteger sectionColumns = layoutSection.columnCount;
        return sectionColumns;
    }
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (NSInteger) numberOfRowsInSection:(NSInteger) section
{
    if (self.deferRowsColsToCollectionView)
    {
        return [self.layoutView numberOfRowsInSection:section];
    }
    else
    {
        SFNativeLayoutSection* layoutSection = [self.sfLayout.sections objectAtIndex:section];
        return layoutSection.rowCount;
    }
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (CGFloat) heightForSection:(NSInteger) sectionNdx
{
    CGFloat height = 0;

    if (self.deferRowsColsToCollectionView)
    {
        height = [self numberOfRowsInSection:sectionNdx] * ROW_HEIGHT;
        if ([self sectionHasHeader:sectionNdx])
        {
            height += HEADER_HEIGHT;
        }
    }
    else
    {
        SFNativeLayoutSection* section = [self.sfLayout.sections objectAtIndex:sectionNdx];

        height += section.rowCount * ROW_HEIGHT;

        if (section.includeHeader)
        {
            height += HEADER_HEIGHT;
        }
    }
    return height;
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (CGSize)collectionViewContentSize
{
    BOOL fillSectionMetrics = NO;
    CGFloat lastY = 0;
    if (self.sectionMetrics == nil)
    {
        self.sectionMetrics = [NSMutableArray array];
        fillSectionMetrics = YES;
    }
    CGSize sz =  [self collectionView].frame.size;

    CGFloat height = 0;
    for (NSInteger ndx=0; ndx < [self numberOfSections]; ++ndx)
    {
        CGFloat sectionHeight = [self heightForSection:ndx];
        height += sectionHeight;

        if (fillSectionMetrics)
        {
            [self.sectionMetrics addObject:@{@"height":@(sectionHeight),@"startingY":@(lastY),@"endingY":@(lastY+sectionHeight)}];
            lastY += sectionHeight;
        }
    }

    sz.height = height;
    return sz;
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    return [super shouldInvalidateLayoutForBoundsChange:newBounds];
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (NSArray*) attributesForSection:(NSInteger) sectionNdx inRect:(CGRect) rect
{
//    NSLog(@"generate attrs for section %d", sectionNdx);

    NSMutableArray* result = [NSMutableArray array];
    CGRect intersect;

    NSDictionary* sectionMetrics = [self.sectionMetrics objectAtIndex:sectionNdx];
    SFNativeLayoutSection* layoutSection = [self.sfLayout.sections objectAtIndex:sectionNdx];

    NSInteger columnCount = [self numberOfColumnsInSection:sectionNdx];

    CGFloat rowStart = [[sectionMetrics valueForKey:@"startingY"] floatValue];

    if ((self.layoutView.layoutDatasource != nil) || (layoutSection.includeHeader))
    {
        CGRect headerFrame = [self collectionView].bounds;
        headerFrame.origin.y = rowStart;
        headerFrame.size.height = HEADER_HEIGHT;

        intersect = CGRectIntersection(rect, headerFrame);
        if (!CGRectIsEmpty(intersect))
        {
            UICollectionViewLayoutAttributes* attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:@"Header"
                                                                                                                    withIndexPath:[NSIndexPath indexPathForItem:0 inSection:sectionNdx]];
            attr.frame = headerFrame;
            [result addObject:attr];
        }

        rowStart = headerFrame.origin.y + headerFrame.size.height;
    }

    for (int rowNdx = 0; rowNdx < [self numberOfRowsInSection:sectionNdx]; rowNdx++)
    {
        CGRect rowRect = [self collectionView].frame;
        rowRect.size.height = ROW_HEIGHT;
        rowRect.origin.y = rowStart + (rowNdx * ROW_HEIGHT);

        intersect = CGRectIntersection(rect, rowRect);
        if (!CGRectIsEmpty(intersect))
        {
            NSInteger columns = [self numberOfColumnsInSection:sectionNdx];
            for (NSInteger colNdx =0; colNdx < columns; ++colNdx)
            {
                NSIndexPath* indexPath = [NSIndexPath indexPathForItem:rowNdx * columnCount+colNdx inSection:sectionNdx];
                    CGRect frame;

                    frame.origin.y = rowRect.origin.y;
                    frame.size.height = ROW_HEIGHT;
                    frame.size.width = self.collectionView.frame.size.width/columnCount;
                    frame.origin.x = colNdx * frame.size.width;

                    UICollectionViewLayoutAttributes* attrs =  [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
                    attrs.frame = frame;
                    [result addObject:attrs];
            }
        }
    }

    return result;
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray* attributes = [NSMutableArray array];

    for (NSDictionary* sectionMetric in self.sectionMetrics)
    {
        //can short circuit based on top of section and bottom of rect
        CGRect sectionRect = [self collectionView].frame;
        sectionRect.origin.y = [[sectionMetric valueForKey:@"startingY"] floatValue];
        sectionRect.size.height = [[sectionMetric valueForKey:@"height"] floatValue];

        CGRect intersect = CGRectIntersection(rect, sectionRect);
        if (!CGRectIsEmpty(intersect))
        {
            NSArray* sectionAttrs = [self attributesForSection:[self.sectionMetrics indexOfObject:sectionMetric] inRect:intersect];
            [attributes addObjectsFromArray:sectionAttrs];
        }
    }

    return attributes;
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return [super layoutAttributesForItemAtIndexPath:indexPath];
}

///////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////
- (NSInteger)numberOfItemsInSection:(NSInteger)section
{
    SFNativeLayoutSection* layoutSection = [self.sfLayout.sections objectAtIndex:section];
    NSInteger sectionColumns = [self numberOfColumnsInSection:section];
    NSInteger sectionRows = layoutSection.rowCount; //%%%

    return sectionColumns * sectionRows;
}

@end

0 个答案:

没有答案