Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使用UICollectionViewTransitionLayout插入自定义UICollectionViewLayoutAttribute属性_Ios_Transitions_Uicollectionviewlayout - Fatal编程技术网

Ios 如何使用UICollectionViewTransitionLayout插入自定义UICollectionViewLayoutAttribute属性

Ios 如何使用UICollectionViewTransitionLayout插入自定义UICollectionViewLayoutAttribute属性,ios,transitions,uicollectionviewlayout,Ios,Transitions,Uicollectionviewlayout,我有两个自定义的UICollectionViewLayout对象,它们使用自定义的uiCollectionViewLayoutAttribute子类。这些自定义属性添加单个属性tintAlpha,用于控制附着到每个集合视图单元的着色覆盖视图的不透明度 现在,我想使用UICollectionViewTransitionLayout子类在这两个布局之间进行转换。如何配置转换布局子类以在自定义布局属性上插入自定义tintAlpha属性 我可以这样做: - (UICollectionViewLayout

我有两个自定义的
UICollectionViewLayout
对象,它们使用自定义的
uiCollectionViewLayoutAttribute
子类。这些自定义属性添加单个属性
tintAlpha
,用于控制附着到每个集合视图单元的着色覆盖视图的不透明度

现在,我想使用
UICollectionViewTransitionLayout
子类在这两个布局之间进行转换。如何配置转换布局子类以在自定义布局属性上插入自定义
tintAlpha
属性

我可以这样做:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
     CustomLayoutAttributes *attr = [super layoutAttributesForItemAtIndexPath:indexPath];

     CustomLayoutAttributes *fromAttr = (CustomLayoutAttributes *)[self.currentLayout layoutAttributesForItemAtIndexPath:indexPath];
     CustomLayoutAttributes *toAttr = (CustomLayoutAttributes *)[self.nextLayout layoutAttributesForItemAtIndexPath:indexPath];

     CGFloat t = self.transitionProgress;
     attr.tintAlpha = (1.0f - t) * fromAttr.tintAlpha + t * toAttr.tintAlpha;

     return attr;
}
但是,这将忽略对当前或下一个布局中的
initialLayoutAttributesForAppearingItemAtIndexPath:
finallayoutAttributesforIsAppearinGiteMatIndexPath:
中的属性所做的任何更改,因此实际上并不正确。据我所知,
UICollectionViewTransitionLayout
的默认实现确定了适当的from/to属性,并将它们缓存在
prepareLayout
layouttributesforItemAtIndexPath:
中。如果在
UICollectionViewTransitionLayout
上有一些公共API,允许我们访问这些从/到属性对象,这将非常有用,就好像我尝试实现自己的逻辑,即是否使用初始/最终属性与标准属性相比,与默认实现必然存在一些差异

在布局转换期间,是否有更好的方法插入这些自定义属性


更新:

我刚刚遇到了这个场景的另一个问题。在上面的代码中,当直接从当前/下一个版面获取从ATTR到ATTR的
时,当前版面的
集合视图
nil
(至少超出转换的第一次运行循环)。如果布局完全取决于集合视图的边界-例如考虑一个简单的覆盖流布局——那么<代码> FROMATTR 将是不正确的。 我真的很渴望在
UICollectionViewTransitionLayout
上有一个可以被子类覆盖的
InterpolatedLayoutAttribute fromLayoutAttribute:toLayoutAttributes:progress:

在提出更好的解决方案之前,我已经实现了以下解决方法。。。 默认实现从
[super prepareLayout]
调用当前和下一个布局,以选择和缓存需要从/转换到的布局属性。因为我们不能访问这个缓存(我的主要抱怨!),所以在转换过程中我们不能直接使用它们。相反,当默认实现调用插值布局属性时,我构建这些属性的自己的缓存。这只能发生在
layouttributesforementsinrect:
(接近于
currentLayout.collectionView==nil
)的问题中,但幸运的是,该方法似乎是在与转换开始相同的运行循环中,在
collectionView
属性设置为
nil
之前首先调用的。这使我们有机会建立从/到布局属性,并在转换期间缓存它们

@interface CustomTransitionLayout ()
@property(nonatomic, strong) NSMutableDictionary *transitionInformation;
@end

@implementation

- (void)prepareLayout
{
    [super prepareLayout];

    if (!self.transitionInformation) {
        self.transitionInformation = [NSMutableDictionary dictionary];
    }
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    // Let the super implementation tell us which attributes are required.
    NSArray *defaultLayoutAttributes = [super layoutAttributesForElementsInRect:rect];
    NSMutableArray *layoutAttributes = [NSMutableArray arrayWithCapacity:[defaultLayoutAttributes count]];
    for (UICollectionViewLayoutAttributes *defaultAttr in defaultLayoutAttributes) {
        UICollectionViewLayoutAttributes *attr = defaultAttr;
        switch (defaultAttr.representedElementCategory) {
            case UICollectionElementCategoryCell:
                attr = [self layoutAttributesForItemAtIndexPath:defaultAttr.indexPath];
                break;
            case UICollectionElementCategorySupplementaryView:
                attr = [self layoutAttributesForSupplementaryViewOfKind:defaultAttr.representedElementKind atIndexPath:defaultAttr.indexPath];
                break;
            case UICollectionElementCategoryDecorationView:
                attr = [self layoutAttributesForDecorationViewOfKind:defaultAttr.representedElementKind atIndexPath:defaultAttr.indexPath];
                break;
        }
        [layoutAttributes addObject:attr];
    }
    return layoutAttributes;
}

layouttributesforementsinrect:
的覆盖只需为
super
要返回属性的每个元素索引路径调用
layouttributesfor…atIndexPath:
,该路径将缓存from/to属性。例如,
layouttributesforItemAtIndexPath:
方法如下所示:


这就留下了一个新的方法来进行实际的插值,在这个方法中,不仅要插值自定义布局属性属性,还要重新实现默认插值(
center
/
size
/
alpha
/
transform
/
transform3D
):


总之。。。 因此,令人沮丧的是,这是一个庞大的代码量(为了简洁起见,这里没有显示太多),而且大多数代码只是复制或试图复制默认实现正在做的事情。这会导致性能下降,并浪费开发时间,因为如果
UICollectionViewTransitionLayout
公开了一个要重写的方法,那么开发过程可能会变得更加简单,例如:

- (UICollectionViewLayoutAttributes *)interpolatedLayoutAttributesFromLayoutAttributes:(UICollectionViewLayoutAttributes *)fromAttributes
                                                                    toLayoutAttributes:(UICollectionViewLayoutAttributes *)toAttributes
                                                                              progress:(CGFloat)progress
{
    MyLayoutAttributes *attributes = (MyLayoutAttributes *)[super interpolatedLayoutAttributesFromLayoutAttributes:fromAttributes toLayoutAttributes:toAttributes progress:progress];
    attributes.customProperty = (1.0f - progress) * fromAttributes.customProperty + progress * toAttributes.customProperty;
    return attributes;
}


这种变通方法的好处是,您不必重新实现决定在转换开始/结束时哪些布局属性可见的代码——默认实现为我们做到了这一点。我们也不必在每次布局失效时获取所有内容的属性,然后检查与可见矩形相交的项。

就是我用于此的。希望蒂莫西·穆斯会来,并提出一个很好的解释,要求他的赏金。否则,我会找到一个答案Thank@jrturton——我以前在遇到
UICollectionView
(例如)的其他问题时,确实看过这个项目,但我决定编写自己的子类。如果我错了,请纠正我,但Timothy的代码也存在上述相同的问题-即,没有考虑初始/最终布局属性,并且他的
prepareLayout
本质上是对插值
UICollectionViewTransitionLayout
的重写。在每次失效时,它也会非常低效地为每一项准备属性(不适合我的情况)。我现在已经做了类似的解决方法(根据
[super-layouttributesforementsinrect:
返回的属性缓存from/to属性),这允许我插入自定义属性。但我已经尝试复制决定是否使用初始/最终的逻辑
- (MyLayoutAttributes *)interpolatedLayoutAttributesFromLayoutAttributes:(MyLayoutAttributes *)fromAttributes
                                                      toLayoutAttributes:(MyLayoutAttributes *)toAttributes
                                                                progress:(CGFloat)progress
{
    MyLayoutAttributes *attributes = [fromAttributes copy];

    CGFloat t = progress;
    CGFloat f = 1.0f - t;

    // Interpolate all the default layout attributes properties.
    attributes.center = CGPointMake(f * fromAttributes.x + t * toAttributes.center.x,
                                    f * fromAttributes.y + t * toAttributes.center.y);
    // ...

    // Interpolate any custom layout attributes properties.
    attributes.customProperty = f * fromAttributes.customProperty + t * toAttributes.customProperty;
    // ...

    return attributes;
}
- (UICollectionViewLayoutAttributes *)interpolatedLayoutAttributesFromLayoutAttributes:(UICollectionViewLayoutAttributes *)fromAttributes
                                                                    toLayoutAttributes:(UICollectionViewLayoutAttributes *)toAttributes
                                                                              progress:(CGFloat)progress
{
    MyLayoutAttributes *attributes = (MyLayoutAttributes *)[super interpolatedLayoutAttributesFromLayoutAttributes:fromAttributes toLayoutAttributes:toAttributes progress:progress];
    attributes.customProperty = (1.0f - progress) * fromAttributes.customProperty + progress * toAttributes.customProperty;
    return attributes;
}