经常遇到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)]));