Setting UIImage transform affects UIScrollView - ios

My aim is to create an UIImage that scales automatically as I scroll in an UIScrollView. This works just fine but as soon as the scale of my image is set to something like .6 you aren't able to scroll in the UIScrollView anymore (even if you reset the scaling to 1 or 0.5 or/and reassign the content size of the scrollview). This is very strange because setting the scaling to 1, .75, .5 or .25 doesn't affect the scrollview (i. e. it works as it should). I'm using transform instead of setting the frame size because I want the image to be centered by the AutoLayout. Is there a better way of scaling an image without touching frame? And why does setting the scaling of an image affect a scrollview at all?
This is the code I'm using for resizing the image:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat pageWidth = sideScroller.frame.size.width;
CGFloat scrollOffset = sideScroller.contentOffset.x;
float fractionalPage = scrollOffset / pageWidth;
NSInteger page = lround(fractionalPage);
[pageControl setCurrentPage:page];
if (scrollOffset > pageWidth)
scrollOffset = (pageWidth * 2) - scrollOffset;
float logoSize = 1 - ((scrollOffset / pageWidth) / 2);
logo.transform = CGAffineTransformMakeScale(logoSize, logoSize);
}

Just a guess but the content size of the content inside of the scroll view isn't changing because of the transform. Try scaling by frame instead.

Related

Edit the alpha of navigation bar when scrolls tableview

I wanna ask if its possible to change the alpha value of a navigation bar when the user is scrolling a tableview.
I have the algorithm, but i need something help to get changes on real time.
/* This is the offset at the bottom of the scroll view. */
CGFloat totalScroll = scrollView.contentSize.height - scrollView.bounds.size.height;
/* This is the current offset. */
CGFloat offset = - scrollView.contentOffset.y;
/* This is the percentage of the current offset / bottom offset. */
CGFloat percentage = offset / totalScroll;
/* When percentage = 0, the alpha should be 1 so we should flip the percentage. */
scrollView.alpha = (1.f - percentage);
It's probably too late, but for future reference, you could do something like this:
func scrollViewDidScroll(scrollView: UIScrollView) {
self.navigationController!.navigationBar.alpha = 1 - (self.tableView.contentOffset.y / (self.tableView.contentSize.height - self.tableView.frame.size.height));
}
On this delegate you have the values of contentOffset of scrollview or tableView, and you can observe the value of this property to make the behavior you desire.
Hope it helps!

Find bounds of UIViewController's view not obscured by UINavigationBar, UITabBar, (etc)

I can configure my UIViewController's edgesForExtendedLayout so that it will extend underneath content such as the navigation bar or tab bar. If I do this, is there some way to determine the frame that is not obscured?
As a possible alternative, is there a way for a UIViewController to determine the default contentInset to apply to a UIScrollView it contains?
Use case
I have zoomable UIScrollView containing an image.
When it is fully zoomed out I want to adjust the content inset too allow the content to stay centred (details here). However, my modified insets don't take in to account the insets that the UIViewController applies automatically so that its content isn't obscured by navigation bars, etc.
I also need to compute the minimum zoom for the content – that at which the whole image will be visible and not obscured. To compute this, I need to know the size of the unobscured part of the content view.
You need this
-(CGRect) unobscuredBounds
{
CGRect bounds = [self.view bounds];
return UIEdgeInsetsInsetRect(bounds, [self defaultContentInsets]);
}
-(UIEdgeInsets) defaultContentInsets
{
const CGFloat topOverlay = self.topLayoutGuide.length;
const CGFloat bottomOverlay = self.bottomLayoutGuide.length;
return UIEdgeInsetsMake(topOverlay, 0, bottomOverlay, 0);
}
You could put this in a category for easy reusability.
These methods correctly handle the changes that occur when the view resizes after a rotation – the change to the UINavigationBar size is correctly handled.
Centring Content
To use this to centre content by adjusting insets, you'd do something like this:
-(void) scrollViewDidZoom:(UIScrollView *)scrollView
{
[self centerContent];
}
- (void)centerContent
{
const CGSize contentSize = self.scrollView.contentSize;
const CGSize unobscuredBounds = [self unobscuredBounds].size;
const CGFloat left = MAX(0, (unobscuredBounds.width - contentSize.width)) * 0.5f;
const CGFloat top = MAX(0, (unobscuredBounds.height - contentSize.height)) * 0.5f;
self.scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left);
}
Your content insets will now reflect the default insets that they need (to avoid being covered up) and will also have the insets they need to be nicely centred.
Handling Rotation & Zoom
You probably also want to perform centring when animating between landscape and portrait. At the same time, you might want to adjust your minimum zoom scale so that your content will always fit. Try out something like this:
-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self centerContent];
const bool zoomIsAtMinimum = self.scrollView.zoomScale == self.scrollView.minimumZoomScale;
self.scrollView.minimumZoomScale = [self currentMinimumScale];
if(zoomIsAtMinimum)
{
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
}
}
-(CGFloat) currentMinimumScale
{
const CGFloat currentScale = self.scrollView.zoomScale;
const CGSize scaledContentSize = self.scrollView.contentSize;
const CGSize scrollViewSize = [self unobscuredBounds].size;
CGFloat scaleToFitWidth = currentScale * scrollViewSize.width / scaledContentSize.width;
CGFloat scaleToFitHeight = currentScale * scrollViewSize.height / scaledContentSize.height;
return MIN(scaleToFitWidth, scaleToFitHeight);
}
The willAnimateRotationToInterfaceOrientation:… method is called within the view animation block, so the changes that it applies will lead to nice smooth animated changes as you switch from landscape to portrait.

Can't lock the top of image in the top of the screen while scrolling the page

I a uiimage that I use as cover photo, and I want to use the scroll view to pull down and enlarge but I want the top of the image to stay on top:
and this is the method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;{
CGFloat offset = scrollView.contentOffset.y;
offset = offset + 54;
if (offset < 0 && offset > -25) {
_coverImageView.frame = CGRectMake(offset, 0,320 + (-offset) * 2, 150 + (-offset));
}
NSLog(#"%f", offset);
}
tnx
You can use imageview behind the scrolview with clear background and resize while scrolling according to offset.
OR
This may help
https://www.cocoacontrols.com/controls/secret-viewer

Image Exact Size and Position After Rotating or Zooming in iOS

After searching lot of things but couldnt get help so asking the question.
I have a ImageView i am rotating that image with gesture now suppose if i had rotate it to some angle and zoom it through pan gesture. Now i want the same image size and position in next view so how can i do that with absolute position and size.
Thanks
Sanjay
To get UIImage size after zooming you can multiply image size by UIScrollView's zoomScale property.
For Image size
Image.width = Image.width + ScrollView.contentOffset.x
Image.height = Image.width + ScrollView.contentOffset.y
For Image location
Image.x = (Image.x * ScrollView.zoomScale) - ScrollView.contentOffset.x
Image.y = (Image.y * ScrollView.zoomScale) - ScrollView.contentOffset.y

UIScrollView zoom to rect

I'm trying to zoom inside a UIScrollView by specifying a rect which is within scrollview's coordinates. However it's not working as expected. and I think it's because of zoom scale or maybe I'm missing a transformation. The scroll view I'm trying to zoom is from the Apple's example PhotoScroller -- ImageScrollView. Also I copied the code to generate a frame to zoom from Apple's example as well:
- (CGRect)zoomRectForScrollView:(UIScrollView *)scrollView withScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// The zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the
// imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible,
// the size of the rect grows.
zoomRect.size.height = scrollView.frame.size.height / scale;
zoomRect.size.width = scrollView.frame.size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
Now the code to actually zoom is the following:
CGPoint scrollRectCenter = CGPointMake(rect.origin.x + (rect.size.width /2) ,
rect.origin.y + (rect.size.height / 2));
CGFloat newZoomScale = self.imageScrollView.zoomScale * 1.3f;
newZoomScale = MIN(newZoomScale, self.imageScrollView.maximumZoomScale);
CGRect zoomToRect = [self zoomRectForScrollView:self.imageScrollView withScale:newZoomScale withCenter:scrollRectCenter];
[self.imageScrollView zoomToRect:zoomToRect animated:YES];
How can I zoom to a rect taking in consideration the zoomed imageView zoomscale, so that it fit's correctly?
What I'm trying to achieve is the effect of the photos app, in which the crop grid is moved and the scrollview zooms to that rect.
Does anybody know a link or code example to achieve a similar effect to the photos app? Thanks a lot.
Let me guess...you have implemented - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale delegate method.
Your problem occurs because when this method is called the scrollview's zoom scale is reseted to 1. I don't know why, don't ask me.
You can fix it in 2 ways :
you save the scale into a variable and in - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale you set your variable to the appropriate scale and do the calculations with your scale.
You don't implement the bloody method, unless you have multiple views in your scrollview and each can zoom individually it doesn't worth it (after all you can access the zoom scale with scrollview.zoomScale)
If you don't implement the method disregard this answer :)

Resources