Scaling a UIView with subviews staying the same size
Easiest way to scale a
UIButton or a
UITableViewCell is to set a transform on it:
view.transform = CGAffineTransformMakeScale(1.5f, 1.5f);
If this works for you that's perfect, but sometimes some subviews start looking bad when zoomed in, especially images and text.
To make the
UIView zoomed in, but the subviews the same size Linear Algebra comes in handy. Especially Invertable Matrices. We know that a matrix multiplied by its inverse matrix will result in an identity matrix.
In terms of
UIView transforms this means that if we multiply the scale transform by its inverse transform, the view will stay the same size. The
UIViews in iOS work in a way, that the resulting displayed view has the final transform as a product of all the transforms of its ancestors in the view hierarchy. So if the
view will have a scale transform set, and its
subview will have the inverse transform set, the
subview will visually stay the same size, while the
view will be scaled.
CGAffineTransform t = CGAffineTransformMakeScale(x,y); CGAffineTransform it = CGAffineTransformInvert(t); view.transform = t; subview.transform = it;
Bonus question: How to make the scaled view look good?
After scaling the final view may not be pixel aligned with the device pixels. Especially if our scale parameter is not integral. This may result in blurry images and fonts.
For instance if a
view has a height of
257 and gets a scale parameter of
1.33 we get the final height of
341,81 which is not integral and the anti-aliasing kicks in.
To make sure our
view.frame stays integral after the transform, we have to use an approximate scale that is nearly the same as our original scale.
CGFloat sx = <something>; CGFloat sy = <something else>; CGFloat w = view.frame.size.width; CGFloat h = view.frame.size.height; CGFloat goodSx = ceilf(w * sx)/w; CGFloat goodSy = ceilf(h * sx)/h; CGAffineTransform t = CGAffineTransformMakeScale(goodSx, goodSy);
The above transform
t will make the
view look good scaled. This works because if we multiply the transform and the height, the result will be reduced to the output of the
ceilf function that is integral.
h * (ceilf(h * sx) / h) = ceilf(h * sx)