- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewFlowLayout *myLayout=[[UICollectionViewFlowLayout alloc]init];
myLayout.scrollDirection=UICollectionViewScrollDirectionHorizontal;
[self.collectionView setCollectionViewLayout:myLayout animated:YES];
UIImageView *recipeImageView=[[UIImageView alloc]initWithFrame:CGRectMake(35, 100, 250, 250)];
recipeImageView.layer.borderColor = [UIColor redColor].CGColor;
recipeImageView.layer.borderWidth = 8.0;
[self.view addSubview:recipeImageView];
NSString *selectedRecipeImageFileName = [self.getName objectAtIndex:indexPath.row];
UIImage *selectedRecipeImage = [UIImage imageNamed:selectedRecipeImageFileName];
recipeImageView.image = selectedRecipeImage;
}
I'm using a collection view. First, I press on any image, then it will show a UIImageView on the view. If I press on another image, then again that image will appear. At this point it works properly. After that, I want to have it so if I press on a blank space then the image view hides. Please give me some ideas.
Add this to your tap gesture:
[recipeImageView removeFromSuperview];
But your image view must be accessible to any function. So you can just make a function and then call it whenever you want.
UPDATE
Sorry for delayed response. Try this:
in your .h file:
first in #interface... add <UIGestureRecognizerDelegate>
and after #interface:
#property UIImageView *recipeImageView;
in your .m files viewDidLoad:
UIGestureRecognizer *taps = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(removeImageView)];
taps.cancelsTouchesInView = NO;
taps.delegate = self;
[self.view addGestureRecognizer:taps];
and somewhere in your .m file:
-(void)removeImageView
{
[_recipeImageView removeFromSuperview];
}
Keep a pointer to that UIImageView and call removeFromSuperview on it.
Use the tap gesture on your main view to remove the UIImageView from superView.
//inside viewDidLoad initilise tap gesture
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(removeImageView:)];
tapRecognizer.numberOfTapsRequired = 1;
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewFlowLayout *myLayout=[[UICollectionViewFlowLayout alloc]init];
myLayout.scrollDirection=UICollectionViewScrollDirectionHorizontal;
[self.collectionView setCollectionViewLayout:myLayout animated:YES];
UIImageView *recipeImageView=[[UIImageView alloc]initWithFrame:CGRectMake(35, 100, 250, 250)];
recipeImageView.layer.borderColor = [UIColor redColor].CGColor;
recipeImageView.layer.borderWidth = 8.0;
// tap gesture was initialised globally.
[self.view addGestureRecognizer:tapGesture];
[self.view addSubview:recipeImageView];
NSString *selectedRecipeImageFileName = [self.getName objectAtIndex:indexPath.row];
UIImage *selectedRecipeImage = [UIImage imageNamed:selectedRecipeImageFileName];
recipeImageView.image = selectedRecipeImage;
}
Now inside the removeImageView:
- (void)removeImageView:(UITapGestureRecognizer*)sender {
UIView *view = sender.view;
//Now here check the views on which user is taping and match if user is taping on desired view where you want remove the images from superView. and also remove the tap gesture from view.
}
Related
I have used third party lib to show array of images in a slider . The images in an array comes from server, now i want to show the image in a bigger image view on a tap gesture. When anyone of the image user tap it should be shown in big imageview. I have tried some code but it is not working. My code is,
int i=0;
tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(expandImage:)];
tap.numberOfTapsRequired = 1;
[_ImageView setUserInteractionEnabled:YES];
[_ImageView addGestureRecognizer:tap];
tap = [_imagesData objectAtIndex:i];
NSLog(#"TTT %#",tap);
[self.view addSubview:_fullImage];
The method is ,
-(void)expandImage:(UITapGestureRecognizer*)recogniser
{
[self.view addSubview:_fullImage];
UIButton *closeButton = [[UIButton alloc]init];
[closeButton setTitle:#"Close" forState:UIControlStateNormal];
// [closeButton addTarget:self action:#selector(Closetab) forControlEvents:UIControlEventTouchUpInside];
[_fullImage addSubview:closeButton];
UIImageView *photoView = [[UIImageView alloc]init];
[photoView setBackgroundColor:[UIColor blueColor]];
[_fullImage addSubview:photoView];
// photoView.accessibilityIdentifier = #"nature2.png";
[_fullImage addSubview:_fullImage];
}
here I attached the sample project , customize yourself
step1
create the one full screen view for preview the image (use one UIView, one close btn, one imageview)
#interface ViewController () <UIScrollViewDelegate, TAPageControlDelegate>
{
NSTimer *timer;
NSInteger index;
//
IBOutlet UIImageView *imgfull;
IBOutlet UIView *fullimagevie;
IBOutlet UIButton *btnClose;
}
step2
add the gesture for tap the image event and set the frame of your duplicate view as bottom of viewcontroller
- (void)viewDidLoad
{
[super viewDidLoad];
[self setviewframe:self.view.frame.size.height + 10];
self.imagesData = #[#"image1.jpg", #"image2.jpg", #"image3.jpg"];
for(int i=0; i<self.imagesData.count;i++){
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame) * i, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.scrollView.frame))];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.image = [UIImage imageNamed:[self.imagesData objectAtIndex:i]];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(expandImage:)];
tap.numberOfTapsRequired = 1;
tap.view.tag = i;
[imageView setUserInteractionEnabled:YES];
[imageView addGestureRecognizer:tap];
[self.scrollView addSubview:imageView];
}
step3
handle the image tap for preview the image
-(void)expandImage:(UITapGestureRecognizer*)recogniser
{
imgfull.image = [UIImage imageNamed:[self.imagesData objectAtIndex:recogniser.view.tag]];
[UIView transitionWithView:fullimagevie
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self setviewframe:0];
}
completion:NULL];
}
step4
dismiss the bigger image view on tap the close button
- (IBAction)btnClose:(UIButton *)sender {
[UIView transitionWithView:fullimagevie
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self setviewframe:self.view.frame.size.height + 10];
}
completion:NULL];
}
step5
create the common method for set the frame for your bigger imageview
-(void)setviewframe:(CGFloat)coordinate{
CGRect modifyframe = fullimagevie.frame;
modifyframe.origin.y = coordinate;
fullimagevie.frame = modifyframe;
}
I am using the following code to attach gesture recognizers to a custom view. But for some reason I am not able to get the gestures to work.
for(NSString *option in _options) {
UIView *blind = [self createBlind:option];
blind.userInteractionEnabled = YES;
blind.tag = index;
[self addSubview:blind];
[self addGravityBehaviorToBlind:blind];
[self addCollisionBehaviorToBlind:blind];
[self addElasticityBehaviorToBlind:blind];
[self registerGestureRecognizer:blind];
_spacingY += 44;
index++;
}
}
-(void) registerGestureRecognizer:(UIView *) blind {
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(blindTapped:)];
[blind addGestureRecognizer:tapGestureRecognizer];
}
-(void) blindTapped:(UITapGestureRecognizer *) recognizer { <-- THIS NEVER GETS CALLED
NSLog(#"blindTapped");
}
For some reason the blindTapped method never gets called even if I tap on the blind view.
UPDATE:
Yes, I see the views on the screen. The views (blind) is a subview in another view. The parent view gets added to the controller.view. There is no place where I have disabled interaction.
Here is the createBlind method:
-(UIView *) createBlind:(NSString *) option {
UIView *blind = [[UIView alloc] initWithFrame:CGRectMake(0, _spacingY, 200, 44)];
blind.layer.borderWidth = 1.0f;
blind.layer.borderColor = [UIColor whiteColor].CGColor;
UILabel *optionTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, blind.bounds.size.width, blind.bounds.size.height)];
optionTitleLabel.text = option;
optionTitleLabel.font = [UIFont fontWithName:#"GillSans" size:17];
optionTitleLabel.textColor = [UIColor whiteColor];
optionTitleLabel.textAlignment = NSTextAlignmentCenter;
[blind addSubview:optionTitleLabel];
return blind;
}
I have removed all the gravity and UIKit methods but still I am not able to trigger the tap gesture.
SOLUTION:
When adding the custom view to my controller.view I was not setting the frame. Once the frame was setup everything worked.
How can you zoom in on a UICollectionViewCell so that it will be displayed full screen? I have extended UICollectionViewFlowLayout and in my view controller when a cell is tapped I'm doing this:
CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];
UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
NSLog(#"Selected cell %#", selectedIndexPath);
Not really sure where to go from here. Should the UICollectionView be responsible of showing the zoomed in cell? Or should I create a new view controller that displays the content of the cell (an image) in full screen?
I took the solution here and modified it slightly to work with a collection view instead. I also added a transparent gray background to hide the original view a bit (assuming the image doesn't take up the entire frame).
#implementation CollectionViewController
{
UIImageView *fullScreenImageView;
UIImageView *originalImageView;
}
...
// in whatever method you're using to detect the cell selection
CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];
UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
originalImageView = [selectedCell imageView]; // or whatever cell element holds your image that you want to zoom
fullScreenImageView = [[UIImageView alloc] init];
[fullScreenImageView setContentMode:UIViewContentModeScaleAspectFit];
fullScreenImageView.image = [originalImageView image];
// ***********************************************************************************
// You can either use this to zoom in from the center of your cell
CGRect tempPoint = CGRectMake(originalImageView.center.x, originalImageView.center.y, 0, 0);
// OR, if you want to zoom from the tapped point...
CGRect tempPoint = CGRectMake(pointInCollectionView.x, pointInCollectionView.y, 0, 0);
// ***********************************************************************************
CGRect startingPoint = [self.view convertRect:tempPoint fromView:[self.collectionView cellForItemAtIndexPath:selectedIndexPath]];
[fullScreenImageView setFrame:startingPoint];
[fullScreenImageView setBackgroundColor:[[UIColor lightGrayColor] colorWithAlphaComponent:0.9f]];
[self.view addSubview:fullScreenImageView];
[UIView animateWithDuration:0.4
animations:^{
[fullScreenImageView setFrame:CGRectMake(0,
0,
self.view.bounds.size.width,
self.view.bounds.size.height)];
}];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(fullScreenImageViewTapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[fullScreenImageView addGestureRecognizer:singleTap];
[fullScreenImageView setUserInteractionEnabled:YES];
...
- (void)fullScreenImageViewTapped:(UIGestureRecognizer *)gestureRecognizer {
CGRect point=[self.view convertRect:originalImageView.bounds fromView:originalImageView];
gestureRecognizer.view.backgroundColor=[UIColor clearColor];
[UIView animateWithDuration:0.5
animations:^{
[(UIImageView *)gestureRecognizer.view setFrame:point];
}];
[self performSelector:#selector(animationDone:) withObject:[gestureRecognizer view] afterDelay:0.4];
}
-(void)animationDone:(UIView *)view
{
[fullScreenImageView removeFromSuperview];
fullScreenImageView = nil;
}
You can simply use another layout (similar to the one you already have) wherein the item size is larger, and then do setCollectionViewLayout:animated:completion: on the collectionView.
You don't need a new view controller. Your datasource remains the same. You can even use the same cell Class, just make sure that it knows when to layout things for a larger cell content size, and when not to.
I'm quite sure that's how Facebook does it in Paper, as there is no reloading of the content, i.e. [collectionView reloadData] never seems to be called (would have caused flickering and resetting of the scroll offset, etc). This seems to be the most straight forward possible solution.
CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];
UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
NSLog(#"Selected cell %#", selectedIndexPath);
__weak typeof(self) weakSelf = self;
[self.collectionView setCollectionViewLayout:newLayout animated:YES completion:^{
[weakSelf.collectionView scrollToItemAtIndexPath:selectedIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}];
You can use MWPhotoBrowser, which is suitable for your problem. It supports Grid with Tap to Zoom functionality. you can get it from here
Grid
In order to properly show the grid of thumbnails, you must ensure the property enableGrid is set to YES, and implement the following delegate method:
(id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser thumbPhotoAtIndex:(NSUInteger)index;
The photo browser can also start on the grid by enabling the startOnGrid property.
In my project I would like to make a hidden image view appear when it is tapped for more than 3 seconds. I know I need to use NSTimer, but I have never created a UIImageView touch event. How can I combine the TapGestureRecognizer with NSTimer to achieve what I want to do? I am completely new to touch events in iOS, and I am just beginning to explore this. So, any help would be appreciated. Thank you!
UPDATE:
I implemented the UILongPressGestureRecognizer as below, but now, the hidden image appears even if I press somewhere outside of the image. How can I make it appear only if pressing the hidden image itself?
- (void)viewDidLoad
{
[super viewDidLoad];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(handleLongPress:)];
longPress.numberOfTouchesRequired = 1;
longPress.minimumPressDuration = 3;
[self.view addGestureRecognizer:longPress];
}
-(void)handleLongPress:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan)
{
BrokenGlass.hidden = NO;
}
}
You don't want a UITapGestureRecognizer and a timer, you want a UILongPressGestureRecognizer.
The image is appearing because you are using the gesture recognizer in the entire view.
[**self.view** addGestureRecognizer:longPress];
The gesture will not trigger on a hidden element.
Here is my solution:
#interface ViewController () <UIGestureRecognizerDelegate>
#property (nonatomic, strong) UIImageView *imageView;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// create the imageView
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
// enable the user interaction in the imageView (otherwise it will not receive events)
_imageView.userInteractionEnabled = YES;
// add as a subview of the main view
[self.view addSubview:_imageView];
// create the gesture recognizer
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressHandler:)];
longPressGesture.delegate = self;
longPressGesture.minimumPressDuration = 3;
// add the gesture to the imageView
[_imageView addGestureRecognizer:longPressGesture];
}
#pragma mark - UIGestureRecognizerDelegate
- (void)longPressHandler:(UILongPressGestureRecognizer *)gestureRecognizer {
// show the image
_imageView.image = [UIImage imageNamed:#"cat.jpeg"];
}
I am trying to add a tap gesture from a subclassed UIImageView and then control the tap from the View Controller. I am not getting any compiling errors but "addSubview" is not displaying any image. How can make the UIImageView to be displayed?
If I try to control the tap and pan gestures from the subclassed UIImageVIew I have no problems but I would like to control these functions from the View Controller
Relevant code looks like this.
UIImageView subclass
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
//self.userInteractionEnabled = YES;
previewController = [[PreviewController alloc]init];
[previewController self];
[self addSubview:character];
// Tap Initialization code
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:(PreviewController *)self.previewController action:#selector(addCharacter:)];
[self addGestureRecognizer:tap];
self.userInteractionEnabled = YES;
}
return self;
}
View Controller
- (void)addCharacter:(UITapGestureRecognizer *)t
{
NSLog(#"add character");
imageNSArray = [NSMutableArray array];
uiImg = [UIImage imageNamed:#"homer.png"];
CGPoint loc = [t locationInView:self.view];
character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[imageNSArray addObject:character];
//Locate the imageNSArray on frameImageView area only.
[self.view addSubview:character];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panCharacter:)];
[self.character addGestureRecognizer:pan];
character.userInteractionEnabled = YES;
}
put a view behind your subclassed imageView. Apply the gestureRecognition to the new View.
You can control your tap gesture from new view. Let me know if i am not clear, or if more info needed.
I think what you want is.. .you want to show a image when user taps on screen.
Do following steps:
1. drag & drop a tap gesture recognizer on default view of your view controller.
2. connect (ctrl +) gestureRecognizer with ViewController.m
Take a look at this code. (Just modified your code)
- (IBAction)onTap:(UITapGestureRecognizer *)sender {
NSLog(#"add character");
UIImage * uiImg = [UIImage imageNamed:#"sel.png"];
CGPoint loc = [sender locationInView:self.view];
UIImageView * character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[self.view addSubview:character];
}
Let me know if this is not what you want…
Edit
better go for this code… No need to do above steps.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onTap:)];
[self.view addGestureRecognizer:tap];
self.view.userInteractionEnabled = YES;
}
- (void)onTap:(UITapGestureRecognizer *)sender
{
NSLog(#"add character");
UIImage * uiImg = [UIImage imageNamed:#"sel.png"];
CGPoint loc = [sender locationInView:self.view];
UIImageView * character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[self.view addSubview:character];
}