I create PhotoViewer by using UICollectionView scroll direction holizontal, pagingEnable = true. I create UICollectionViewCell contains UIScrollView to zooming UIImage.
But the first create UICollectionViewCell zoomScale working, UICollectionCell reuse zoomScale not working.
My code:
#interface ImageCell : UICollectionViewCell
#property (nonatomic, strong) UIImageView *imgView;
#property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) NSString *stringURL;
#property (nonatomic, strong) UIImage *img;
- (void)resize;
#end
#interface ImageCell()<UIScrollViewDelegate>
#end
#implementation ImageCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)resize {
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:[NSURL URLWithString:self.stringURL]
options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize)
{
// progression tracking code
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) {
if (image) {
if(self.imgView == nil) {
self.imgView = [[UIImageView alloc] initWithFrame:self.frame];
[self.scrollView addSubview:self.imgView];
}
NSLog(#"%#", NSStringFromCGSize(image.size));
self.img = image;
self.imgView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
self.imgView.image = image;
self.scrollView.contentSize = image.size;
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / image.size.width;
CGFloat scaleHeight = scrollViewFrame.size.height / image.size.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
self.scrollView.maximumZoomScale = 1;
[self.scrollView setZoomScale:minScale];
[self centerScrollViewContents];
}
}];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imgView;
}
[self.scrollView setZoomScale:minScale]; working when cell is create, when cell reuse not working
This line from the UIScrollView class reference
The UIScrollView class can have a delegate that must adopt the UIScrollViewDelegate protocol. For zooming and panning to work, the delegate must implement both viewForZoomingInScrollView: and scrollViewDidEndZooming:withView:atScale:
So you should also implement method scrollViewDidEndZooming:withView:atScale:
Related
I have a UIImageView and a UIView (filled with smaller imageviews) all placed in a UIScrollView (for zooming).
To better help you understand, I have a map (ImageView) with fog(UIView with smaller imageviews) in the scrollview so I can zoom the map.
If I add the mapview and fogview to the self.view then the application works as it should, touching the fog at a point removes that fog image.
However, when I add the map and fog views to the scrollview nothing responds to touches.
I ultimately want the default behavior to be touching fog view will remove the fog at one point. Unless the user presses a button to zoom/pinch the view, which will zoom both the mapview and fogview.
The problem below is no touches are processed when I add the mapview and fogview to the scrollview. Currently there is no ability to press a button to pinch/zoom as I still don't have the default behavior I want.
Any help?
#interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIActionSheetDelegate, UIGestureRecognizerDelegate, UIScrollViewDelegate>{
UIImage * fogImage;
NSUserDefaults * defaults;
bool canZoom;
}
#property (weak, nonatomic) IBOutlet UIButton *btnTakePicture;
#property (strong, nonatomic) UIButton * btnMenu;
#property (strong, nonatomic) UIButton * btnZoom;
#property (strong, nonatomic) UIScrollView* scrollView;
#property (strong, nonatomic) UIImageView *mapView;
#property (strong, nonatomic) UIView * fogView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
fogImage = [UIImage imageNamed:#"fog1.jpg"];
self.mapView = [[UIImageView alloc] initWithFrame:CGRectZero];
self.fogView = [[UIView alloc] initWithFrame:CGRectZero];
_scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
_scrollView.delegate = self;
_scrollView.minimumZoomScale = 0.75;
_scrollView.maximumZoomScale = 3.0;
[_scrollView addSubview:self.mapView];
[_scrollView addSubview:self.fogView];
[self.view addSubview:_scrollView];
self.mapView.hidden = YES;
self.fogView.hidden = YES;
self.scrollView.hidden = YES;
defaults = [NSUserDefaults standardUserDefaults];
canZoom = false;
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.mapView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.fogView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.scrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
- (void) zoom:(id)sender{
canZoom = !canZoom;
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
self.btnTakePicture.hidden = YES;
self.btnMenu.hidden = NO;
self.btnZoom.hidden = NO;
[picker dismissViewControllerAnimated:YES completion:^(void) {
[self fillScreenWithFog];
self.mapView.image = chosenImage;
self.mapView.contentMode = UIViewContentModeScaleAspectFit;
self.mapView.hidden = NO;
self.fogView.hidden = NO;
_scrollView.hidden = NO;
_scrollView.userInteractionEnabled = YES;
self.scrollView.contentSize = self.mapView.frame.size;
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
#pragma mark Fog Maker
- (void) removeFogAtPoint:(CGPoint)point{
NSLog(#"removeFogAtPoint %#", NSStringFromCGPoint(point));
CGRect fingerRect = CGRectMake(point.x - 5, point.y-5, 10, 10);
for(UIImageView *view in self.fogView.subviews){
CGRect subviewFrame = view.frame;
if(CGRectIntersectsRect(fingerRect, subviewFrame)){
[UIView animateWithDuration:1.25
animations:^{
view.alpha = 0;
}
completion:^(BOOL finished){
[view removeFromSuperview];
}];
}
}
}
- (void) fillScreenWithFog {
// do a loop to fill the screen with fog getNewSquare
}
- (UIImageView*) getNewSquare:(CGRect)frame withTag:(int)tag{
UIImageView * imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = fogImage;
imageView.contentMode = UIViewContentModeScaleAspectFill;
return imageView;
}
-(void) touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(#"Touches Moved");
CGPoint location = [[touches anyObject] locationInView:self.scrollView];
[self removeFogAtPoint:location];
}
#end
I want to combine two images and send them as one to a Parse database.
Only I get no image as result.
This is my code:
.h file
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface mailViewController : UIViewController<UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *naamText;
#property (weak, nonatomic) IBOutlet UITextField *emailText;
#property (weak, nonatomic) IBOutlet UIImageView *dankView;
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UIButton *buttonLogo;
#property (weak, nonatomic) IBOutlet UIImageView *mailImage;
#property (weak, nonatomic) IBOutlet UIImageView *achtergrondImage;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (nonatomic, strong) UIImage *coverImage;
#property (nonatomic, strong) UIImage *achtergrond;
//#property (nonatomic, strong) UIImage *finalImage;
- (IBAction)send:(id)sender;
- (IBAction)cancel:(id)sender;
#end
.m file
#import "mailViewController.h"
#import "cat01ViewController.h"
#interface mailViewController ()
#property (nonatomic, strong) UIImage *finalImage;
#end
#implementation mailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
self.naamText.delegate = self;
self.emailText.delegate = self;
self.mailImage.image = self.coverImage;
//hide dankwoord
self.dankView.hidden = YES;
_label.hidden = YES;
_buttonLogo.hidden = YES;
[super viewDidLoad];
}
- (void) viewWillAppear:(BOOL)animated
{
if (self.coverImage != nil)
self.mailImage.image = self.coverImage;
}
- (void)addImages{
UIImage *image1 = self.mailImage.image;
UIImage *image2 = self.achtergrond;
CGSize size = CGSizeMake(image1.size.width, image1.size.height + image2.size.height);
[image1 drawInRect:CGRectMake(0,0,size.width, image1.size.height)];
[image2 drawInRect:CGRectMake(0,image1.size.height,size.width, image2.size.height)];
self.finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//Add image to view
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.finalImage.size.width, self.finalImage.size.height)];
imageView.image = self.finalImage;
[self.view addSubview: imageView];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.naamText resignFirstResponder];
[self.emailText resignFirstResponder];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
if (textField) {
[textField resignFirstResponder];
}
PFObject *emailadres = [PFObject objectWithClassName:#"emailadres"];
[emailadres setObject:_naamText.text forKey:#"name"];
[emailadres setObject:_emailText.text forKey:#"email"];
emailadres[#"iPad_nr"] = #"iPad 2";
[emailadres saveInBackground];
self.dankView.hidden = NO;
_label.hidden = NO;
_buttonLogo.hidden = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
_label.hidden = YES;
});
return NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)send:(id)sender {
[self.naamText resignFirstResponder];
[self.emailText resignFirstResponder];
UIImage *image = self.finalImage;
NSData *imageData = UIImagePNGRepresentation(image);
PFFile *imageFile = [PFFile fileWithName:#"image.png" data:imageData];
PFObject *mailPhoto = [PFObject objectWithClassName:#"mailPhoto"];
mailPhoto[#"imageName"] = #"Ikzieikzie";
mailPhoto[#"imageFile"] = imageFile;
[mailPhoto setObject:_naamText.text forKey:#"name"];
[mailPhoto setObject:_emailText.text forKey:#"email"];
mailPhoto[#"iPad_nr"] = #"iPad 1";
[mailPhoto saveInBackground];
self.dankView.hidden = NO;
_label.hidden = NO;
_buttonLogo.hidden = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
_label.hidden = YES;
});
}
- (IBAction)cancel:(id)sender {
[self.naamText resignFirstResponder];
[self.emailText resignFirstResponder];
self.dankView.hidden = NO;
_label.hidden = NO;
_buttonLogo.hidden = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
_label.hidden = YES;
});
}
#end
So, I know how to send the images individual to the Parse database... but I cant understand how to combine them and send them as one.
You set the local variable finalImage in addImages, you never set a class variable self.finalImage to contain the combined image, so this line
UIImage *image = self.finalImage;
probably sets image to nil.
Also, you never add the UIImageView *imageView in addImages as a subview as you've probably intended.
So to fix this code, I'd recommend creating defining finalImage as a class property at the top of the class, ex:
#interface ViewController ()
#property (nonatomic, strong) UIImage *finalImage;
#end
Then in addImages you can change the local variable finalImage to self.finalImage and properly add the UIImageView as a subview, ex:
self.finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//Add image to view
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.finalImage.size.width, self.finalImage.size.height)];
imageView.image = self.finalImage;
[self.view addSubview: imageView];
After making these changes you can still use this line in send::
UIImage *image = self.finalImage;
You have misplaced the context, it should be focused to imageview object not to the image object.
Try this:
UIImage *image1 = self.mailImage.image;
UIImage *image2 = self.achtergrond;
CGSize size = CGSizeMake(image1.size.width, image1.size.height + image2.size.height);
[image1 drawInRect:CGRectMake(0,0,size.width, image1.size.height)];
[image2 drawInRect:CGRectMake(0,image1.size.height,size.width, image2.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
//Add image to view
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, finalImage.size.width, finalImage.size.height)];
UIGraphicsBeginImageContext(size);
imageView.image = finalImage;
UIGraphicsEndImageContext();
Hope this helps.
So, this is the final solution! Thanks for your help!
UIImage *image1 = self.achtergrondImage.image;
UIImage *image2 = self.mailImage.image;
UIGraphicsBeginImageContext(image1.size);
[image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)];
[image2 drawInRect:CGRectMake(image1.size.width - image2.size.width, image1.size.height - image2.size.height, image2.size.width, image2.size.height)];
self.finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.finalImage.size.width, self.finalImage.size.height)];
imageView.image = self.finalImage;
I want to show an image using a UIImageView inside a UIScrollview. The image needs to fit on the screen while keeping the aspect ratio.
This all works, except that, when I zoom first, I can scroll below the image. The height of area is about 64.
This is how it looks after scrolling (White is the background color of the UIImageView and red is the background color of the UIScrollView):
This is the code in my ImageViewController:
#import "ImageViewController.h"
#interface ImageViewController () <UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) UIImageView *imageView;
#property (nonatomic, strong) UIImage *image;
#end
#implementation ImageViewController
- (void)viewDidLoad
{
NSLog(#"viewDidLoad");
[super viewDidLoad];
_scrollView.minimumZoomScale = 1.0 ;
_scrollView.maximumZoomScale = _imageView.image.size.width / _scrollView.frame.size.width;
_scrollView.zoomScale = 1.0;
_scrollView.backgroundColor = [UIColor redColor];
_scrollView.delegate = self;
_imageView.backgroundColor = [UIColor whiteColor];
[_scrollView addSubview:_imageView];
}
- (void)viewDidLayoutSubviews
{
self.imageView.frame = self.scrollView.bounds;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}
- (UIImageView *)imageView
{
if (!_imageView) _imageView = [[UIImageView alloc] init];
return _imageView;
}
- (UIImage *)image
{
NSLog(#"image");
return self.imageView.image;
}
- (void)setImage:(UIImage *)image
{
NSLog(#"setImage");
self.imageView.image = image;
}
#pragma mark - UIScrollViewDelegate
// mandatory zooming method in UIScrollViewDelegate protocol
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
-(void)setImageURL:(NSURL *)imageURL
{
NSLog(#"setImageURL");
_imageURL = imageURL;
self.image = [UIImage imageWithContentsOfFile:[imageURL path]];
}
#end
This are the properties of my UIScrollView:
How can I fix this?
I got it working. This is my code:
#import "ImageViewController.h"
#interface ImageViewController () <UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) UIImageView *imageView;
#property (nonatomic, strong) UIImage *image;
#end
#implementation ImageViewController
- (void)viewDidLoad
{
NSLog(#"viewDidLoad");
[super viewDidLoad];
self.scrollView.contentSize = self.scrollView.frame.size;
self.scrollView.delegate = self;
CGRect rect = CGRectZero;
rect.size = self.image.size;
self.scrollView.minimumZoomScale = 0.5;
self.scrollView.maximumZoomScale = 2.5;
self.scrollView.zoomScale = 1.0;
self.imageView = [[UIImageView alloc] initWithFrame:rect];
self.imageView.image = self.image;
[self.scrollView addSubview:self.imageView];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
}
- (IBAction)tappedAction:(id)sender {
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:#[self.image] applicationActivities:nil];
[self presentViewController:activityVC animated:YES completion:nil];
}
- (void)viewDidLayoutSubviews
{
self.imageView.frame = self.scrollView.bounds;
}
#pragma mark - UIScrollViewDelegate
// mandatory zooming method in UIScrollViewDelegate protocol
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
UIView *subView = [scrollView.subviews objectAtIndex:0];
CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);
subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
scrollView.contentSize.height * 0.5 + offsetY);
}
-(void)setImageURL:(NSURL *)imageURL
{
NSLog(#"setImageURL");
_imageURL = imageURL;
self.image = [UIImage imageWithContentsOfFile:[imageURL path]];
}
#end
The code in scrollViewDidZoom: is used to keep the image centered.
I am building a ViewController just to show one image. I added the ImageView programmatically to a scroll view. I would like to allow the user to zoom in and out. This is my code
#interface ImageViewerViewController ()<UIScrollViewDelegate>
#property (nonatomic, strong) UIImageView *ImageView;
#property (weak, nonatomic) IBOutlet UIScrollView *Scroll;
#end
#implementation ImageViewerViewController
-(UIView*) viewForZoomingInScrollView{
return self.ImageView;
}
-(void) viewDidLoad{
self.Scroll.minimumZoomScale = 0.2;
self.Scroll.maximumZoomScale = 1.5;
self.Scroll.delegate = self;
NSLog(#"View did load");
if(self.imageName)
[self updateImage];
}
-(void)setImageName:(NSString *)imageName{
NSLog(#"set Image");
_imageName = imageName;
}
-(void)updateImage{
self.ImageView =[[UIImageView alloc]init];
self.ImageView.image = [UIImage imageNamed:self.imageName];
[self.ImageView sizeToFit];
self.Scroll.contentSize = self.imageName? self.ImageView.image.size: CGSizeZero;
[self.Scroll addSubview:self.ImageView];
}
#end
As you see, I already set the delegate of the scroll to self and I added the protocol header and the needed message.
But the zooming feature is not working.
Could you help me please?
I appreciate your time and efforts.
Regards,
This will work as I created a demo of it. If anything do else let me know.
-(void)viewDidLoad
{
float minimumScale = [_floorPlanImageView frame].size.width /[_floorPlanScrollView frame].size.width;
_floorPlanScrollView.maximumZoomScale = 5; //Change as per you need
_floorPlanScrollView.minimumZoomScale = minimumScale; //Change as you need
_floorPlanScrollView.zoomScale = minimumScale;
_floorPlanScrollView.delegate =self;
_floorPlanScrollView.clipsToBounds = YES;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return _floorPlanImageView;
}
I use SDWebimage to load and cache pictures, and now I am looking for a way to swipe/scroll through the images. I've tried different approaches but I can't seem to get it working, can someone help me with this?
You just do your scrolling image browser as you otherwise would, but instead of setting the image property synchronously, you just call the SDWebImage method setImageWithURL (from its UIImageView category).
To show you a quick and dirty implementation, create a UIScrollView, turn on paging, and in viewDidLoad you can set the content size and load the first image, like so:
[self.scrollView setContentSize:CGSizeMake(self.view.bounds.size.width * [self.objects count],
self.view.bounds.size.height)];
dispatch_async(dispatch_get_main_queue(), ^{
ImageBrowserObject *object = self.objects[0];
[object scrollView:self.scrollView addImageViewIfNeededForIndex:0];
});
You also want to set up your controller as a delegate for that scroll view and then handle the scrollViewDidScroll event:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
static NSInteger lastKnownIndex = -1;
NSInteger currentIndex = scrollView.contentOffset.x / scrollView.frame.size.width + 0.5f;
NSInteger nextIndex = currentIndex + 1;
NSInteger prevIndex = currentIndex - 1;
if (prevIndex < 0) prevIndex = 0;
if (currentIndex == lastKnownIndex)
return;
// add the imageviews we need, remove the ones we don't
[self.objects enumerateObjectsUsingBlock:^(ImageBrowserObject *object, NSUInteger idx, BOOL *stop) {
if (idx >= prevIndex && idx <= nextIndex)
[object scrollView:scrollView addImageViewIfNeededForIndex:idx];
else
[object scrollView:scrollView removeImageViewIfNeededForIndex:idx];
}];
lastKnownIndex = currentIndex;
}
And my ImageBrowserObject is defined as follows:
#interface ImageBrowserObject : NSObject
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSURL *url;
#property (nonatomic, weak) UIImageView *imageView;
#end
#implementation ImageBrowserObject
- (id)initWithTitle:(NSString *)title URL:(NSURL *)url
{
self = [super init];
if (self) {
_title = title;
_url = url;
}
return self;
}
- (void)scrollView:(UIScrollView *)scrollView addImageViewIfNeededForIndex:(NSInteger)index
{
if (self.imageView)
return;
CGRect frame = CGRectMake(index * scrollView.frame.size.width,
0.0,
scrollView.frame.size.width,
scrollView.frame.size.height);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
[scrollView addSubview:imageView];
[imageView setImageWithURL:self.url placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
self.imageView = imageView;
}
- (void)scrollView:(UIScrollView *)scrollView removeImageViewIfNeededForIndex:(NSInteger)index
{
if (!self.imageView)
return;
[self.imageView removeFromSuperview];
self.imageView = nil;
}
#end
This is a pretty simplistic implementation, but I suspect you get the idea.