bywang
bywang

Reputation: 21

How to page down a Rectangle in SwiftUI?

I am a new player for swiftui dev. And I want to write a page-down clock to study swiftui. But I stuck on how to page-down a page, which means rotate the object around x axis. And I know rotate3DEffect would generate strange result.

Here is my code:

 Rectangle() // the view
 .frame(width: 100, height: 100, alignment: .center)
 .foregroundColor(.white)
 .accessibilityAction {
     let a = UIView(frame: CGRect(origin: CGPoint(x: 10,y: 10), size: CGSize(width: 1, height: 2)))
     a.backgroundColor = .blue
                
     let b = UIView(frame: CGRect(origin: CGPoint(x: 10,y: 10), size: CGSize(width: 1, height: 2)))
     b.backgroundColor = .yellow
                
     let c = UIView(frame: CGRect(origin: CGPoint(x: 10,y: 10), size: CGSize(width: -1, height: -2)))
     c.backgroundColor = .red
                
     rotation(first: a,back: b,solid: c)
                
            }


func rotation<V>(first: V, back: V, solid: V) where V: UIView{
    // rotationFront
    // rotationBack
    /*
    | B|/C
    | A|
     */
    rotationFront(first: first)
    rotationBack(back: back)
}
func rotationFront<V>(first: V) where V: UIView {
    let animation = CABasicAnimation(keyPath: "transform.rotation.x")
    animation.fromValue = (10/360)*Double.pi
    animation.toValue = (355/360)*Double.pi
    animation.duration = 1.0
    animation.repeatCount = 0
    
    first.layer.add(animation, forKey: "rotationBack")
}

func rotationBack<V>(back: V) where V: UIView {
    let animation = CABasicAnimation(keyPath: "transform.rotation.x")
    animation.fromValue = (10/360)*Double.pi
    animation.toValue = (355/360)*Double.pi
    animation.duration = 1.0
    animation.repeatCount = 0
    back.layer.add(animation, forKey: "rotationFront")
}

It does nothing. What should I do? Thanks a lot.

Upvotes: 2

Views: 97

Answers (1)

Gry
Gry

Reputation: 111

Hmm i feel you're missing the base of how swiftui works with views, and you patched some solutions from uikit to rotate things. I would suggest to watch some wwdc videos about swiftui or follow some base courses like the one that standford provide free on their youtube channel. Here a video that helps with your idea https://youtu.be/3krC2c56ceQ

I added a solution that i come up on the fly but i would suggest to follow the Standford video because it provide a more complete solution where they use the AnimationModifier to handle the change from face up to flipped. To animate rotations you should use the .rotation3DEffect or .rotationEffect modifiers (it depends on the usecase).

BTW here the base idea:

  1. flip to 90° using the .rotation3DEffect so the card is not visible on the x axis
  2. change the number incrementing the value
  3. flip the number so is not rotated with .scale
  4. complete the flip of 180 so the number is visible with the incremented value
struct PageDownExampleView: View {
    @State var counterx1: Int = 0
    @State var progressx1: Double = 0
    @State var flip: Bool = false

    var body: some View {
        VStack {
            Text("\(counterx1)")
                .font(.system(size: 70, weight: .bold))
                .foregroundColor(.white)
                .frame(width: 100, height: 100, alignment: .center)
                .background(Color.black)
                .scaleEffect(CGSize(width: 1.0,
                                    height: flip ? -1 : 1.0))
                .rotation3DEffect(.degrees(progressx1),
                                  axis: (x: 1.0, y: 0.0, z: 0.0),
                                  anchor: .center,
                                  anchorZ: 0.0,
                                  perspective: 0.5)
                .padding(15)
                .border(Color.black, width: 9)
            Button(action: {
                withAnimation {
                    progressx1 += -90
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        flip.toggle()
                        counterx1 += 1
                        withAnimation {
                            progressx1 += -90
                        }
                    }
                }
            }, label: {
                HStack(spacing: 5) {
                    Image(systemName: "playpause.fill")
                    Text("Start / Stop".uppercased())
                }
            })
                .padding()
                .border(Color.black, width: 1)
        }
    }
}

Side note:

the uiviews you created are part of UIKit framework and you're creating view applying a transform rotation. The first error is how you try to use uikit components in swiftui (your missing how to connect the two frameworks, you can search for UIViewRepresentable for the topic), and accessibilityAction handles only actions, they don't show anything.

Upvotes: 2

Related Questions