iOS 第三方自定义Alertview项目MBProcessHud中的重要代码分析
做ios,弹出一个自定义的alertview挺常见的。ios7以前,我们可以对系统的UIAlertView进行一点操作,实现一点简单的定制,但是ios7不再允许我们这样做了。因此,我们需要自己创建一个alertview。感谢大神们的辛勤工作,在网络上已经有多个效果不错的自定义alertview项目,大体分为2类:通过UIWindow实现,通过UIView实现。
通过UIWindow实现的话,首先要创建新的UIWindow,为了实现旋转后的布局,必须加载一个rootviewcontroller,再把需要的view加载rootviewcontroller上,总体来说,实现比较复杂。
通过UIView实现的话,可以通过addsubview 方法加到需要的view上,再实现相关动画,总体来说比较简单。
MBProcessHud项目是第二种实现方式,网上还有一个项目对它进行了扩展,实现了更多酷炫效果,请到code4app网站或github上查询。
MBProcessHud项目没有提供按钮选项,我们可以通过更改它的代码实现,所以在这里我简单分析一下它的关键函数。
最主要的函数就是要重写view的- (void)layoutSubviews 函数
- (void)layoutSubviews { // Entirely cover the parent view UIView *parent = self.superview; if (parent) { self.frame = parent.bounds; } CGRect bounds = self.bounds; // Determine the total widt and height needed,margin为一个常量 CGFloat maxWidth = bounds.size.width - 4 * margin; //这里的totalSize大小指的是显示内容的圆角矩形的大小 CGSize totalSize = CGSizeZero; //第一个控件--------------------------------------------- //确定indicator的大小 CGRect indicatorF = indicator.bounds; //先确定indicator的宽度,如果过大,那么设定成maxWidth,否则保持原值。 indicatorF.size.width = MIN(indicatorF.size.width, maxWidth); //修正totoalSize的宽度,使它能容的下indicator totalSize.width = MAX(totalSize.width, indicatorF.size.width); //不断叠加totoalSize的高度 totalSize.height += indicatorF.size.height; //第二个控件------------------------------------------------ CGSize labelSize = MB_TEXTSIZE(label.text, label.font); labelSize.width = MIN(labelSize.width, maxWidth); totalSize.width = MAX(totalSize.width, labelSize.width); //不断叠加totoalSize的高度 totalSize.height += labelSize.height; if (labelSize.height > 0.f && indicatorF.size.height > 0.f) { totalSize.height += kPadding; } //第三个控件--------------------------------------------- CGFloat remainingHeight = bounds.size.height - totalSize.height - kPadding - 4 * margin; CGSize maxSize = CGSizeMake(maxWidth, remainingHeight); CGSize detailsLabelSize = MB_MULTILINE_TEXTSIZE(detailsLabel.text, detailsLabel.font, maxSize, detailsLabel.lineBreakMode); totalSize.width = MAX(totalSize.width, detailsLabelSize.width); totalSize.height += detailsLabelSize.height; if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) { totalSize.height += kPadding; } totalSize.width += 2 * margin; totalSize.height += 2 * margin; // Position elements,依次放置控件 //第一个控件------------------------- CGFloat yPos = round(((bounds.size.height - totalSize.height) / 2)) + margin + yOffset; CGFloat xPos = xOffset; indicatorF.origin.y = yPos; indicatorF.origin.x = round((bounds.size.width - indicatorF.size.width) / 2) + xPos; indicator.frame = indicatorF; //累加y偏移量 yPos += indicatorF.size.height; if (labelSize.height > 0.f && indicatorF.size.height > 0.f) { yPos += kPadding; } //第二个控件------------------------- CGRect labelF; labelF.origin.y = yPos; labelF.origin.x = round((bounds.size.width - labelSize.width) / 2) + xPos; labelF.size = labelSize; label.frame = labelF; //累加y偏移量 yPos += labelF.size.height; if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) { yPos += kPadding; } //第三个控件------------------------- CGRect detailsLabelF; detailsLabelF.origin.y = yPos; detailsLabelF.origin.x = round((bounds.size.width - detailsLabelSize.width) / 2) + xPos; detailsLabelF.size = detailsLabelSize; detailsLabel.frame = detailsLabelF; // Enforce minsize and square rules,尽量保持矩形 if (square) { CGFloat max = MAX(totalSize.width, totalSize.height); if (max <= bounds.size.width - 2 * margin) { totalSize.width = max; } if (max <= bounds.size.height - 2 * margin) { totalSize.height = max; } } if (totalSize.width < minSize.width) { totalSize.width = minSize.width; } if (totalSize.height < minSize.height) { totalSize.height = minSize.height; } self.size = totalSize; }