Need assistance displaying image in UIScrollView like iOS photo app - ios

I am trying to display image in my app like photo app of iOS
here is what I am doing
I drag drop the UIScrollView in Xcode and set its NSLayoutConstraint leading, trailing, top, bottom
Inside scroll view drag drop the UIImageView and set its NSLayoutConstraint leading, trailing, top, bottom, equal width to main view and equal height to main view, And created the IBOutlets to width and height.
Make my controller UIScrollViewDelegate delegate.
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.minimumZoomScale=0.3;
self.scrollView.maximumZoomScale=6.0;
UIImage *img = [UIImage imageNamed:#"b.jpg"];
self.iVW.constant = img.size.width;
self.iVH.constant = img.size.height;
self.imageView.image = img;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
b.jpg is 11000 x 5000
here is my result at full zoom out :(
and desire result which is from iOS photo app

you can used this library , it support scrolling , zoom and sharing also
https://github.com/mwaterfall/MWPhotoBrowser

Related

How to get UIImageView size after autolayout is applied?

My storyboard has UIImageView which is automatically positioned and scaled by autolayout constraints.
When application runs, this UIImageView is properly resized and positioned according to device screen size and autolayout constraints.
How I can get UIImageView frame after it is displayed on the screen?
Common UIImageView.bounds and UIImageView.frame values return original values which were used in storyboard and does not reflect new UIImageView size.
In order to get the right frame/bounds of your UIImageView after resizing, you need first ask auto-layout to update that layout using [yourImageView layoutIfNeeded]. that will solve your constraints and update your yourImage.bounds.
[myImageView layoutIfNeeded];
NSLog(#"w: %f, h: %f", myImageView.bounds.size.width, myImageView.bounds.size.height);
Check these methods:
- (void)viewWillAppear:(BOOL)animated {
// view is about to be added to hieararchy
}
- (void)viewDidAppear:(BOOL)animated {
// view was added
}
- (void)viewDidLayoutSubviews {
// VC just laid off its views
}

Create effect top image is overlaid by content when sliding up

I have to create an effect like in the images but I don't know how to do it (and also don't know how to call this effect to search). You can see in the pictures, at first we have an image at the top of page. After that, when we scroll up, the image moves up while the content moves with higher speed to cover the image. Can you give me a link or a suggestion?
First of all take imageview and scrollview in your apps with IBOutlet.
In your YourViewController.h file
#property(nonatomic,retain) IBOutlet UIImageView *imagev;
#property(nonatomic,retain) IBOutlet UIScrollView *scr;
In your YourViewController.m file
- (void)viewDidLoad
{
scr.contentSize = CGSizeMake(320,850);
scr.decelerationRate = UIScrollViewDecelerationRateNormal;
[super viewDidLoad];
}
Set imagev frame according to scrolling in scrollview delegate.
pragma mark - ScrollView Delegate
-(void)scrollViewDidScroll:(UIScrollView *)callerScrollView
{
NSLog(#"%f",callerScrollView.contentOffset.y);
[imagev setFrame:CGRectMake(imagev.frame.origin.x, - 0.5 *callerScrollView.contentOffset.y, imagev.frame.size.width, imagev.frame.size.height)];
}
Output :

UIScrollView wrong offset with Auto Layout

I have a fairly simple view configuration:
A UIViewController, with a child UIScrollView and a UIImageView in this UIScrollView.
I set the UIImageView with a height sufficient to break out of the visible area (ie. higher to 1024pt), and set the Bottom space to superview constraint of my UIImageView to a fixed positive value (20 for example).
The whole setup works as expected, the image scrolls nicely in its parent.
Except when the view is scrolled (the effect is more visible if you scrolled to the bottom of the view), then disappear, and appear again (you switched to another view and came back) the scrolling value is restored, but the content of the scroll view is moved to the outside top part of its parent view.
This is not simple to explain, I'll try to draw it:
If you want to test/view the source (or the storyboard, I did not edit a single line of code). I put a little demo on my github: https://github.com/guillaume-algis/iOSAutoLayoutScrollView
I did read the iOS 6 changelog and the explanation on this particular topic, and think this is the correct implementation of the second option (pure auto layout), but in this case why is the UIScrollView behaving so erratically ? Am I missing something ?
EDIT: This is the exact same issue as #12580434 uiscrollview-autolayout-issue. The answers are just workarounds, as anyone found a proper way to fix this or is this a iOS bug ?
EDIT 2: I found another workaround, which keep the scroll position in the same state the user left it (this is an improvement over 12580434's accepted answer):
#interface GAViewController ()
#property CGPoint tempContentOffset;
#end
#implementation GAViewController
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tempContentOffset = self.mainScrollView.contentOffset;
self.scrollView.contentOffset = CGPointZero;
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.scrollView.contentOffset = self.tempContentOffset;
}
This basically save the offset in viewWillAppear, reset it to the origin, and then restore the value in viewDidAppear. The problem seems to occur between these two calls, but I can't find its origin.
Yeah, something strange happened with UIScrollView in pure autolayout environment. Re-reading the iOS SDK 6.0 release notes for the twentieth time I found that:
Note that you can make a subview of the scroll view appear to float (not scroll) over the other scrolling content by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview.
Solution
Connect your subview to the outer view. In another words, to the view in which scrollview is embedded.
As IB does not allow us set up constraints between the imageView and a view outside the scroll view’s subtree, such as the scroll view’s superview then I've done it in code.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view removeConstraints:[self.view constraints]];
[self.scrollView removeConstraints:[self.scrollView constraints]];
[self.imageView removeConstraints:[self.imageView constraints]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[_scrollView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scrollView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_scrollView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scrollView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[_imageView(700)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_imageView(1500)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]];
}
And vau! It works!
The edit didn't work for me. But this worked:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.tempContentOffset = self.scrollView.contentOffset;
self.scrollView.contentOffset = CGPointZero;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.scrollView.contentOffset = self.tempContentOffset;
}
For me I went to the IB clicked my view controller that contains the scroll view. Then I went to Attribute Inspector -> View Controller -> Extend Edges -> Uncheck "Under Top Bars" and "Under Bottom Bars".
Simple solution found, Just put
[self setAutomaticallyAdjustsScrollViewInsets:NO];
in your ViewControllers viewDidLoad method
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self setAutomaticallyAdjustsScrollViewInsets:NO];
}
I had a similar problem using a UIScrollView in a UIViewController with a top extra space that was not visible in Storyboard. The solution for me was to uncheck the "Adjust Scroll View Insets" on the ViewController storyboard properties : see answer Extra Space (inset) in Scroll View at run time
Add a global property contentOffset and save the current contentOffset in viewDidDisappear.
Once you return the method viewDidLayoutSubviews will be called and you can set your original contentOffset.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.scrollView setContentOffset:self.contentOffset animated:FALSE];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.contentOffset = self.scrollView.contentOffset;
[self.scrollView setContentOffset:CGPointMake(0, 0) animated:FALSE];
}
Looks like the problem solved with the dispatch_async during the viewWillAppear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGPoint originalContentOffset = self.scrollView.contentOffset;
self.scrollView.contentOffset = CGPointZero;
dispatch_async(dispatch_get_main_queue(), ^{
self.scrollView.contentOffset = originalContentOffset;
});
}

iOS UIScrollView always bounces back

I'm trying to make a basic proof of concept app. It uses UIScrollView with an UIImageView inside of it.
I set the image then set the contentSize of the UIScrollView but I still can't seem to scroll, it always bounces back to the start. Does anyone have any idea what I might be missing?
PS. Zooming works fine.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.picture setImage:nil];
[self.picture setImage:self.image];
self.scroll.contentSize = self.picture.frame.size;
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.picture;
}
Hi everyone ok, I've figured out what the problem was other then the fix below. It works as soon as i turn off the Autolayout option in storyboard.
When you set the image on a UIImageView, the frame of it does not update to the size of the new image. What you'll want to do is call the following to update the frame frame of picture to match the size of the image.
[self.picture sizeToFit];
On a side note, you dont need to set the image on nil on the imageView before changing it.

sizeToFit and constraints

I have an view:
There is layout constraint between label1 and label2. Pressing on button adds text from text view to label1. After it label 1 is resized to fit text (sizeToFit is called). And after resizing it looks like constraints don't work:
Does somebody has an idea how to make constraints work?
My coode:
#interface ViewController ()
{
CGFloat _width;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void) viewDidAppear:(BOOL)animated
{
_width = self.l1.frame.size.width;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)addText:(id)sender {
self.l1.text = [NSString stringWithFormat:#"%# %#", self.l1.text, self.text.text];
self.l1.frame = CGRectMake(self.l1.frame.origin.x, self.l1.frame.origin.y, _width, 0);
[self.l1 sizeToFit];
}
#end
I've found the reason: height constraint was equal to 40 of label 1. When I change it to greater or equal , all other constraints work ok.
I had a similar issue in which an UIImageView was at the top of several UILabelViews. The constraints were set to keep a small distance between the top image and the stack of labels below.
The problem was that when loading an unknown image size into the UIImage the height would change, but the labels to follow did not push down, and were covered by the image.
I tried to delete the set height of the UIImageView but XCode would not let me.
I resolved the issue by reducing the priority on the explicit UIImageview height constraint to 1.
After, the labels moved down the ViewController with even space between the image and themselves, as expected.

Resources