iOS7中如何在UIAlertView中添加子视图?

67

在iOS 7中,使用addSubview方法向UIAlertView添加控件已经不再被推荐。据我所知,苹果公司承诺会添加contentView属性。

iOS 7现已发布,但我发现该属性尚未添加。因此,我正在寻找一些自定义解决方案,以便向该alertView添加进度条等功能。例如类似于TSAlertView的东西,但更适合在中使用。


3
GM种子已经发布,但并非公开发布。如有需要,请与苹果公司进行测试并提交错误报告。 - Wain
9
正如在 SO 上多次指出的那样,iOS 7 的问题并不是禁止讨论的。当然,开发人员不应该讨论他们同意的 NDA 条款所涵盖的内容。但是 SO 并不关心这些。 - rmaddy
1
修改UIAlertView的视图层次结构已经被明确禁止了一段时间。 “UIAlertView类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。” - vikingosegundo
UIAlertView文档中没有任何链接或单词。只有一个事实,即它在iOS7中不起作用,并且有很多关于苹果开发者论坛的讨论。 - B.S.
1
从iOS8开始,使用UIAlertController代替。 - János
显示剩余5条评论
8个回答

55

干得好,伙计!我会更新我的答案,加入你的精彩控件。 - Tarek Hallak
另一个设计不同的分支在这里: github.com/kwent/ios-custom-alertview - Quentin Rousseau
这在禁用ARC时无法工作。我花了大部分下午尝试修复原始的Github项目,但没有成功。 - Wedge Martin
3
感谢@WedgeMartin,没错,这个项目是一个ARC项目。但是,您不需要修复原始文件,只需在Xcode中设置一个例外:https://dev59.com/52kv5IYBdhLWcg3wiRWo - Wimagguc
@Wimagguc 我已经实现了这个库。有一件事我无法解决。我该如何从这个自定义警报视图中访问像uiview、uibutton这样的视图属性? - Shourob Datta

35

我只用了1天就创建了一个与苹果的警告视图完全相同的自定义警告视图

  1. 拍摄一张苹果警告视图的截图,以供参考(字体大小、间距、宽度)。
  2. 创建一个带有标题、消息、自定义视图和按钮表格的xib(Apple现在使用表格而不是UIButton,默认表格单元足够好)。请注意,您需要3个按钮表格:两个用于左侧和右侧按钮(当按钮数量为2时),另一个用于其他情况(一个按钮或多个按钮)。
  3. 实现UIAlertView的所有方法到您的自定义警告视图中。

  4. 显示/隐藏 - 您可以为警报创建特定的模态窗口,但我只是将我的警报放在顶部的根视图控制器上。将您可见的警报注册到静态数组中。如果显示第一个警报/解除最后一个警报,请将您的窗口/视图控制器的色调模式更改为暗淡/自动,并添加/删除一些暗淡的视图(黑色,alpha = 0.2)。

  5. 模糊背景 - 使用苹果的示例代码(我使用了不透明的白色)
  6. 3D动态效果 - 使用苹果的示例代码(5行代码)。如果您想要一个不错的效果,请在步骤5中拍摄稍大的快照,并为警报背景和前景添加反向动画器。

编辑:

模糊背景和视差效果示例代码均可在“iOS_RunningWithASnap”WWDC 2013示例代码中找到

视差效果:

UIInterpolatingMotionEffect* xAxis = [[[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                                                     type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis] autorelease];
xAxis.minimumRelativeValue = [NSNumber numberWithFloat:-10.0];
xAxis.maximumRelativeValue = [NSNumber numberWithFloat:10.0];

UIInterpolatingMotionEffect* yAxis = [[[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                                                     type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis] autorelease];
yAxis.minimumRelativeValue = [NSNumber numberWithFloat:-10.0];
yAxis.maximumRelativeValue = [NSNumber numberWithFloat:10.0];

UIMotionEffectGroup *group = [[[UIMotionEffectGroup alloc] init] autorelease];
group.motionEffects = @[xAxis, yAxis];
[self addMotionEffect:group];

模糊的背景是唯一复杂的地方。如果可以使用不透明的颜色代替,尽量使用。否则需要进行大量的实验。另外请注意,当背景为暗色时,模糊的背景并不是一个好的解决方案。

对于显示/隐藏动画,我正在使用新的弹簧动画方法:

void (^animations)() = ^{
    self.alpha = 1.0f;
    self.transform = CGAffineTransformIdentity;
};

self.alpha = 0.0f;
self.transform = CGAffineTransformMakeScale(0.5f, 0.5f);

[UIView animateWithDuration:0.3
                      delay:0.0
     usingSpringWithDamping:0.7f
      initialSpringVelocity:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:animations
                 completion:^(BOOL completed) {
                         //calling UIAlertViewDelegate method
                     }];

@Sulthan,您能告诉我哪个WWDC视频或示例使用了3D /视差效果吗?谢谢。安德烈亚 - Andrea
我发现这非常有帮助。他们提供了执行此操作所需的一切,还提供了额外功能的选项,我认为做得很好! - user2277872
14
George Asda:Sulthan友善地提供了创建UIAlertView克隆时需要涵盖的高级检查清单。他表现出了员工的诚信,没有直接分享别人为之付费的代码。他完全没有必要帮忙。应该尊重一下他。更好的做法是,创建一个实现,并与我们分享... 做 unto others等等。 - Chris Hatton

32
我编写了一个完整的UIAlertView实现,模仿了完整的UIAlertView API,但添加了我们一直想要的contentView属性:SDCAlertViewimage
(来源:github.io)

2
@GeorgeAsda:关于你的bug:请提出一个单独的问题,并添加适当的信息和代码。README指示了项目需要正确构建的文件。不确定你对Cocoapods有什么意见,但许多人认为这是获取此项目最新文件的最简单方法。 - Scott Berrevoets
1
如果一个库不支持CocoaPods,我认为这是一个很大的负面因素,而且相比其他手动添加第三方库的方法,我非常倾向于使用它。但是对于那些不喜欢它的人来说,他们总是可以选择更加困难的道路。 - Gavin
5
Pods绝对是正确的选择。不必理会那些持反对意见者。如果他们不想使用Pods,也很容易手动添加。反对Pod的人态度如此粗鲁,我感到震惊。 - powerj1984
1
@GeorgeAsda “如果其中一个依赖项更新并破坏了您的项目怎么办???” 使用CocoaPods,您可以定义依赖项的版本并将其“冻结”在那里。另一方面,手动复制文件并不总是那么容易,无法确定您需要哪个版本。 - Kremk
1
@Kremk,我想说的是,我希望自己能够掌控下载的内容,而不是被某个该死的播客所控制...你不必同意我的观点,但你需要接受不同的看法。 - George Asda
显示剩余6条评论

27

对于那些喜欢简单有效方法而不需要编写代码的人,这里提供了一个酷炫的解决方案,无需使用任何其他私有框架即可向iOS 7警报视图添加子视图,即

[alertView setValue:imageView forKey:@"accessoryView"];

为了更好地理解,以下是示例代码:

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(180, 10, 85, 50)];
UIImage *wonImage = [UIImage imageNamed:@"image.png"];
[imageView setImage:wonImage];

//check if os version is 7 or above
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
      [alertView setValue:imageView forKey:@"accessoryView"];
}else{
      [alertView addSubview:imageView];
}

希望这能帮助到某些人,谢谢 :)


3
请下票者仔细审查答案,并在投反对票之前三思。至少在评论中提供理由是最低的要求。:v - Eshwar Chaitanya
不起作用。它在没有iOS 7的情况下工作,这意味着else条件与addSubview正常工作,但if条件与setValue不起作用。 - MD SHAHIDUL ISLAM
@Salim 请检查您的Xcode版本,iOS 7需要使用5及以上版本的Xcode。 - Eshwar Chaitanya
1
很棒的答案。对我来说非常有效,用于将UIActivityIndicatorView添加到UIAlertView中。我只是用活动指示器替换了UIImageView。 - Septronic
图片大小被忽略了。不知道为什么。 - bruno

17

适用于IOS7

UIAlertView *alertView1 = [[UIAlertView alloc] initWithTitle:@"Enter Form Name" 
                                               message:@""
                                               delegate:self 
                                               cancelButtonTitle:@"Cancel"
                                               otherButtonTitles:@"Ok", nil];
alertView1.alertViewStyle = UIAlertViewStyleSecureTextInput;
UITextField *myTextField = [alertView1 textFieldAtIndex:0];
[alertView1 setTag:555];
myTextField.keyboardType=UIKeyboardTypeAlphabet;

[alertView1 show];

这适用于iOS 5及更高版本。这不仅仅是iOS 7的特性。 - Brian Stormont

10

在iOS7中,将不再有带有自定义视图的UIAlertView,也不会有苹果公司改变心意的contentView,因此现在在UIAlertView中是不可能使用addSubview的。

根据苹果论坛上许多帖子,SVProgressHUD是一个很好的替代品。

编辑:

iOS7中正式没有addSubviewUIAlertView的子类化。

UIAlertView类旨在按原样使用,不支持子类化。该类的视图层次结构是私有的,不得修改。

其他很好的替代品:

ios-custom-alertview by wimagguc

MZFormSheetController


2
我仍然认为他们会履行承诺添加contentView,因为在现有应用程序中破坏UI是一个愚蠢的决定。 - B.S.
4
你最好想出一种不同的方法,这里不会有奇迹发生。;-) - Matthias Bauch

1
你可以在这里找到不需要额外类的简单解决方案 这里
它基于为普通的 UIAlertView 设置 accessoryView。

1

PKAlertController (https://github.com/goodpatch/PKAlertController) 是一个非常棒的库。我测试了很多类似的库,只有它满足了我所有的需求。

它的优点:

  • 支持自定义视图
  • 支持 iOS7
  • 它是一个视图控制器
  • 行为和外观都像本地警报视图,包括运动效果
  • 可定制
  • 与 UIAlertController 的接口相似

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接