美文网首页
造轮子:打造一款易用的 iOS Toast

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

作者: 上发条的树 | 来源:发表于2024-08-15 18:36 被阅读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

    相关文章

      网友评论

          本文标题:造轮子:打造一款易用的 iOS Toast

          本文链接:https://www.haomeiwen.com/subject/xriekjtx.html