Pull up and down the UIView with x

Edit

This is what I want to visualize (ignore the ugly red line, it just indicates the movement of the UIView):

enter image description here

I want to have a UIView that is initialized in the middle of the screen. After that, I want to give him a push up, and gravity will pull him down until he is on the screen. My old question is working with UIPushBehaviour, UIDynamicBehaviour and UIGravityBehaviour (see below). Matt pointed out that UIPushBehaviour may not be the right choice, as it doesn't work very well with every screen size available on iOS.

I can do this with the UIView.animate function, but it is really static and does not look natural. With UIPushBehaviour, UIDynamicBehaviour and UIGravityBehaviour, this looks very good, but the UIPushBehaviour value cannot be calculated for each screen size to give the same endpoint for the UIView x and y position.

Question

How can I initialize a UIView in the middle of the screen, pull this UIView (with some change in x position) and let gravity (or something else) pull it down until it exits the screen? It is important that the x and y positions are the same for every screen size.

Below is my old question

I have a UIPushBehaviour with instantaneous as the mode in which I click around the UIView . The larger the screen, the less it pushes.
I also have a UIDynamicItemBehavior with resistance set to 1 , I think this is one of the main reasons why it is different in every screen size (correct me if I am wrong).

I need a function that will press UIView on the same endpoint, with the same speed, duration and endpoint, regardless of screen size.

I tried to make a relative value with no luck:

For the iPhone 5S, let's say a magnitude of 0.5 touches the UIView from mid to top. I wanted to calculate the value on all devices, such as:

 let y = 0.5 / 520 // 5S screen height magnitude = self.view.frame.height * y 

For iPhone 8, it has an excellent result and does not work. When I read the documents , I thought I would understand this. I thought that 1 value is 100 pixels, but this is clearly not the case.
Is it possible to calculate a value, for example, to move a UIView from the middle to the right?

I did a project here . There is a black UIView that pushes to the edges on the iPhone 5, but not on the iPhone 8.

+5
source share
1 answer

Decision

You need to scale the amount of pressure relative to the screen size so that your image always ends in one place. To do this, adjusting the UIPushBehavior pushDirection vector works quite well. In this case, I set the direction of the shock in proportion to the boundaries of the view and reduced it by a constant coefficient.

 let push = UIPushBehavior(items: [pushView], mode: .instantaneous) let pushFactor: CGFloat = 0.01 push.pushDirection = CGVector(dx: -view.bounds.width * pushFactor, dy: -view.bounds.height * pushFactor) animator.addBehavior(push) 

You may need to tweak some constants to get the animation you need. Constants you can customize:

  • Gravity magnitude (currently 0.3)
  • Push factor (currently 0.01)

Depending on your needs, you may need to scale the scale of gravity proportional to the size of the screen.

Note. These constants will need to change depending on the size of your animated view, since UIKit Dynamics considers the size of the view as its mass. If your view needs to be dynamically different, you will need to scale your constants according to the size of the animated view.

Edit comments on the original question:

  • Views of different sizes. As I mentioned in my article above, you will need to apply an additional factor to take into account the "mass" of views. Something like view.frame.height * view.frame.width * someConstant should work fine.

  • IPad Screen Size: pushFactor is pushFactor applied to the dx and dy components of the vector. Since iPads have different aspect ratios, you need to split it into two constants, possibly xPushFactor and yPushFactor , which can take into account differences in aspect ratio.

Examples

iPhone 8

gif solutions for iPhone 8 screen size

iPhone SE

gif iPhone SE size solutions

Source code for the full playground

Copy and paste this code into the Swift playing field to see it in action. I have included the sizes of the different screens of the iPhone, so just uncomment the size you want to easily test on different sizes of the device. Most of the interesting / relevant code is in viewDidAppear .

 import UIKit import PlaygroundSupport class ViewController: UIViewController { let pushView = UIView() var animator: UIDynamicAnimator! override func viewDidLoad() { super.viewDidLoad() view.frame = CGRect(x: 0, y: 0, width: 568, height: 320) // iPhone SE // view.frame = CGRect(x: 0, y: 0, width: 667, height: 375) // iPhone 8 // view.frame = CGRect(x: 0, y: 0, width: 736, height: 414) // iPhone 8+ // view.frame = CGRect(x: 0, y: 0, width: 812, height: 375) // iPhone X view.backgroundColor = .white let pushViewSize = CGSize(width: 200, height: 150) pushView.frame = CGRect(x: view.bounds.midX - pushViewSize.width / 2, y: view.bounds.midY - pushViewSize.height / 2, width: pushViewSize.width, height: pushViewSize.height) pushView.backgroundColor = .red view.addSubview(pushView) animator = UIDynamicAnimator(referenceView: self.view) let dynamic = UIDynamicItemBehavior() dynamic.resistance = 1 animator.addBehavior(dynamic) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let gravity = UIGravityBehavior(items: [pushView]) gravity.magnitude = 0.3 animator.addBehavior(gravity) let push = UIPushBehavior(items: [pushView], mode: .instantaneous) let pushFactor: CGFloat = 0.01 push.pushDirection = CGVector(dx: -view.bounds.width * pushFactor, dy: -view.bounds.height * pushFactor) animator.addBehavior(push) } } let vc = ViewController() PlaygroundPage.current.needsIndefiniteExecution = true PlaygroundPage.current.liveView = vc.view 
+4
source

Source: https://habr.com/ru/post/1272369/


All Articles