I have a horizontal scrollview with an image which I need to rotate as the user scrolls left or right. It needs to rotate as the user moves the scroll across the screen. So if the user scrolls half way and stops the image should rotate halfway etc. I have looked at few examples but nothing seems to be giving me the correct result. Can some one please help.
Thanks in advance
Vertical scrolling and Swift 5:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let topOffset = scrollView.contentOffset.y
let angle = -topOffset * 2 * CGFloat(Double.pi / 180)
self.myImageView.transform = CGAffineTransform(rotationAngle: angle)
}
Don't forget to do this in viewDidLoad:
self.scrollView.delegate = self
You'll need to implement the scrollViewDidScroll method and then apply a rotation matrix to the image. To rotate a UIIMage you can do what they outline here. How to Rotate a UIImage 90 degrees?
However, this would be better accomplished in a pan gesture recognizer. The pan gesture will give you information about how far the user panned, and then you can rotate the image based on that distance.
To rotate image is not good for performance. You'd better set image view's rotate transform as user scrolls. Like this:
imageView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
Related
Problem:
I got a Tableview with dynamically many cells. The cells contain PKDrawings with the PencilKit Framework. So its like a book...
I would like to do 2 things:
1. Zoom in so i am closer to the cells-content so the drawings seem bigger.
(But when I say cells-content I mean all cells so I am talking about the Tableview. I don't want to zoom into a specific cell)
2. Zoom out so I start seeing more and more pages (cells) above and below the one that was "in my focus" when not zooming out or in.
If that's not possible as the Cells are Hidden and its hard to tell them while zooming out when to load again its fine if the maximal zoom-out is the point when I haven't zoomed in.
As a Tableview is already a subclass of the UIScrollview I can access its min & max Zoomscale. However setting this doesn't change anything. The ScrollViewDidZoom won't get triggered either.
Scrolling works fine though...
I think that this should all be possible if I somehow manage it to put my Tableview into another View/Scrollview and just zoom in/out on that but I don't know how to do that...
Thanks in advance for any help!
For zooming UITableview cell u can use CGAffineTransform. You can manage the scale value as per requirement
// For Zoom in
CGAffineTransform trans = CGAffineTransformScale(cell.contentView.transform, 100, 100);
view.transform = trans;
// For Zoom Out
CGAffineTransform trans = CGAffineTransformScale(cell.contentView.transform, 0.01, 0.01);
view.transform = trans;
To zoom complete UItableView you can apply affine transform to tableview
// For Zoom in
CGAffineTransform trans = CGAffineTransformScale(tableView.transform, 100, 100);
view.transform = trans;
// For Zoom Out
CGAffineTransform trans = CGAffineTransformScale(tableView.transform, 0.01, 0.01);
view.transform = trans;
For pinch gesture u can use following gestures well documented by apple developer documentation https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_uikit_gestures/handling_pinch_gestures
I used pinch gesture for zooming. It's working fine. Using slider I am rotating that image. Rotation is also working perfect.
The problem after zooming, if I rotate the image, the zoom effect is missing. Here is the code I used for rotation
subView.transform = CGAffineTransformMakeRotation(slider.value * 2*M_PI / slider.maximumValue);
Thanks in Advance.
What is zooming? It is a transform. That’s all it is.
So your code comes along and rips out that transform and replaces it with a different transform.
// subView has zoom transform
subView.transform = CGAffineTransformMakeRotation(slider.value * 2*M_PI / slider.maximumValue);
// zoom transform overwritten
So you have wiped out the zoom.
I don't understand. how can I bring back my ImageView to the origin position (which is the Middle) of the view?
I want to use a TapGesture.
Or I have a second option to rotate it back to the original position. Currently I am trying to rotate it back but it doesn't work.
#IBAction func backToOrigin(recognizer:UITapGestureRecognizer){
if let view = recognizer.view{
self.view.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 2))
}
}
If you just want to undo a previous CGAffineTransform that you used to move or rotate your view you can use view.transform = CGAffineTransform.identity. (Also, delete the use of self from your code because self.view and the view inside your func are different things.)
This is what I currently have:
func handlePinching(recognizer : UIPinchGestureRecognizer) {
self.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformScale(self.transform, recognizer.scale, recognizer.scale));
recognizer.scale = 1.0;
}
Using self.view.transform for that also makes it bigger. I want to make it zoom "internally" (I really don't know how to explain it).
So I'm not 100% sure to understand the question but I guess I get it.
For example you want to zoom on an image without zooming the other element of the UI (NavBar, Buttons, ...) right?
So I guess in you're example you're in a viewController, which means, when you change the scale of self.view you'll zoom everything. You have to apply the scale on the specific view that you want to zoom in.
In the example below, to zoom on the image, the image is inside of an UIImageView, and this imageView is subView of self.view. And you will just apply a transform on this imageView.
Moreover I think you get a little bit confused on how to zoom, considering the view you want to zoom is imageView you just need to do
imageView.transform = CGAffineTransformMakeScale(recognizer.scale,recognizer.scale)
I hope this answer your question, let me know if something is not clear.
I would like to decrease the zooming speed behavior of a UIScrollView.
I've tried the solutions given in this two answers: Answer 1, Answer 2, but I'm not getting the expected results.
This is my implementation of answer 2:
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
if(scrollView.multipleTouchEnabled){
CGFloat fSpeedZoom = 2;
CGFloat fMaxZoomScale = scrollView.maximumZoomScale;
CGFloat fMinZoomScale = scrollView.minimunZoomScale;
scrollView.maximumZoomScale = scrollView.zoomScale + fSpeedZoom;
scrollView.minimumZoomScale = scrollView.zoomScale - fSpeedZoom;
if(scrollView.maximumZoomScale > fMaxZoomScale){
self.scrollView.maximumZoomScale = fMaxZoomScale;
}
if(scrollView.minimumZoomScale < fMinZoomScale){
self.scrollView.minimumZoomScale = fMinZoomScale;
}
}
}
If I keep the fSppedZoom values between 2 and 5 I get kind of an exponential behavior in which the further I try to zoom, the slower it zooms. I would like to get a linear behavior in which with a single parameter I could control the zooming speed.
I would recommend against doing this.
When you drag, the point that was underneath your finger when the drag started stays underneath your finger as the drag pans. This remains the case until you reach the edge of the draggable area, at which time the point moves in the same direction as the pan, but not as far, to simulate resistance.
When you pinch to zoom, the same thing happens. The two points that were underneath your two fingers stay underneath your finger as the pinch moves (hence you can pan at the same time as zooming). Again, this only breaks down when further zooming is not possible.
If you break this touch-point relationship, user interactions feel alien and unnatural.
If you absolutely must do this, I would recommend, instead of trying to fight UIScrollView's built-in zooming behaviour, implementing your own pinch gesture recogniser and considering the relationship you want to achieve between the positions of your touches and the area of the scroll view you want to show.