SwiftUI模块系列 - 已更新23篇 SwiftUI项目 - 已更新2个项目 往期Demo源码下载

技术:SwiftUI、SwiftUI3.0、3D转换、视图切换、过渡动画 运行环境: SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max

SwiftUI搭建一个视图之间的立方体3D自定义转换过渡动画

概述详细一、运行效果二、项目结构图三、程序实现 - 过程1.创建一个项目命名为 `CustomTransition`1.1.引入资源文件和颜色2. 创建一个虚拟文件`New Group` 命名为 `View`3. 创建一个文件`New File` 选择`SwiftUI View`类型 命名为`Home`4. 创建一个文件`New File` 选择`SwiftUI View`类型 命名为`CubicTransition`

CodeContentView - 主窗口Home - 主页CubicTransition - `过渡动画`

概述

使用SwiftUI搭建一个视图之间的立方体3D自定义转换过渡动画

详细

一、运行效果

二、项目结构图

三、程序实现 - 过程

思路: 1.搭建主页部分 2.创建一个过渡动画的类、记录当前详情页和上一个页 、以及是否显示主页的属性 3.过渡动画类 处理当前页 和 下一个页面的偏移的逻辑处理 。比如当前页进行当前页跳转。下一个就进行3d动画过渡偏移整个屏幕

1.创建一个项目命名为 CustomTransition

1.1.引入资源文件和颜色

背景图片2张

2. 创建一个虚拟文件New Group 命名为 View

3. 创建一个文件New File 选择SwiftUI View类型 命名为Home

4. 创建一个文件New File 选择SwiftUI View类型 命名为CubicTransition

Code

ContentView - 主窗口

主要是展示主窗口Home

//

// ContentView.swift

// Shared

//

// Created by 李宇鸿 on 2022/9/4.

//

import SwiftUI

struct ContentView: View {

var body: some View {

Home()

}

}

struct ContentView_Previews: PreviewProvider {

static var previews: some View {

ContentView()

}

}

Home - 主页

思路: 1.搭建主页部分 2.创建一个过渡动画的类、记录当前详情页和上一个页 、以及是否显示主页的属性 3.过渡动画类 处理当前页 和 下一个页面的偏移的逻辑处理 。比如当前页进行当前页跳转。下一个就进行3d动画过渡偏移整个屏幕

//

// Home.swift

// CustomTransition (iOS)

//

// Created by 李宇鸿 on 2022/9/4.

//

import SwiftUI

struct Home: View {

@State var show : Bool = false

var body: some View {

GeometryReader{proxy in

let size = proxy.size

CubicTransition(show:$show) {

ZStack{

Image("Pic1")

.resizable()

.aspectRatio(contentMode: .fill)

.frame(width: size.width, height: size.height)

.clipped()

Button{

// 使用点击屏幕测试来回切换 引发bug的处理

// show.toggle()

}label: {

Text("Navigate")

.font(.title3)

.foregroundColor(.white)

.padding()

.background(.ultraThinMaterial)

.cornerRadius(10)

.environment(\.colorScheme, .dark)

}

.offset(y: 150)

}

} detail: {

Image("Pic2")

.resizable()

.aspectRatio(contentMode: .fill)

.frame(width: size.width, height: size.height)

.clipped()

}

}

.ignoresSafeArea()

.overlay(alignment: .top) {

HStack(spacing:12){

if show {

Button {

show.toggle()

} label: {

Image(systemName: "arrow.left")

.font(.title2)

.foregroundColor(.white)

}

}

Text(show ? "Back" : "Custom transition")

.font(.title.bold())

.foregroundColor(.white)

}

.padding()

.padding(.top,4)

.frame(maxWidth:.infinity,alignment: .leading)

.background(.ultraThinMaterial)

.environment(\.colorScheme, .dark)

}

.onTapGesture{

show.toggle()

}

}

}

struct Home_Previews: PreviewProvider {

static var previews: some View {

Home()

}

}

CubicTransition - 过渡动画

用来监听ScrollView的滚动 偏移量的改变

// CubicTransition.swift

// CustomTransition (iOS)

//

// Created by 李宇鸿 on 2022/9/4.

//

import SwiftUI

struct CubicTransition: View {

var cotnent: Content

var detail: Detail

// 显示视图

@Binding var show : Bool

init(show:Binding,

@ViewBuilder content: @escaping ()-> Content,

@ViewBuilder detail: @escaping()->Detail) {

self.detail = detail()

self.cotnent = content()

self._show = show

}

// 动画属性

@State var animateView : Bool = false

@State var showView : Bool = false

// 避免用户一直来回切换引起的bug - 没有将当前视图移除问题

@State var task : DispatchWorkItem?

var body: some View {

GeometryReader{proxy in

let size = proxy.size

HStack(spacing:0){

cotnent

.frame(width: size.width, height: size.height)

// 当detail View被push时旋转当前视图

.rotation3DEffect(.init(degrees: animateView ? -85 : 0), axis: (x: 0, y: 1, z: 0),anchor: .trailing,anchorZ: 0,perspective: 1)

// 显示详细信息视图

ZStack{

if showView {

detail.frame(width: size.width, height: size.height)

.transition(.move(edge: .trailing))

.onDisappear{

print("Colosed")

}

}

}

.rotation3DEffect(.init(degrees: animateView ? 0 : 85), axis: (x: 0, y: 1, z: 0),anchor: .leading,anchorZ: 0,perspective: 1)

}

// 应用抵消

.offset(x:animateView ? -size.width : 0)

}

.onChange(of: show) { newValue in

task?.cancel()

// 在动画星星前显示视图

if show {

showView = true

}

// 视图未被删除,因此它将产生内存问题

else {

//当动画完成时关闭视图

//在0.35秒之后

// 避免用户一直来回切换引起的bug - 没有将当前视图移除问题

// 为了避免这个问题

task = .init{

showView = false

}

if let task = task {

DispatchQueue.main.asyncAfter(deadline: .now() + 0.35,execute: task)

}

}

//为什么使用单独的变量而不是显示

//因为一旦它设置为false,它就会删除

//这样动画将不会完成

DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {

withAnimation(.easeInOut(duration: 0.35)){

animateView.toggle()

}

}

}

}

}

struct CubicTransition_Previews: PreviewProvider {

static var previews: some View {

ContentView()

}

}

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: