造轮子:打造一款易用的 iOS Toast

2024-08-15  本文已影响0人  上发条的树

一、写在前面

实在是因为太久没有写 iOS 了,快把主业给忘记了,于是心痒痒的打开 Xcode 。想起之前工作中需要这么一个 Toast,它需要满足这些功能:

代码 XXToast 已开源,如果觉得对你有用请给个⭐️

二、主要功能

1、按队列顺序显示

在实际开发中,很多时候需要对一整个执行流程进行 Toast 提示,因此我们是需要 Toast 按顺序显示的,而不是在步骤1的 Toast 显示时,进入步骤2或步骤3时立刻被其 Toast 覆盖,这样起不到很好的提示作用。而因为在 Objective-C 中,数组是有序的,刚好可以用来作为队列使用。

static NSMutableArray *toastQueue;
toastQueue = [NSMutableArray array];

有任务进来,就往后面加:

[toastQueue addObject:xxx];

完成任务时,就移除最前面的:

[toastQueue removeObjectAtIndex:0];

2、不被其它的视图遮挡

很多时候,我们在展示一个 Toast 的时候,刚好需要切换 ViewController,而又不希望 Toast 在切换 ViewController 后就不显示了。那么 Toast 就肯定不能加到当前的 ViewController 上。那么加到 KeyWindow 上呢?实测也是不行的。

+ (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

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

__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 关闭的功能,在完整展示信息的同时,可以带给用户更多的自由度。

三、显示效果

effect.png
上一篇下一篇

猜你喜欢

热点阅读