2

前 后

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

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

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

在布局类中,如果我为 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 返回 YES,它会正确绘制但会完全重绘,所以它看起来像地狱一样,因为它会发生移动/淡化的事情。并且调整视图大小并不会真正使布局无效,没有理由不能使用相同的布局。

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

//
//  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
4

0 回答 0