- SwiftUI框架详细解析 (三) —— 基于SwiftUI的闪
- SwiftUI框架详细解析 (二) —— 基于SwiftUI的闪
- SwiftUI框架详细解析 (二十) —— 基于SwiftUI的
- SwiftUI框架详细解析 (十) —— 基于SwiftUI构建
- SwiftUI框架详细解析 (十三) —— 基于SwiftUI创
- SwiftUI框架详细解析 (十二) —— 基于SwiftUI创
- SwiftUI框架详细解析 (十一) —— 基于SwiftUI构
- SwiftUI框架详细解析 (十六) —— 基于SwiftUI简
- SwiftUI框架详细解析 (十七) —— 基于SwiftUI简
- SwiftUI框架详细解析 (六) —— 基于SwiftUI的导
版本记录
版本号 | 时间 |
---|---|
V1.0 | 2019.09.16 星期一 |
前言
今天翻阅苹果的API文档,发现多了一个框架SwiftUI,这里我们就一起来看一下这个框架。感兴趣的看下面几篇文章。
1. SwiftUI框架详细解析 (一) —— 基本概览(一)
2. SwiftUI框架详细解析 (二) —— 基于SwiftUI的闪屏页的创建(一)
源码
1. Swift
首先看下工程组织结构
下面看一下代码
1. AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: - UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
}
2. SceneDelegate.swift
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()
}
}
}
3. ContentView.swift
import SwiftUI
import MapKit
struct ContentView: View {
@State var showSplash = true
var body: some View {
ZStack{
MapView(coordinate: CLLocationCoordinate2DMake(37.331820, -122.03118))
.edgesIgnoringSafeArea(.all)
SplashScreen()
.opacity(showSplash ? 1 : 0)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
SplashScreen.shouldAnimate = false
withAnimation() {
self.showSplash = false
}
}
}
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
4. SplashScreen.swift
import SwiftUI
struct SplashScreen: View {
static var shouldAnimate = true
let fuberBlue = Color("Fuber blue")
let uLineWidth: CGFloat = 5
let uZoomFactor: CGFloat = 1.4
let lineWidth: CGFloat = 4
let lineHeight: CGFloat = 28
let uSquareLength: CGFloat = 12
@State var percent = 0.0
@State var uScale: CGFloat = 1
@State var squareColor = Color.white
@State var squareScale: CGFloat = 1
@State var lineScale: CGFloat = 1
@State var textAlpha = 0.0
@State var textScale: CGFloat = 1
@State var coverCircleScale: CGFloat = 1
@State var coverCircleAlpha = 0.0
var body: some View {
ZStack {
Image("Chimes")
.resizable(resizingMode: .tile)
.opacity(textAlpha)
.scaleEffect(textScale)
Circle()
.fill(fuberBlue)
.frame(width: 1, height: 1,
alignment: .center)
.scaleEffect(coverCircleScale)
.opacity(coverCircleAlpha)
Text("F BER")
.font(.largeTitle)
.foregroundColor(.white)
.opacity(textAlpha)
.offset(x: 20, y: 0)
.scaleEffect(textScale)
FuberU(percent: percent)
.stroke(Color.white, lineWidth: uLineWidth)
.rotationEffect(.degrees(-90))
.aspectRatio(1, contentMode: .fit)
.padding(20)
.onAppear() {
self.handleAnimations()
}
.scaleEffect(uScale * uZoomFactor)
.frame(width: 45, height: 45,
alignment: .center)
Rectangle()
.fill(squareColor)
.scaleEffect(squareScale * uZoomFactor)
.frame(width: uSquareLength, height: uSquareLength,
alignment: .center)
.onAppear() {
self.squareColor = self.fuberBlue
}
Rectangle()
.fill(fuberBlue)
.scaleEffect(lineScale, anchor: .bottom)
.frame(width: lineWidth, height: lineHeight,
alignment: .center)
.offset(x: 0, y: -22)
Spacer()
}
.background(fuberBlue)
.edgesIgnoringSafeArea(.all)
}
}
extension SplashScreen {
var uAnimationDuration: Double { return 1.0 }
var uAnimationDelay: Double { return 0.2 }
var uExitAnimationDuration: Double { return 0.3 }
var finalAnimationDuration: Double { return 0.4 }
var minAnimationInterval: Double { return 0.1 }
var fadeAnimationDuration: Double { return 0.4 }
func handleAnimations() {
runAnimationPart1()
runAnimationPart2()
runAnimationPart3()
if SplashScreen.shouldAnimate {
restartAnimation()
}
}
func runAnimationPart1() {
withAnimation(.easeIn(duration: uAnimationDuration)) {
percent = 1
uScale = 5
lineScale = 1
}
withAnimation(Animation.easeIn(duration: uAnimationDuration).delay(0.5)) {
textAlpha = 1.0
}
let deadline: DispatchTime = .now() + uAnimationDuration + uAnimationDelay
DispatchQueue.main.asyncAfter(deadline: deadline) {
withAnimation(.easeOut(duration: self.uExitAnimationDuration)) {
self.uScale = 0
self.lineScale = 0
}
withAnimation(.easeOut(duration: self.minAnimationInterval)) {
self.squareScale = 0
}
withAnimation(Animation.spring()) {
self.textScale = self.uZoomFactor
}
}
}
func runAnimationPart2() {
let deadline: DispatchTime = .now() + uAnimationDuration + uAnimationDelay + minAnimationInterval
DispatchQueue.main.asyncAfter(deadline: deadline) {
self.squareColor = Color.white
self.squareScale = 1
withAnimation(.easeOut(duration: self.fadeAnimationDuration)) {
self.coverCircleAlpha = 1
self.coverCircleScale = 1000
}
}
}
func runAnimationPart3() {
DispatchQueue.main.asyncAfter(deadline: .now() + 2*uAnimationDuration) {
withAnimation(.easeIn(duration: self.finalAnimationDuration)) {
self.textAlpha = 0
self.squareColor = self.fuberBlue
}
}
}
func restartAnimation() {
let deadline: DispatchTime = .now() + 2*uAnimationDuration + finalAnimationDuration
DispatchQueue.main.asyncAfter(deadline: deadline) {
self.percent = 0
self.textScale = 1
self.coverCircleAlpha = 0
self.coverCircleScale = 1
self.handleAnimations()
}
}
}
struct FuberU: Shape {
var percent: Double
func path(in rect: CGRect) -> Path {
let end = percent * 360
var p = Path()
p.addArc(center: CGPoint(x: rect.size.width/2, y: rect.size.width/2),
radius: rect.size.width/2,
startAngle: Angle(degrees: 0),
endAngle: Angle(degrees: end),
clockwise: false)
return p
}
var animatableData: Double {
get { return percent }
set { percent = newValue }
}
}
#if DEBUG
struct SplashScreen_Previews : PreviewProvider {
static var previews: some View {
SplashScreen()
}
}
#endif
5. MapView.swift
import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
#if DEBUG
struct MapView_Previews : PreviewProvider {
static var previews: some View {
MapView(coordinate: CLLocationCoordinate2DMake(0,0))
}
}
#endif
后记
本篇主要讲述了基于SwiftUI的闪屏页的创建,感兴趣的给个赞或者关注~~~
网友评论