5

I am trying to animate UITextView by changing transform. But it makes text disappered while animating. Here is my test code.

class ViewController: UIViewController {
    let textView = UITextView()

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        textView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(textView)
        
        textView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        textView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        textView.heightAnchor.constraint(equalToConstant: 300).isActive = true
        textView.backgroundColor = .systemOrange
        textView.text = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"
        textView.textColor = .white

        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            let animator = UIViewPropertyAnimator(duration: 2, curve: .easeInOut, animations:  {
                self.textView.transform = CGAffineTransform(translationX: 0, y: 1000)
            })
            animator.startAnimation()
        }
    }
}

Demo

I tried with storyboard but the result was same. Same result when I use UIView.animate method.

Why does this happen? I want to animate it with text on.

UPDATE

let contraint = textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
contraint.isActive = true

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    contraint.constant = 1000
    let animator = UIViewPropertyAnimator(duration: 2, curve: .easeInOut, animations:  {
        self.view.layoutIfNeeded()
    })
    animator.startAnimation()
}

I tested with this code, and got same result.

Paul
  • 759
  • 2
  • 7
  • 20
  • @matt I tried to animate top constraint, and got same result. I updated my question. – Paul Jul 26 '20 at 16:04
  • Yup I agree. Darn! Okay, I do have one very obvious suggestion: animate a snapshot instead. Sorry, but it might be the best way. I'll whip up an example. – matt Jul 26 '20 at 16:04
  • @matt Yeah. Animating a snapshot works perfect. I tested it before. – Paul Jul 26 '20 at 16:06
  • Gave it as an answer anyway. No bad thing; this is what snapshot views are for, after all, i.e. to give you something to animate. – matt Jul 26 '20 at 16:09

1 Answers1

4

I'm afraid you'll have to animate a snapshot view instead:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    let v = self.textView.snapshotView(afterScreenUpdates: true)!
    v.frame = self.textView.frame
    self.view.addSubview(v)
    self.textView.isHidden = true
    let animator = UIViewPropertyAnimator(duration: 2, curve: .easeInOut, animations:  {
        v.frame.origin.y = 1000
    })
    animator.startAnimation()
}

I don't think that's a bad solution; this is what snapshot views are for, after all.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Yeah. This is good. Actually I animate transform during interactive transition. But finding all UITextView subviews of view takes some time, so I want to avoid it. – Paul Jul 26 '20 at 16:13
  • Oooooh that sounds like a different question. I actually have a cool utility that will find all UITextView subviews instantly. :) https://stackoverflow.com/a/58138866/341994 — It sounds to me like you haven't really asked the right question here, though; clearly what you want to do is a lot more interesting than the example you gave. I'm glad you gave the simple example, because you made it really easy to reproduce the issue; but more broadly you evidently want to make text views user-draggable or some such. – matt Jul 26 '20 at 16:14
  • yeah, it's a different question though, I don't know why this simple example doesn't works. – Paul Jul 26 '20 at 16:18
  • File a bug with Apple if you think the text view should keep displaying its text while being animated. But clearly it doesn't, you proved that; so we have to work around it. – matt Jul 26 '20 at 16:29