Resize All Subview in Scrollviewdidzoom

resize all subview in scrollViewDidZoom

When you are zooming in the scroll view, the zoomView (mainView in your case) is not resized, just an affine transformation applied on it's layer (CALayer). For example in case of 1.2 zoomScale it is :[1.2, 0, 0, 1.2, 0, 0].
So it's bounds is not changed - just all of it's content scaled up/down, it also affects it's frame property - so nor the contained inner view, and label will be resized, just scaled up/down when rendering the mainView, this is why their frame is unaffected.

Just implement - (void)scrollViewDidZoom:(UIScrollView *)scrollView in the delegate and print out the main view's frame, bounds, layer.affineTransform to see what happens on zooming.

To make what you want you have to adjust the label according the zoomScale:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
float zoomScale = scrollView.zoomScale;
self.label.bounds = CGRectMake(0, 0, 100*zoomScale, 100*zoomScale); // supposing that label's original size is {100, 100}
self.label.layer.affineTransform = CGAffineTransformMakeScale(1.0/zoomScale, 1.0/zoomScale);
}

Maintain constant line width in zooming UIScrollView subView

The answer was to set these rectangleViews as children of the UIScrollView and NOT have them returned by viewForZoomingInScrollView:. This means they will be scrolled, but not zoomed.

In their drawRect:, I transform their frame with the scrollView's zoomScale (provided by the VC). This causes slight artifacts because changing the frame triggers a redraw (without triggering drawRect:), but I'm willing to live with that for the moment.

This means I can set their size as if they were zoomed, but draw them with 1:1 pixels, add text, images, etc., and they remain crisp.

Center content of UIScrollView when smaller

Currently I'm subclassing UIScrollView and overriding setContentOffset: to adjust the offset based on contentSize. It works both with pinch and programatic zooming.

@implementation HPCenteringScrollView

- (void)setContentOffset:(CGPoint)contentOffset
{
const CGSize contentSize = self.contentSize;
const CGSize scrollViewSize = self.bounds.size;

if (contentSize.width < scrollViewSize.width)
{
contentOffset.x = -(scrollViewSize.width - contentSize.width) / 2.0;
}

if (contentSize.height < scrollViewSize.height)
{
contentOffset.y = -(scrollViewSize.height - contentSize.height) / 2.0;
}

[super setContentOffset:contentOffset];
}

@end

In addition to being short and sweet, this code produces a much smoother zoom than @Erdemus solution. You can see it in action in the RMGallery demo.

Retain the size of Subview added to a scrollView

Presumably you're calling -setTransform: from -scrollViewDidZoom:? Why not just call it the same way immediately after adding the subview?

How do I reset after a UIScrollView zoom?

I can't help you with the crashing, other than tell you to check and make sure you aren't unintentionally autoreleasing a view or layer somewhere within your code. I've seen the simulator handle the timing of autoreleases differently than on the device (most often when threads are involved).

The view scaling is an issue with UIScrollView I've run into, though. During a pinch-zooming event, UIScrollView will take the view you specified in the viewForZoomingInScrollView: delegate method and apply a transform to it. This transform provides a smooth scaling of the view without having to redraw it each frame. At the end of the zoom operation, your delegate method scrollViewDidEndZooming:withView:atScale: will be called and give you a chance to do a more high-quality rendering of your view at the new scale factor. Generally, it's suggested that you reset the transform on your view to be CGAffineTransformIdentity and then have your view manually redraw itself at the new size scale.

However, this causes a problem because UIScrollView doesn't appear to monitor the content view transform, so on the next zoom operation it sets the transform of the content view to whatever the overall scale factor is. Since you've manually redrawn your view at the last scale factor, it compounds the scaling, which is what you're seeing.

As a workaround, I use a UIView subclass for my content view with the following methods defined:

- (void)setTransformWithoutScaling:(CGAffineTransform)newTransform;
{
[super setTransform:newTransform];
}

- (void)setTransform:(CGAffineTransform)newValue;
{
[super setTransform:CGAffineTransformScale(newValue, 1.0f / previousScale, 1.0f / previousScale)];
}

where previousScale is a float instance variable of the view. I then implement the zooming delegate method as follows:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
[contentView setTransformWithoutScaling:CGAffineTransformIdentity];
// Code to manually redraw view at new scale here
contentView.previousScale = scale;
scrollView.contentSize = contentView.frame.size;
}

By doing this, the transforms sent to the content view are adjusted based on the scale at which the view was last redrawn. When the pinch-zooming is done, the transform is reset to a scale of 1.0 by bypassing the adjustment in the normal setTransform: method. This seems to provide the correct scaling behavior while letting you draw a crisp view at the completion of a zoom.

UPDATE (7/23/2010): iPhone OS 3.2 and above have changed the behavior of scroll views in regards to zooming. Now, a UIScrollView will respect the identity transform you apply to a content view and only provide the relative scale factor in -scrollViewDidEndZooming:withView:atScale:. Therefore, the above code for a UIView subclass is only necessary for devices running iPhone OS versions older than 3.2.

add UIButton as subview of UIWebView and resize it when zoom

If you're targeting iOS 5 and higher you can access scrollView property from UIWebView instance and become its delegate.

We are interested in scrollView:zoom* methods. Basic idea is:

1) On -scrollViewDidZoom: you're positioning the button according to scrollView.zoomScale with taking into account currentButtonFrame;

2) On -scrollViewDidEndZooming:withView:atScale: you're updating currentButtonFrame.

Check sample project here.

Sample Image

Zooming an UIImageView that contains subviews

There are many ways to achieve this. I would say the easiest one is to simply back-scale your views. This is what I used as a demo:

class ViewController: UIViewController {

@IBOutlet private var scrollView: UIScrollView?
private var imageView: UIImageView?
private var annotations: [UIView] = [UIView]()

override func viewDidLoad() {
super.viewDidLoad()

let imageView = UIImageView(image: UIImage(named: "background"))
scrollView?.addSubview(imageView)
scrollView?.contentSize = imageView.bounds.size
scrollView?.maximumZoomScale = 5.0
self.imageView = imageView

scrollView?.delegate = self

applyAnnotationView({
let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
view.backgroundColor = UIColor.red
view.layer.cornerRadius = view.bounds.width*0.5
return view
}(), at: CGPoint(x: 100.0, y: 100.0))

applyAnnotationView({
let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
view.backgroundColor = UIColor.green
view.layer.cornerRadius = view.bounds.width*0.5
return view
}(), at: CGPoint(x: 200.0, y: 200.0))
}

func applyAnnotationView(_ view: UIView, at position: CGPoint) {
view.center = position
annotations.append(view)
imageView?.addSubview(view)
}

}

// MARK: - UIScrollViewDelegate

extension ViewController: UIScrollViewDelegate {

func scrollViewDidZoom(_ scrollView: UIScrollView) {
annotations.forEach { item in
item.transform = CGAffineTransform(scaleX: 1.0/scrollView.zoomScale, y: 1.0/scrollView.zoomScale)
}
}

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}

}

Simply applying CGAffineTransform(scaleX: 1.0/scrollView.zoomScale, y: 1.0/scrollView.zoomScale) does all the work. It should be OK even when using constraints.



Related Topics



Leave a reply



Submit