Pop-ups are a ubiquitous design in projects, used in many requirements such as message reminders, operation interaction, and function selection.

In UIKit, there are many ways to implement it, such as overwriting UIView, modal UIViewController, adding keyWindow/rootController, etc.

Today we’ll look at some of the implementations available in SwiftUI.

System comes with

  • Alert, ActionSheet: These systems come with pop-ups and I won’t go into details. They are very convenient, but they don’t support much customization. You don’t use it much in projects, because most projects have their own set of UI warning pop-up effects. But most are also based on its style to implement.

  • .sheet(…) ,. FullScreenCover (…). : Modifier commonly used in mode, but rarely used for pop-ups. Why ‘almost’? Because when I wrote this, I deliberately tried to achieve it, but there are limitations. We’ll talk about that.

The custom

start

Implementing a popover on SwiftUI is simple. Just use ZStrck to nest two Views.

Yes, it’s ugly. But it does kind of pop over. Embellish it a little bit. Add an animation display

code The effect

Walk slowly! Completed.

Through different modifier can achieve different pop-up effect.

End of this article (Manual dog head)

The problem

If you were just using it for a Demo, that would work.

However, in the actual project writing process, the UI is more complex component control combination nested. Especially in NavigationView, TabView, and NavigationView + TabView, this effect is not sufficient.

This does not meet expectations, and in real projects, navigation is almost impossible, so the problem arises.

I found some similar code online, and when I added NavigationView and TabView to the code, more or less the same thing happened. As it turns out, writing a Demo is a little different from actually writing a project.

The solution

  1. Will need to pop upviewPut it in the outermost layer

    This solution is the easiest to think of and the simplest. Refer to the code above and place the ZStack directly outside the NavigationView.

    Limitations: This approach is problematic if page A pushes to page B. Because the navigation bar of page B is endowed by page A. There is no way to put ZStack outside the navigation bar.

    In most cases, the project level is NavigationView or TabView. If you want to use ZStack for full-screen popups, you need to put ZStack in the outermost layer. One or two popovers are acceptable, but if there are too many popovers, it may be uncomfortable:

    And this is just presentation, not interaction. To do this, you need to think about logic and encapsulation.

    The PartialSheet is the bottom pop-up box wrapped around the outermost View. Those who are interested can refer to it or use it directly.

    Suggestion: If the current View does not have or hides the navigation bar, or the popup does not need a background. It can be implemented directly this way. Such as Hud, Toast, etc.

  2. Based on theSwiftUIModal jump implementation in

    The Modifier used for the mode of SwiftUI is.sheet(…). And the fullScreenCover (…). (iOS 14), clears the modal View’s background color by adding background to the View that needs to be popped up.

    Implementation effect

    Modifier code The effect
    .fullScreenCover()
    .sheet()

    Limitations: Due to the use of system modes, they are all pop-up from the bottom animation, and currently there is no modification of the pop-up animation. So it limits how popovers can appear.

    The two modifiers in SwiftUI are equivalent to the mode effects in UIKit where UIModalPresentationStyle is Automatic and fullScreen. Therefore, this method can ignore the hierarchical relationship in the project and realize the overall popover effect efficiently and quickly.

    Suggestion: Because the pop-up mode is limited to the bottom, it is suitable for some custom pop-up views.

  3. Customize the modal jump by getting the master controller

    Given the second solution, let’s say that the problem seems to be solved if the constraints of the second solution are removed.

    Since the pop-up mode cannot be modified in SwiftUI. The mode is performed by taking the current controller and modifying the parameters during the jump.

    Start by setting the current controller with a custom environment variable:

    Then modify the modal jump parameter of UIViewController:

    The above code is only set up for popovers. You can also expose other parameters for customization. Since SwiftUI does not have full-screen mode jump on iOS 13, you can customize SwiftUI in this way based on your personal needs.

    The next step is to implement and call the View via @environment (\.viewController) to the main controller and implement the call where you want to interact.

    code The effect

    Limitations: Because the mode is a new controller, the gap time of multiple popover interactions is slightly longer. After all, we must first dismiss and then re-present.

    The above code is just a simple display, with very little functionality or effect involved. Writing projects is more complicated than this, but most popover problems can be handled by paying attention to the logic of multiple popover displays or interactions. Of course, writing will be relatively complex, after all, belongs to the overall custom, without the help of SwiftUI’s own modifier.

    Suggestion: According to the requirements, simple methods can not handle, use this way.

conclusion

The pop-up box problem is something I encountered in some specific projects and only found the current solutions. There must be a better way I haven’t found. If you find any of the above articles or code unreasonable, feel free to leave a comment. If you have a better solution, please feel free to comment.

There are usually some problems that we don’t see when we write the Demo. However, when writing actual projects, there are more logic and interaction involved, and some problems are often exposed by themselves. At this time, more knowledge will be learned and acquired through the process of solving problems.

Finally, thank you for reading. I wish good!