前言
前段时间公司另一iOS工程师在做项目的时候遇到一个标签视图,刚开始的时候他是自己创建的,但遇到一些问题,我就建议他去网上找一些比较好的第三方,因为这些标签不是一个地方出现,你总不能一直粘贴复制吧。遇到这种情况最好的处理方式就是自己封装一套,虽然刚开始设计的时候需要耗一些时间,一旦封装完成以后写代码就是一路绿灯,既然要封装一套那就要考虑其他开发者使用的便利性、代码的可读性以及功能的拓展性。自己之前做电商项目的时候也写过一套,这次在之前的那套基础上对代码做了一定的完善与拓展便开源出来了
先看一下QQ音乐、美团、天猫以及SGTagsView实现的标签效果图展示
代码介绍
SGTagsViewConfigure *configure = [SGTagsViewConfigure configure];
NSArray *tags = @[@"iPhone 8", @"iPhone 8P", @"iPhone X", @"iPhone XR", @"iPhone XS", @"iPhone XS Max"];
SGTagsView *tagsView = [SGTagsView tagsViewWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 50) configure:configure];
tagsView.tags = tags;
[self.view addSubview:tagsView];
tagsView.singleSelectedBlock = ^(SGTagsView * _Nonnull tagsView, NSString *tag, NSInteger index) {
NSLog(@"%@ - - %ld", tag, index);
};
看完代码是不是相当便利,而且SGTagsView的设计理念来源是对SGPagingView框架内部的SGPageTitleView的抽取,目前GitHub1200+star,希望能够方便更多的开发者使用和了解
设计过程中遇到的一些问题及处理
- 垂直布局自适应以及标签自动换行问题及处理
- (void)P_layoutVerticalStyle {
__block CGFloat btnX = 0;
CGFloat btnY = (self.tag_rown - 1) * (self.configure.verticalSpacing + self.configure.height);
CGFloat btnH = self.configure.height;
CGFloat contentScrollViewWidth = self.contentScrollView.frame.size.width;
[self.tempMArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIButton *btn = obj;
CGSize tempSize = [self P_sizeWithString:btn.currentTitle font:self.configure.font];
CGFloat btnW = tempSize.width + self.configure.additionalWidth;
btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
btnX = CGRectGetMaxX(btn.frame) + self.configure.horizontalSpacing;
if (btnX > contentScrollViewWidth) {
*stop = YES;
self.tag_rown += 1;
for (NSInteger index = 0; index < idx; index++) {
[self.tempMArr removeObjectAtIndex:0];
}
[self P_layoutVerticalStyle];
}
}];
}
看内部代码可以得知 P_layoutVerticalStyle 这个函数在不停的自我调用,这里最重要就是 self.tempMArr 这个临时数组记录要布局的标签进行标签布局;如果当前标签的整体frame小于SGTageView的宽,取下一标签继续比较当前标签与SGTageView宽做对比;如果当前标签的整体frame大于SGTageView的宽,1、停止遍历,2、记录标签行数,3、移除之前标签对象,4、再次调用自身函数继续计算直到所有标签布局完成为止
- 图片与文字布局遇到的问题及处理
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[button setImage:[UIImage imageNamed:imageName] forState:(UIControlStateNormal)];
[self P_button:button imagePositionStyle:imagePositionStyle spacing:spacing];
});
这里之所以使用dispatch_after函数是因为内部子视图布局是在layoutSubviews里面处理的,这个函数调用时机相对其他函数较晚,而调整图片与文字位置的布局方法是在得知图片以及文字frame才开始的,所以简单粗暴的就这样解决了
end
如有技术问题请前往GitHub;看到之后会抽时间处理的