Changing origin point of an animation of a UIImage in Swift3 - ios

I have the following code, which basically just grows a UIImage from 0 to its intended height:
let bounds = self.tankLevelRep.bounds
UIView.transition(with: self.tankLevelRep, duration: 2.0, animations: {self.tankLevelRep.bounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: 118.0)}, completion: nil)
This works fine except for the fact that it grows from the middle. I would like it to grow upwards from the bottom. The attached graphic shows the animation as it nears its end. You can see that the animation is not starting from the bottom, but rather, from the center, and growing outwards. I would like for it to start at the bottom, and the image to grow upwards.
What can I change in my code to make this happen?
Notes:
• "tankLevelRep" is the outlet name for my UIImage

You should update the frame and the bounds mirror the change, in your code make sure you animate from the bottom by setting the origin to bounds.size.height instead of the origin.y. Here is a nice fill animation from another post.

Related

swift: Move animation

I have viewController in storyboard. And 4 squares. I want to place my squares on view. At first I want to show two squares. If I press on button I want to my red 2 squares move left and I show next 2 blue squares. Like this animation.
Do I need to create a scrollView or collectionView or something else to move the squares? What the best way to create this?
Use UiVew.animate and CGAffineTransform
Setup
Create a UIView that will contain your squares. Make sure that UIView has clip to bounds enabled. Then, add your four squares in, with the blue ones nested inside the UIView, but with their coordinates outside of the container so that they're getting clipped.
Then, when you want to move them, you simply translate all of your squares x to the left. By putting this movement inside of a UIView.animate block, iOS will perform the animation for you.
UIView.animate(withDuration: 2.0) {
self.redTopView.transform = CGAffineTransform(translationX: -160, y: 0)
self.redBottomView.transform = CGAffineTransform(translationX: -160, y: 0)
self.blueTopView.transform = CGAffineTransform(translationX: -160, y: 0)
self.blueBottomView.transform = CGAffineTransform(translationX: -160, y: 0)
}
Final result: http://g.recordit.co/SToMSZ77wu.gif

How to specify position that popover controller's arrow points to

It's well known that in order to present UIAlertController with preferredStyle: .actionSheet, it's a good practice to set an anchor using the next code:
popover.sourceView = view
popover.sourceRect = view.bounds
In my case, the view is UIImageView, it's size is 44x44, but its image (three vertical dots) is very thin (its size is 4x24). So the view is mostly transparent. As a result, popover "points" to empty space. (Note that I am using red color to show fully transparent area)
Ideally, popover's arrow should point to the central white dot. But I do not know how to achieve it. I tried to modify sourceRect as follows:
popover.sourceRect = CGRect(x: view.bounds.midX - 1,
y: view.bounds.midY - 1,
width: 2,
height: 2)
but it points to the top white dot for some reason:
How can I make it pointing to the desired point?
The sourceRect worked for me, i just used the y coordinates to position the arrow and it worked for me.
popover.sourceRect = CGRect(x: 0, y: yourPosition, width: 0, height: 0)
You can also have a look at this.

Unable to minimize subview alongside mainView during animation

I have two views, videoView (which is the mainView) and subVideoView (which is the subView of mainView).
I am trying to minimize both views using animation at the same time, as shown in the below code. I am able to minimize the videoView (i.e mainView) and not the subVideoView.
However, when I hide code for minimising videoView (i.e mainView), I am able to minimise the subVideoView.
I believe it has to do something with the way I am animating.
Can some one please advice how I can minimise both views (proportionally) with animation at the same time and end up with the below result.
RESULTS OF EXISTING CODE
func minimiseOrMaximiseViews(animationType: String){
UIView.animate(withDuration: 0.5, delay: 0, options: [],
animations: { [unowned self] in
switch animationType {
case "minimiseView" :
// Minimising subVideoView
self.subVideoView.frame = CGRect(x: self.mainScreenWidth - self.minSubVideoViewWidth - self.padding,
y: self.mainScreenHeight - self.minSubVideoViewHeight - self.padding,
width: self.minSubVideoViewWidth,
height: self.minSubVideoViewHeight)
// Minimising self i.e videoView
self.frame = CGRect(x: self.mainScreenWidth - self.videoViewWidth - self.padding,
y: self.mainScreenHeight - self.videoViewHeight - self.padding,
width: self.videoViewWidth,
height: self.videoViewHeight)
self.layoutIfNeeded()
case "maximiseView":
// Maximising videoView
self.frame = CGRect(x: 0, y: 0, width: self.mainScreenSize.width, height: self.mainScreenSize.height)
// Maximising subVideoView
self.subVideoView.frame = CGRect(x: self.mainScreenWidth - self.maxSubVideoViewWidth - self.padding,
y: self.mainScreenHeight - self.maxSubVideoViewHeight - self.padding - self.buttonStackViewBottomPadding - buttonStackViewHeight,
width: self.maxSubVideoViewWidth,
height: self.maxSubVideoViewHeight)
default:
break
}
As per your requirement add subViews in mainView and set
mainView.clipsToBounds = true
and In the minimiseOrMaximiseViews method you just need to manage Y axis of mainView for show and hide.
I could minimise both views simultaneously using animation, when I've set both views (videoView and subVideoView) as subViews of window i.e UIApplication.shared.keywindow.
Unless I'm missing something, this kind of animation is much more easily achieved by animating the transform property of the videoView (the main view). You will need to concatenate scaling and translation transforms for that, because scaling is by default applied to a view's center.
The trick is that applying a transform to a view affects all its subviews automatically, e.g. applying a scaling transform to a view scales both the view and all its subviews.
To make a reverse animation just set videoView.transform = CGAffineTransformIdentity inside an animation block.
Caveat: You should be careful, though, with the frame property of a transformed view. The frame property is synthetic and is derived from bounds, center and transform. This means that setting a view's frame resets its transform property. In other words, if you manipulate your views using transform, you most likely want to avoid setting their frames directly.

UIScrollview zoomToRect center of currently visible view

I have a UIScrollView displaying a image. I want to programmatically zoom in to the a rect somewhere near the center (doesn't have to be exact) of the currently visible area. How would I get the coordinates of this rect to use with zoomToRect? Note that this image could be already zoomed in and only showing a fraction of the scrollView content area.
The the X and Y position of that image are relative to the scrollview's contentSize. The area shown on screen is defined by the scrollview's contentOffset.
You then take the position of your scrollview on screen and the position of the selection rectangle on your screen.
Finally you need to do rather simple maths (a few additions/subtractions) for both X and Y using the above values.
Grab UIImageView's frame and call insetBy(dx:dy:):
Returns a rectangle that is smaller or larger than the source
rectangle, with the same center point.
From Apple Documentation
Here's a quick visualisation in a PlayGround:
let blueSquare = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
let yellowSquare = UIView(frame: blueSquare.frame.insetBy(dx: 100, dy: 100))
blueSquare.backgroundColor = .blue
yellowSquare.backgroundColor = .yellow
blueSquare.addSubview(yellowSquare)
Will result in this:

Scale a UIView Horizontally

I'm trying to scale a view Horizontally but i'm not getting the results i expected.
view.bounds = CGRectMake(view.bounds.origin.x, view.bounds.origin.y , view.bounds.size.width * scaleX, view.bounds.size.height );
view.center = CGPointMake(view.bounds.origin.x, view.center.y);
As you can see at the code above, i want to scale the view just to the right side. This is why i changed the center of the view.
The problem is that the view stills scaling to both sides!
I did the same logic to scale another UIView vertically and got the result i expected.
Just found the problem.
when setting certer, the new point must be relative to frame, not bounds.
so, i get the code:
view.center = CGPointMake(-view.frame.origin.x, view.center.y);
Hope it helps somebody..
Thx for help
If the origin of your view's frame is in the top-left (which is the default), increasing the width of your view should scale it to the right only.
This should work:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width * scaleX, view.frame.size.height);
You do not need to adjust the origin/center point to scale only to the right.
Try using an affine transform instead:
view.transform = CGAffineTransformMakeScale(scaleX, 1)
And then setting the center.

Resources