iOS SwiftUI基础学习(三)

第七节 正向传值
在之前我们已经完成了跳转的部分,但是只是跳转到一个Text View,现在我们新建一个SwiftUI View:SceneryView.swift 文件,用来显示跳转后的页面



在新的页面,我们先创建好所需的视图,这里我们采用 ZStack 深浅的布局,使得图片和文字叠加

struct SceneryView: View {
    var body: some View {
        ZStack {
            Image("埃及-金字塔-黄昏")
            Text("埃及")
        }
    }
}

为了能够在这个页面接收上一个页面传进来的值,我们定义一个属性 “scenery”
这个时候在下面的 SceneryView_Previews 预览代码就会提示我们,我们定义了一个值,但是没有进行传值操作
我们点击“Fix”自动修复,填入我们之前定义的sceneries数组


struct SceneryView_Previews: PreviewProvider {
    static var previews: some View {
        SceneryView(scenery: sceneries[0])
    }
}

我们可以发现,在每一个SwiftUI View下方都有一个Previews,它的作用就是让我们可以调试数据,然后预览效果。它只会在debug状态下有效,在运行后这部分的代码的不会有效的。
我们将代码修改一下如图所示,可以看到在Previews中可以测试我们需要显示的内容



然后回到第一个页面,将跳转的destination目标改为我们新建的SceneryView,并且参照刚才Presviews的代码,我们写下如下代码



这时候点击右边画布的,就可以发现我们已经实现了正向传值了。
最后我们完善一下SceneryView的布局设置
struct SceneryView: View {
    
    let scenery: Scenery
    
    var body: some View {
        
        // 对齐方式:底部右对齐
        ZStack(alignment: .bottomTrailing) {
            Image(scenery.imageName)
                // 让图片不超出父控件范围
                .resizable()
                // 自适应比例模式
                .aspectRatio(contentMode: .fit)
                // 设置最小、最大宽高
                .frame(minWidth: 0, idealWidth: 0, maxWidth: .infinity, minHeight: 0, idealHeight: 0, maxHeight: .infinity, alignment: .center)
            Text(scenery.location)
                // 字体
                .font(.largeTitle)
                // 四周边距
                .padding()
                // 颜色
                .foregroundColor(.secondary)
        }
        // 导航栏显示样式为inline
        .navigationBarTitle(Text(scenery.name), displayMode: .inline)
    }
}

这里是.infinity是指无穷大,结合.resizble和.fit的限制,图片就会在当前区域自动寻找到最合适的高度,这个应该比较好理解
根据截图可以看出Image和Text的区域



第八节 状态绑定和缩放动画
为了达到点击图片出现缩放的效果,我们需要给图片添加一个点击手势事件,并且需要用一个变量来记录点击的状态,这个我们就需要使用到状态绑定这个知识点。
关于@State的说明:加了@State注解的变量,视图通过监视和读取该变量来重新渲染UI。其状态是由SwiftUI来存储管理的,作为视图渲染的单一可信来源。
意思也很简单,就是一旦使用了@State修饰变量,一旦变量的值发生改变,SwiftUI就会自动刷新页面,不需要我们手动去刷新。
我们在View中定义一个用来记录缩放的变量zoomed,然后根据zoomed的状态来改变图片的显示模式,代码如下

struct SceneryView: View {
    
    let scenery: Scenery
    @State var zoomed = false
    
    var body: some View {
        
        // 对齐方式:底部右对齐
        ZStack(alignment: .bottomTrailing) {
            Image(scenery.imageName)
                // 让图片不超出父控件范围
                .resizable()
                // 根据zoomed状态进行调整
                .aspectRatio(contentMode: zoomed ? .fill : .fit)
                // 设置最小、最大宽高
                .frame(minWidth: 0, idealWidth: 0, maxWidth: .infinity, minHeight: 0, idealHeight: 0, maxHeight: .infinity, alignment: .center)
                .onTapGesture {
                    // toggle相当于对值取反
                    zoomed.toggle()
                }
            Text(scenery.location)
                // 字体
                .font(.largeTitle)
                // 四周边距
                .padding()
                // 颜色
                .foregroundColor(.secondary)
        }
        // 导航栏显示样式为inline
        .navigationBarTitle(Text(scenery.name), displayMode: .inline)
    }
}

到这里我们就实现了图片点击缩放的效果,也是超级简单。得力于@State状态绑定的特性,我们可以很快捷的得到我们想看到的预览效果。
接下来我们再给缩放添加一个简单动画效果:withAnimation

.onTapGesture {
      // toggle相当于对值取反
      withAnimation {
            zoomed.toggle()
      }
}

完成了图片的处理,紧接着我们开始对Text View的动画进行处理
首先我们完成消失/显示的处理

if !zoomed {
    Text(scenery.location)
           .font(.largeTitle)
           .foregroundColor(.secondary)
           .padding()
}

这里就是表示当zoomed为false时,显示Text View,为true时隐藏Text View。
另外还有一个向右边移动的动画,这个时候我们需要使用到 transition
在SwiftUI中,transition决定了某个View如何插入到视图栈中,或者如何在视图栈中移除。transition自身并没有任何效果, 需要配合动画一起使用

if !zoomed {
    Text(scenery.location)
           .font(.largeTitle)
           .foregroundColor(.secondary)
           .padding()
           // 向右边边距移动
           .transition(.move(edge: .trailing))
}

到这里我们所有的代码都写完了,可以说总共不到一百行的代码,却实现了很多内容。不得不说SwiftUI是真的简洁好用,已经不想写OC的代码了,哈哈哈。

你可能感兴趣的:(iOS SwiftUI基础学习(三))