|
@@ -132,4 +132,331 @@ struct ButtonView: View {
|
|
|
}
|
|
|
|
|
|
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
+```
|
|
|
+//
|
|
|
+// AaronListView.swift
|
|
|
+// Aaronwei
|
|
|
+//
|
|
|
+// Created by ylkj on 2023/10/21.
|
|
|
+//
|
|
|
+
|
|
|
+import SwiftUI
|
|
|
+
|
|
|
+
|
|
|
+struct AaronListView_Previews: PreviewProvider {
|
|
|
+ static var previews: some View {
|
|
|
+ AaronListView(isPush: .constant(true))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+struct AaronListView: View {
|
|
|
+ @State var offset: CGSize = .zero
|
|
|
+ @Binding var isPush : Bool
|
|
|
+ @State public var showDetailInner = false
|
|
|
+ @Namespace var nameSpace
|
|
|
+
|
|
|
+ @Environment(\.presentationMode) var presentationMode
|
|
|
+
|
|
|
+ @State private var username: String = ""
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ ZStack(){
|
|
|
+ if showDetailInner {
|
|
|
+ withAnimation(.easeInOut){
|
|
|
+ TestDetailView(showDetailInner:$showDetailInner).padding(0).background(Color.white).zIndex(10).ignoresSafeArea(.all)
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ VStack{
|
|
|
+
|
|
|
+ ButtonDetailView(icon:"applelogo",text:"苹果")
|
|
|
+
|
|
|
+ List{
|
|
|
+ StreetRow(name: "The Lodon Street")
|
|
|
+
|
|
|
+ .onTapGesture {
|
|
|
+ showDetailInner.toggle()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }.background(Color.white.opacity(0.0))
|
|
|
+ .scaleEffect(getScale())
|
|
|
+ .offset(x: self.offset.width > 0 ? self.offset.width :0)
|
|
|
+ .gesture(DragGesture()
|
|
|
+ .onChanged{ value in
|
|
|
+ withAnimation(.spring()) {
|
|
|
+ offset = value.translation
|
|
|
+ print(offset)
|
|
|
+ if(offset.width > 160){
|
|
|
+ presentationMode.wrappedValue.dismiss()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .onEnded { value in
|
|
|
+ withAnimation(.spring()) {
|
|
|
+ offset = .zero
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func getScale() -> CGFloat {
|
|
|
+ let width = UIScreen.main.bounds.width / 2
|
|
|
+ let offsetX = abs(offset.width)
|
|
|
+ let percentage = offsetX / width
|
|
|
+ return 1.0 - min(0.5, percentage)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+struct StreetRow: View {
|
|
|
+
|
|
|
+ var name: String
|
|
|
+ @Namespace var shapeTransition
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ HStack(alignment: .center){
|
|
|
+ Text("1")
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .padding()
|
|
|
+ .background(Color.white)
|
|
|
+ .foregroundColor(.black)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.black, lineWidth: 3))
|
|
|
+
|
|
|
+ HStack(alignment: .center){
|
|
|
+ Image("applelogo").resizable().frame(width: 80, height: 80)
|
|
|
+ .background(.green)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.white, lineWidth: 4))
|
|
|
+ .shadow(radius: 5)
|
|
|
+
|
|
|
+
|
|
|
+ VStack(alignment: .leading){
|
|
|
+ Text("Queezy App")
|
|
|
+ .foregroundColor(Color(red: 50 / 255, green: 50 / 255, blue: 50 / 255))
|
|
|
+ .fontWeight(.bold)
|
|
|
+ Text("1888 rmb")
|
|
|
+ .foregroundColor(.gray)
|
|
|
+ .padding(.top,1)
|
|
|
+ }
|
|
|
+
|
|
|
+ }.frame(width: 240)
|
|
|
+ HStack{
|
|
|
+ Text("2")
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .padding()
|
|
|
+ .background(Color.white)
|
|
|
+ .cornerRadius(80)
|
|
|
+ .foregroundColor(.gray)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.gray, lineWidth: 3))
|
|
|
+ }.padding(.leading,10).padding(.top,4)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct ButtonDetailView: View {
|
|
|
+ var icon :String
|
|
|
+ var text :String
|
|
|
+ @Environment(\.presentationMode) var presentationMode
|
|
|
+
|
|
|
+ struct CustomButtonStyle: ButtonStyle {
|
|
|
+ func makeBody(configuration: Configuration) -> some View {
|
|
|
+ configuration.label
|
|
|
+ .font(.system(size: 12))
|
|
|
+ .frame(minWidth: 0, maxWidth: .infinity)
|
|
|
+ .padding()
|
|
|
+ .foregroundColor(Color(.white))
|
|
|
+ .background(Color.green)
|
|
|
+ .cornerRadius(20)
|
|
|
+ .padding(.horizontal, 10)
|
|
|
+ .padding(.vertical, 2)
|
|
|
+ .shadow(radius: 4)
|
|
|
+ .scaleEffect(configuration.isPressed ? 1.2 : 1)
|
|
|
+ .animation(.easeInOut(duration: 0.2), value: configuration.isPressed)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ VStack{
|
|
|
+ Button(action: {
|
|
|
+ presentationMode.wrappedValue.dismiss()
|
|
|
+ }){
|
|
|
+ HStack {
|
|
|
+ Image(systemName: icon)
|
|
|
+ .imageScale(.large)
|
|
|
+ Text(text)
|
|
|
+ .fontWeight(.semibold)
|
|
|
+ .font(.title)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .buttonStyle(CustomButtonStyle())
|
|
|
+ }
|
|
|
+ .font(.largeTitle)
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+struct TestDetailView: View {
|
|
|
+ @State var offset: CGSize = .zero
|
|
|
+ @Binding var showDetailInner : Bool
|
|
|
+ @State var isText = false
|
|
|
+ @State var offsetN: CGSize = .zero
|
|
|
+ @State var indexText: Int = 0
|
|
|
+
|
|
|
+ @Namespace var shapeTransition1
|
|
|
+ @Namespace var shapeTransition2
|
|
|
+ @Namespace var shapeTransition3
|
|
|
+ @Namespace var shapeTransition4
|
|
|
+ @Namespace var shapeTransitionD
|
|
|
+ let menuImages = ["house", "paperplane", "heart", "person.2"]
|
|
|
+
|
|
|
+
|
|
|
+ @Environment(\.presentationMode) var presentationMode
|
|
|
+ func getScaleN() -> CGFloat {
|
|
|
+ let width = UIScreen.main.bounds.width / 2
|
|
|
+ let offsetX = abs(offsetN.width)
|
|
|
+ let percentage = offsetX / width
|
|
|
+ return 1.0 - min(0.5, percentage)
|
|
|
+ }
|
|
|
+ var body: some View {
|
|
|
+ ZStack {
|
|
|
+ if isText {
|
|
|
+ // Rounded Rectangle
|
|
|
+ VStack(alignment: .center){
|
|
|
+
|
|
|
+
|
|
|
+ Image("applelogo").frame(minWidth: 0, maxWidth: .infinity,minHeight: 0,maxHeight: 400)
|
|
|
+ .background(.green)
|
|
|
+ .shadow(radius: 5)
|
|
|
+ .matchedGeometryEffect(id: "circle1\(indexText)", in: shapeTransition2,isSource: isText)
|
|
|
+ VStack(alignment: .leading){
|
|
|
+ Text("Queezy App")
|
|
|
+ .foregroundColor(Color(red: 50 / 255, green: 50 / 255, blue: 50 / 255))
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .matchedGeometryEffect(id: "circle2\(indexText)", in: shapeTransition3,isSource: isText)
|
|
|
+ Text("1888 rmb")
|
|
|
+ .foregroundColor(.gray)
|
|
|
+ .padding(.top,1)
|
|
|
+ .matchedGeometryEffect(id: "circle3\(indexText)", in: shapeTransition4,isSource: isText)
|
|
|
+ }
|
|
|
+
|
|
|
+ Text("\(indexText)")
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .padding()
|
|
|
+ .background(Color.white)
|
|
|
+ .cornerRadius(80)
|
|
|
+ .foregroundColor(.gray)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.gray, lineWidth: 3))
|
|
|
+ .matchedGeometryEffect(id: "circleD\(indexText)", in: shapeTransitionD,isSource: isText)
|
|
|
+ Text("1\(indexText)")
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .padding()
|
|
|
+ .background(Color.white)
|
|
|
+ .foregroundColor(.black)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.black, lineWidth: 3))
|
|
|
+ .matchedGeometryEffect(id: "circle4\(indexText)", in: shapeTransition1,isSource: isText)
|
|
|
+ Spacer()
|
|
|
+
|
|
|
+ }.onTapGesture {
|
|
|
+ withAnimation(.easeInOut){
|
|
|
+ isText.toggle()
|
|
|
+ }
|
|
|
+ }.zIndex(10).background(Color.white.opacity(0.4))
|
|
|
+ .scaleEffect(getScaleN())
|
|
|
+ .offset(x: self.offsetN.width > 0 ? self.offsetN.width :0)
|
|
|
+ .gesture(DragGesture()
|
|
|
+ .onChanged{ value in
|
|
|
+ withAnimation(.spring()) {
|
|
|
+ offsetN = value.translation
|
|
|
+ if(offsetN.width > 180){
|
|
|
+ isText.toggle()
|
|
|
+ }else{
|
|
|
+ offsetN = .zero
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .onEnded { value in
|
|
|
+ withAnimation(.spring()) {
|
|
|
+ offsetN = .zero
|
|
|
+ isText = false
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ )
|
|
|
+ }else{
|
|
|
+ VStack{
|
|
|
+ ForEach(menuImages.indices,id:\.self){ index in
|
|
|
+ HStack(alignment: .center){
|
|
|
+ Text("\(index)")
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .padding()
|
|
|
+ .background(Color.white)
|
|
|
+ .foregroundColor(.black)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.black, lineWidth: 3))
|
|
|
+ .matchedGeometryEffect(id: "circle2\(index)", in: shapeTransition1,isSource: !isText)
|
|
|
+ HStack(alignment: .center){
|
|
|
+ Image("applelogo").resizable().frame(width: 80, height: 80)
|
|
|
+ .background(.green)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.white, lineWidth: 4))
|
|
|
+ .shadow(radius: 5)
|
|
|
+ .matchedGeometryEffect(id: "circle1\(index)", in: shapeTransition2)
|
|
|
+
|
|
|
+ VStack(alignment: .leading){
|
|
|
+ Text("Queezy App")
|
|
|
+ .foregroundColor(Color(red: 50 / 255, green: 50 / 255, blue: 50 / 255))
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .matchedGeometryEffect(id: "circle3\(index)", in: shapeTransition3,isSource: !isText)
|
|
|
+ Text("1888 rmb")
|
|
|
+ .foregroundColor(.gray)
|
|
|
+ .padding(.top,1)
|
|
|
+ .matchedGeometryEffect(id: "circle4\(index)", in: shapeTransition4,isSource: !isText)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }.frame(width: 240)
|
|
|
+ HStack{
|
|
|
+ Text("1\(index)")
|
|
|
+ .fontWeight(.bold)
|
|
|
+ .padding()
|
|
|
+ .background(Color.white)
|
|
|
+ .cornerRadius(80)
|
|
|
+ .foregroundColor(.gray)
|
|
|
+ .clipShape(Circle())
|
|
|
+ .overlay(Circle().stroke(Color.gray, lineWidth: 3))
|
|
|
+ .matchedGeometryEffect(id: "circleD\(index)", in: shapeTransitionD,isSource: !isText)
|
|
|
+ }.padding(.leading,10).padding(.top,4)
|
|
|
+
|
|
|
+ }.onTapGesture {
|
|
|
+ withAnimation(.easeInOut){
|
|
|
+ isText.toggle()
|
|
|
+ indexText = index
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
```
|