一、写在前面
实在是因为太久没有写 iOS 了,快把主业给忘记了,于是心痒痒的打开 Xcode 。想起之前工作中需要这么一个 Toast,它需要满足这些功能:
- 调用时自动按队列顺序显示;
- 不被其它的视图遮挡;
- 淡入淡出动画;
- 自由的指定显示时长;
- 自由的指定显示位置,有三种位置选择;
- 根据内容长度自动调整显示时长(限定最大和最小显示时长);
- 点击吐司关闭。
代码 XXToast 已开源,如果觉得对你有用请给个⭐️
二、主要功能
1、按队列顺序显示
在实际开发中,很多时候需要对一整个执行流程进行 Toast 提示,因此我们是需要 Toast 按顺序显示的,而不是在步骤1的 Toast 显示时,进入步骤2或步骤3时立刻被其 Toast 覆盖,这样起不到很好的提示作用。而因为在 Objective-C 中,数组是有序的,刚好可以用来作为队列使用。
1 2
| static NSMutableArray *toastQueue; toastQueue = [NSMutableArray array];
|
有任务进来,就往后面加:
1
| [toastQueue addObject:xxx];
|
完成任务时,就移除最前面的:
1
| [toastQueue removeObjectAtIndex:0];
|
2、不被其它的视图遮挡
很多时候,我们在展示一个 Toast 的时候,刚好需要切换 ViewController,而又不希望 Toast 在切换 ViewController 后就不显示了。那么 Toast 就肯定不能加到当前的 ViewController 上。那么加到 KeyWindow 上呢?实测也是不行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| + (UIWindow *)getKeyWindow { UIWindow *keyWindow = nil; if (@available(iOS 13.0, *)) { for (UIWindow *window in [UIApplication sharedApplication].windows) { if (window.isKeyWindow) { keyWindow = window; break; } } } else { keyWindow = [UIApplication sharedApplication].keyWindow; } return keyWindow; }
|
实际上需要自行创建一个 window,设置 windowLevel,使其处于较高的 level
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if (@available(iOS 13.0, *)) { // get the currently active scene for (UIWindowScene* scene in [UIApplication sharedApplication].connectedScenes) { if (scene.activationState == UISceneActivationStateForegroundActive) { toastWindow = [[UIWindow alloc] initWithWindowScene:scene]; break; } } } else { toastWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; } toastWindow.windowLevel = UIWindowLevelAlert + 1; toastWindow.backgroundColor = [UIColor clearColor]; toastWindow.hidden = NO; [toastWindow makeKeyAndVisible];
|
3、淡入淡出动画
因为 Toast view 我使用 UIView 实现,淡入淡出的动画可以这样实现:
其中最需要注意的是,因为我对 Toast 使用了手势,因此需要对 animateWithDuration
使用 UIViewAnimationOptionAllowUserInteraction
,以允许在动画的过程中允许用户交互。而且 toastView 不能直接设置 alpha 等于或略大于0,否则手势交互也将失效,因此改用 colorWithAlphaComponent
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| __weak typeof(self) weakSelf = self; // fade in animation [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ toastView.alpha = 1.0; } completion:^(BOOL finished) { // fade out animation [UIView animateWithDuration:0.3 delay:duration options:UIViewAnimationOptionAllowUserInteraction animations:^{ // toastView.alpha = 0.01; using this will disable the gesture toastView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; } completion:^(BOOL finished) { // remove the toast view [weakSelf removeToastView:toastView]; }]; }];
|
4、根据内容长度自动调整显示时长
在根据内容长度自动调整显示时长的同时,限定最大和最小显示时长,更符合实际使用中的用户习惯。不会因为内容过短而导致用户没看完就关闭了,也不会因为内容太长,导致占用太长时间。结合点击 Toast 关闭的功能,在完整展示信息的同时,可以带给用户更多的自由度。
三、显示效果