iOS中UICollectionView布局对齐方式的runtime实现

经常遇到UI设计师设计出多个按钮的布局效果,但是系统默认的CollectionView布局总是不尽人意.例如这种标签式的控件,放到控制器上往往会变成了这样


相信大部分人也用过此类控件,如果想让标签左对齐,往往要写很多代码去自定义UICollectionViewLayout.我也遇到过这种问题,我在自定义UICollectionViewLayout后,发现在iOS9下,这种布局配合AutoLayout时,reloadData后会导致Crash,改了很久未果.偶然发现了一个方法,简单快捷,使用到了UICollectionViewFlowLayout的私有方法,可以简单快捷的实现我要的效果.只需要加上几行代码即可.

下面这个方法是UICollectionViewFlowLayout的私有方法.下面来跟大家解释一下options需要传的参数

- (void)_setRowAlignmentsOptions:(NSDictionary *)options;

options根据runtime可以获取到默认key有3个,其value为NSTextAlignment的NSNumber值:

UIFlowLayoutCommonRowHorizontalAlignmentKey  //水平对齐方式

UIFlowLayoutLastRowHorizontalAlignmentKey          //当前行最后一个cell的对齐方式

UIFlowLayoutRowVerticalAlignmentKey                    //垂直对齐方式

经过试验,前两个key在scrollDirection为UICollectionViewScrollDirectionVertical时生效,最后一个在UICollectionViewScrollDirectionVertical模式下不生效.

UIFlowLayoutCommonRowHorizontalAlignmentKey默认值为NSTextAlignmentJustified,意思就是水平分布,这就是为什么每行cell的间距都不一样的罪魁祸首了

UIFlowLayoutLastRowHorizontalAlignmentKey的默认值为NSTextAlignmentCenter,意思就是最后一个cell居中对齐,这就是为什么一行只有一个cell的时候,这个cell都是居中的罪魁祸首了.

当我们改变了这两个默认值后

SEL sel = NSSelectorFromString(@"_setRowAlignmentsOptions:");

if ([self.collectionView.collectionViewLayout respondsToSelector:sel]) {

        ((void(*)(id,SEL,NSDictionary*))objc_msgSend)(self.collectionView.collectionViewLayout,sel,

                    @{@"UIFlowLayoutCommonRowHorizontalAlignmentKey":@(NSTextAlignmentLeft),

                    @"UIFlowLayoutLastRowHorizontalAlignmentKey" : @(NSTextAlignmentLeft),

                    @"UIFlowLayoutRowVerticalAlignmentKey" : @(NSTextAlignmentCenter)});   

  }

我们看看效果


ok达到了我们的效果.

我们再来看一点好玩的.把UIFlowLayoutCommonRowHorizontalAlignmentKey的对齐方式改成right会怎样呢?


ok了,key的释义出来了,UIFlowLayoutCommonRowHorizontalAlignmentKey的对齐方式为right时,如果UIFlowLayoutLastRowHorizontalAlignmentKey为left,那么一行只有一个cell时,这个cell会左对齐.

注:此方法为UIKit框架下的公有类的私有方法,可以上架,经过测试,可以适配从iOS 9至iOS 12的所有机型.对此方法还有不懂的地方,可以联系我或者直接在下方留言,我看到会第一时间回复你们.

更新:

swift写法

导入

Import ObjectiveC

collectionView.collectionViewLayout.perform(Selector.init(("_setRowAlignmentsOptions:")),with:NSDictionary.init(dictionary:["UIFlowLayoutCommonRowHorizontalAlignmentKey":NSNumber.init(value:NSTextAlignment.left.rawValue)]));

你可能感兴趣的:(iOS中UICollectionView布局对齐方式的runtime实现)