加载视图和链接视图_使用SwiftUI的简单应用加载视图

加载视图和链接视图

Creating an initial app loading screen is probably not thought about too much when developing iOS apps. Today we’ll take a quick look at how we can create a relatively simple and elegant loading screen.

在开发iOS应用程序时,可能不会过多考虑创建一个初始应用程序加载屏幕。 今天,我们将快速了解如何创建一个相对简单而优雅的加载屏幕。

We want to see your work! If you’ve built something using this tutorial, send us pics! Find us on Twitter @TrailingClosure, or email us at howdy@TrailingClosure.com

我们希望看到您的作品! 如果您使用本教程构建了一些东西,请给我们发送图片! 在Twitter @TrailingClosure上找到我们,或通过howdy@TrailingClosure.com给我们发送电子邮件

This tutorial is split into two parts:

本教程分为两个部分:

  • Creating the ScaledMaskModifier

    创建ScaledMaskModifier

  • Creating the LoadingView

    创建LoadingView

创建ScaledMaskModifier (Create The ScaledMaskModifier)

Our ScaledMaskModifier is going to be used to animate the display of our loading view. It takes a Mask as an input that will scale up over time to display the loading view. See below for a glimpse.

我们的ScaledMaskModifier将用于设置加载视图的动画。 它使用“ Mask作为输入,它将随着时间的推移按比例放大以显示加载视图。 请参阅下面的内容。

Image for post
ScaledMaskModifier using a Circle作为蒙版的 Circle as the mask ScaledMaskModifier

First, create a new ViewModifier called ScaledMaskModifier. We're going to add two variables to the class:

首先,创建一个新的ViewModifier称为ScaledMaskModifier 。 我们将向该类添加两个变量:

  1. mask - The Mask described earlier. It will grow over time to display the underlying loading view.

    mask -面具如前所述。 随着时间的流逝,它将显示基础的加载视图。

  2. progress - The value to keep track of where in the animation we are.

    progress跟踪动画位置的值。

Here is the template of the struct so far:

到目前为止,这是该结构的模板:

import SwiftUI
struct ScaledMaskModifier<Mask: View>: ViewModifier {

var mask: Mask
var progress: CGFloat

func body(content: Content) -> some View {
content
}
}

Next we need to calculate the height and width of the mask and then apply it to our content. The tricky thing here is we want to ensure that the mask will shape will grow to the full size of the content. Think of it similarly to how we use scaleToFill() on an Image.

接下来,我们需要计算蒙版的高度和宽度,然后将其应用于内容。 这里的棘手事情是我们要确保蒙版的形状将增长到内容的全部大小。 与我们如何在Image上使用scaleToFill()类似地考虑它。

  1. Create a function called calculateSize(geometry: GeometryProxy). This will return the size of the mask at it's maximum (at the end of the animation). It will figure out whether or not the width or height of the content is larger and return that as the size.

    创建一个名为calculateSize(geometry: GeometryProxy)的函数。 这将返回最大的mask大小(在动画末尾)。 它将确定内容的宽度或高度是否较大,并将其返回为大小。

// Calculate Max Size of Mask
func calculateSize(geometry: GeometryProxy) -> CGFloat {
if geometry.size.width > geometry.size.height {
return geometry.size.width
}
return geometry.size.height
}
  1. Apply the mask to our content while using calculateSize(geometry:) and progress to scale the mask size over time.

    在使用calculateSize(geometry:)同时,将mask应用于我们的内容,然后progress缩放遮罩大小。

import SwiftUI
struct ScaledMaskModifier<Mask: View>: ViewModifier {

var mask: Mask
var progress: CGFloat

func body(content: Content) -> some View {
content
.mask(GeometryReader(content: { geometry in
self.mask.frame(width: self.calculateSize(geometry: geometry) * self.progress,
height: self.calculateSize(geometry: geometry) * self.progress,
alignment: .center)
}))
}

// Calculate Max Size of Mask
func calculateSize(geometry: GeometryProxy) -> CGFloat {
if geometry.size.width > geometry.size.height {
return geometry.size.width
}
return geometry.size.height
}
}

创建LoadingView (Create the LoadingView)

Next up we’ll put the ScaledMaskModifier to work by creating the LoadingView. Also inside the LoadingView is where we'll handle the animations.

接下来,我们将通过创建ScaledMaskModifier来使LoadingView 。 同样在LoadingView内,我们将处理动画。

  1. Create a new View and call it LoadingView. Inside you need to define 3 variables: one for the contents of the LoadingView, one for the progress of the animation, and another for the Y offset (bouncing animation). See below for an example.

    创建一个新的View并将其LoadingView 。 在内部,您需要定义3个变量:一个用于LoadingView的内容,一个用于动画的进度,另一个用于Y偏移(弹跳动画)。 请参阅下面的示例。

import SwiftUI
struct LoadingView<Content: View>: View {
var content: Content
@Binding var progress: CGFloat
@State var logoOffset: CGFloat = 0 //Animation Y Offset

var body: some View {
content
}
}
  1. Next, we’ll need to apply the ScaledMaskModifier to the content. Here we used a Circle as the mask, but really you could use any Shape or View such as a Rectangle or any other custom SwiftUI View.

    接下来,我们需要将ScaledMaskModifier应用于内容。 在这里,我们使用Circle作为蒙版,但是实际上您可以使用任何ShapeView例如Rectangle或任何其他自定义SwiftUI View

var body: some View {
content
.modifier(ScaledMaskModifier(mask: Circle(), progress: progress))
}
  1. In addition the ScaledMaskModifier we will make the content bounce up and down. To do this, we're going to animate its y offset.

    此外, ScaledMaskModifier我们将尽content上下跳动。 为此,我们将为其y偏移量设置动画。

var body: some View {
content
.modifier(ScaledMaskModifier(mask: Circle(), progress: progress))
.offset(x: 0, y: logoOffset)
}
  1. Time to add the animations. Here we’ll animate the content's progress change from 0 to 1, while at the same time bouncing it up and down.

    是时候添加动画了。 在这里,我们将使content的进度从0变为1进行动画处理,同时将其上下跳动。

import SwiftUI
struct LoadingView<Content: View>: View {
var content: Content
@Binding var progress: Double
@State var logoOffset: CGFloat = 0 //Animation Y Offset

var body: some View {
content
.modifier(ScaledMaskModifier(mask: Circle(), progress: progress))
.offset(x: 0, y: logoOffset)
.onAppear {
withAnimation(Animation.easeInOut(duration: 1)) {
self.progress = 1.0
}
withAnimation(Animation.easeInOut(duration: 0.4).repeatForever(autoreverses: true)) {
self.logoOffset = 10
}
}
}
}

创建一个例子 (Creating an Example)

Now we’re going to put our LoadingView to the test in an example. See below:

现在,在一个示例中,我们将LoadingView进行测试。 见下文:

Here we’ve created a fake HomeView that is displayed once the loading is finished. As you can see we use the variable doneLoading to decide which vie to render on screen.

在这里,我们创建了一个伪造的HomeView ,加载完成后就会显示出来。 如您所见,我们使用变量doneLoading决定在屏幕上渲染哪个视频。

For the LoadingView I've passed in a Image that will be used as the content of the loading screen.

对于LoadingView我传递了一个Image ,该Image将用作加载屏幕的content

Finally, if you’re curious as to why I’ve used the onAppear() function, it is so I can simulate the asynchronous nature of loading data for your app.

最后,如果您对我为什么使用onAppear()函数感到好奇,那么我可以模拟为您的应用程序加载数据的异步特性。

import SwiftUI
struct ContentView: View {
@State var progress: CGFloat = 0
@State var doneLoading: Bool = false

var body: some View {
ZStack {
if doneLoading {
HomeView()
.transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
} else {
LoadingView(content: Image("PathMaskLogo-Dark")
.resizable()
.scaledToFit()
.padding(.horizontal, 50),
progress: $progress)
// Added to simulate asynchronous data loading
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation {
self.progress = 0
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
withAnimation {
self.doneLoading = true
}

}
}
}
}
}
}
}
Image for post
Example Use
使用范例

支持像这样的未来教程! (Support Future Tutorials Like This One!)

Please consider subscribing using this link. If you aren’t reading this on TrailingClosure.com, please come check us out sometime!

请考虑使用此链接进行订阅。 如果您没有在TrailingClosure.com上阅读此书 ,请随时联系我们!

We want to see your work! If you’ve built something using this tutorial, send us pics! Find us on Twitter @TrailingClosure, or email us at howdy@TrailingClosure.com

我们希望看到您的作品! 如果您使用本教程构建了一些东西,请给我们发送图片! 在Twitter @TrailingClosure上找到我们,或通过howdy@TrailingClosure.com给我们发送电子邮件

翻译自: https://medium.com/dev-genius/simple-app-loading-view-239807a9db1e

加载视图和链接视图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值