I have a CollectionView where I display my custom CollectionViewCell which consists of a UIImageView (called "thumbnailView").
What I want is that when the user presses one of the collection cell, then the image becomes darker (exactly the same behaviour in the iPhone home menu with all the apps).
I've tried with the Quartz Framework and did so in the MyCustomCollectionViewCell.m :
-(void) setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}
-(void) drawRect:(CGRect)rect {
[super drawRect:rect];
if (self.highlighted) {
[self.thumbnailView.layer setBackgroundColor:[UIColor blackColor].CGColor];
[self.thumbnailView.layer setOpacity:0.9];
}
}
but it just adds black corners to my images in the collection cell but without darkening them like I want.
You can add another view to do the highlighting.
In the custom cell add a property:
#property (nonatomic, strong) UIView *highlightView;
Initialize and add it to the cell's contentView. Notice that the alpha is initially set to zero:
self.highlightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
self.highlightView.backgroundColor = [UIColor blackColor];
self.highlightView.alpha = 0;
[self.contentView addSubview:self.highlightView];
In your custom UICollectionView override the highlight methods and change the alpha of the cell's highlight view:
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCollectionViewCell* cell = (MyCustomCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:0.3 animations:^()
{
cell.highlightView.alpha = 0.5;
}];
}
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCollectionViewCell* cell = (MyCustomCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:0.3 animations:^()
{
cell.highlightView.alpha = 0;
}];
}
Related
Hi I am a beginner in iOS and in my project I have added a collection view programmatically and it was added successfully.
My requirement is when I click on UICollectionViewCell then it will be displayed full screen like below second image and when I click on close button image will go back to its actual position.
For this I have tried some code, but it's not working!
Please help me.
My code:-
#import "ViewController.h"
#interface ViewController ()
{
BOOL isFullScreen;
CGRect prevFrame;
UIImageView *dot;
NSArray * images;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
images = [[NSArray alloc]initWithObjects:#"1.png",#"2.png",#"3.png",#"4.png",#"5.png",#"6.png",#"7.png",#"8.png",#"9.png", nil];
isFullScreen = NO;
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
_collectionView=[[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
[_collectionView setDataSource:self];
[_collectionView setDelegate:self];
_collectionView.backgroundColor = [UIColor whiteColor];
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[self.view addSubview:_collectionView];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 9;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
dot =[[UIImageView alloc] initWithFrame:CGRectMake(0,0,cell.frame.size.width,cell.frame.size.height)];
dot.image=[UIImage imageNamed:[images objectAtIndex:indexPath.row]];
[cell.contentView addSubview:dot];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(100, 100);
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
if (!isFullScreen) {
[UICollectionView animateWithDuration:0.5 delay:0 options:0 animations:^{
prevFrame = cell.frame;
[cell setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = TRUE;
}];
return;
}
else{
[UICollectionView animateWithDuration:0.5 delay:0 options:0 animations:^{
[cell setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = FALSE;
}];
return;
}
}
#end
Try
cell.framewill not give you the correct position of the cell on the screen, but the position within the content scrollview of the CollectionViewController
In order to find the correct frame, try
CGRect frameToAnimateTo = [self.navigationController.view convertRect:cell.frame fromView:self.collectionView];
To find the position of the cell view in the surrounding NavigationController.
As for the actual animation, it will be a bit more complicated than just transitioning views. Assuming you want to present the image in an own ViewController (which you don't necessarily have to, but your question indicates that you plan to...), you will have to implement a custom ViewController transition.
The easiest solution would be to develop a UIView with image view and button, that pops up from the collectionView and simply contains an UIImageView and an UIButton for closing.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "second") as! ViewController
let imagenew = UIImage(named: iosImages[indexPath.row])
print(imagenew!)
vc.img = imagenew as Any as! UIImage
navigationController?.pushViewController(vc, animated: true)
}
Send the image value to the next view controller and store that in the UIImage variable, then passed that value to the UIImageView for display.
It's there a way to add an semi transparent overlay to a CollectionViewCell on it's clicked? (I want to "darken" the entire cell when a user taps on the cell).
I found a way to change the background color but I don't know if there'a way to add an overlay.
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:0.1 delay:0 options:(UIViewAnimationOptionAllowUserInteraction) animations:^{ [cell setBackgroundColor:[UIColor colorWithRed:232/255.0f green:232/255.0f blue:232/255.0f alpha:1]]; } completion:nil];
}
EDIT
I added an UIView with a semi transparent background to the Cell once it's tapped:
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
UIView *overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 172, 210)];
overlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.1];
[cell addSubview:overlay];
}
The simplest solution, I find, is to add to the cell, right from the start, a UIImageView with no image but with a highlighted image:
UIImageView* iv = [[UIImageView alloc] initWithImage:nil highlightedImage:im];
iv.userInteractionEnabled = NO;
[cell addSubview: iv];
The result is that the image im magically becomes visible in the cell when - and only when - the cell is highlighted (selected).
i make an application that conatin UICollectionview with CustumCell and each Cell Contain images i want to make when any image selected then it was zoom in view and when zoom view touch
then collectionview was Shown like as a URBMediaFocusViewController Libraray
link of library is here URBMediaFocusViewController
i know it was asked many times but please give me solution.
It's not very elegant, but this is how I do it. Basically get the frame location and size of your source UICollectionView Cell, the frame and location of where you want it to appear (in this case I fill the view), then animate between the two sizes. Hope this helps.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
[self zoomToSelectedImage:indexPath];
}
-(void)zoomToSelectedImage:(NSIndexPath *)indexPath
{
UIImageView *zoomImage = [[UIImageView alloc] initWithImage:[self.myPictures objectAtIndex:indexPath.row]];
zoomImage.contentMode = UIViewContentModeScaleAspectFit;
CGRect zoomFrameTo = CGRectMake(0,0, self.view.frame.size.width,self.view.frame.size.height);
UICollectionView *cv = (UICollectionView *)[self.view viewWithTag:66]; // Change to whatever the tag value of your collectionView is
cv.hidden = TRUE;
UICollectionViewCell *cellToZoom =(UICollectionViewCell *)[cv cellForItemAtIndexPath:indexPath];
CGRect zoomFrameFrom = cellToZoom.frame;
[self.view addSubview:zoomImage];
zoomImage.frame = zoomFrameFrom;
zoomImage.alpha = 0.2;
[UIView animateWithDuration:0.2 animations:
^{
zoomImage.frame = zoomFrameTo;
zoomImage.alpha = 1;
} completion:nil];
I have an Horizontal-only UIScrollView.
it contains several UIImageViews and a borderView for indicating which one is selected.
borderView is a UIView with border and no content.
what I want to do:
when the user tap the imageView, I wish the borderview can move to and overlay on the tapped imageView for indicating.
what I did in my code:
1.Add imageViews with UITapgesture event and borderView to the scrollView
-(void)setStaticFilterToBar
{
_filterList = [APIHelper getStaticFilterList:_originBackgroundImage];
filterScrollView.contentSize = CGSizeMake(320,filterScrollView.contentSize.height);
filterScrollView.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.7f];
int xAis = 64;
for(int i=0; i<_filterList.count; i++)
{
UIImageView *filter = [[UIImageView alloc]initWithImage:[_filterList objectAtIndex:i]];
[filter setUserInteractionEnabled:YES];
[filter setFrame:CGRectMake(i * xAis,5,60,60)];
[filter setTag:i];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self
action:#selector(filterElementTapToApplyFilter:)];
[tap setDelegate:self];
[filter addGestureRecognizer:tap];
[filterScrollView addSubview:filter];
if((i+1) * xAis > 320)
{
filterScrollView.contentSize = CGSizeMake(filterScrollView.contentSize.width + xAis,
filterScrollView.contentSize.height);
}
}
//add borderview
UIView *borderView = [[UIView alloc]init];
borderView.layer.borderColor = [UIColor redColor].CGColor;
borderView.layer.borderWidth = 3.0f;
borderView.layer.cornerRadius = 6;
[filterScrollView addSubview:borderView];
}
-(void)filterElementTapToApplyFilter:(UITapGestureRecognizer *) recognizer
{
//apply filter
[self applyFilterByUIView:recognizer.view];
//move the borderview to the tapped imageView
[self selectSubViewsFromScrollView:filterScrollView TargetFrame:recognizer.view.frame];
}
2.Tap the imageview to change the borderview's frame value to that of imageView's.
(no matter using animationwithDuration:animations:completion: or set the frame directly)
-(void)selectSubViewsFromScrollView:(UIScrollView *)scrollView TargetFrame:(CGRect)targetFrame
{
//borderView is the last subview.
UIView *borderView = [scrollView.subviews objectAtIndex:scrollView.subviews.count-1];
NSLog(#"Before: borderView.frame:(%d,%d,%d,%d)",(int)borderView.frame.origin.x,
(int)borderView.frame.origin.y,
(int)borderView.frame.size.width,
(int)borderView.frame.size.height);
//1
borderView.frame = targetFrame;
//2 for animation
//[UIView animateWithDuration:0.3 animations:^{
// borderView.frame = targetFrame;
//}];
NSLog(#"After: borderView.frame:(%d,%d,%d,%d)",(int)borderView.frame.origin.x,
(int)borderView.frame.origin.y,
(int)borderView.frame.size.width,
(int)borderView.frame.size.height);
}
The problem I have:
it works just fine as I predicted for beginning.
But after scrolling the filterScrollView, click on imageview and the borderview won't change its position anymore.but still apply the right filter correctly.
the value of borderview's frame is changed, but the position in screen didn't change.
what happened here? Did I miss anything? Any help would be appreciated.
Note. I use storyboard and use No autolayout for all views.
We can use Collection View ,collection view also internally work same as scroll view and also we can handle selecting items easily .
in cellforItemAtIndexPath method add selected and normal cells like below
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"collectionViewCell" forIndexPath:indexPath];
if (cell.selected) {
cell.backgroundColor = [UIColor blueColor]; // highlight selection
}
else
{
cell.backgroundColor = [UIColor clearColor]; // Default color
}
return cell;
}
//once it is selected add the color
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
}
//when deselected make it as normal style
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor ClearColor]; // Default color
}
I have a UIView on every UITableViewCell.. This UIView has a event for touch to make it grow in height.
When user taps on this UIView the grow animation works fine, and then i mark a flag to indicate that this cell have a bigger UIView.
But when i need recycle that cell and make her bigger automatically the UIView won't grows when the UITableView displays the cell again. If i change the backgroundColor it displays the change, but don't work if i change their frame height.
A sample code:
Custom UIViewController - UITableViewDelegate, UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([_dataSource count] > 0)
{
Model *model = [_dataSource objectAtIndex:indexPath.row];
ModelCellView *cell = [model getViewFor: tableView];
return cell;
}
return nil;
}
My Model with data
- (ModelCellView*)getViewFor:(UITableView *)tableView
{
NSString *cellIdentifier = #"ModelCell";
ModelCellView *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[ModelCellView alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
//Lots of code
// Reset actionbar (UIView) to specific size
[cell.actionBar resetToState: _actionBarOpened];
//Lots of code
return cell;
}
My custom UIView class (ActionBar) inside custom UITableViewCell
- (void)resetToState:(BOOL)opened;
{
if(opened)
{
_closed = NO;
//[self open]; //tried to change de frame height here, but dont work too.
}
else
{
_closed = YES;
//[self close]; //tried to change de frame height here, but dont work too.
}
[self setNeedsLayout];
}
- (void)layoutSubviews
{
if(!_closed)
{
// This dont work
int sizeToGrow = 60;
[self setFrame: CGRectMake(
_defaultPosition.x,
_defaultPosition.y - sizeToGrow,
_defaultSize.width,
_defaultSize.height + sizeToGrow)];
// This work
self.backgroundColor = [UIColor redColor];
// This work
[_saveButton setFrame: CGRectMake(
_saveButton.frame.origin.x,
INSIDE_VIEW_Y_POSITION,
_saveButton.frame.size.width,
_saveButton.frame.size.height)];
// This work
[_deleteButton setFrame: CGRectMake(
_deleteButton.frame.origin.x,
INSIDE_VIEW_Y_POSITION,
_deleteButton.frame.size.width,
_deleteButton.frame.size.height)];
}
else
{
// This dont work
[self setFrame: CGRectMake(
_defaultPosition.x,
_defaultPosition.y,
_defaultSize.width,
_defaultSize.height)];
// This work
self.backgroundColor = [UIColor greenColor];
// This work
[_saveButton setFrame: CGRectMake(
_saveButton.frame.origin.x,
OUTSIDE_VIEW_Y_POSITION,
_saveButton.frame.size.width,
_saveButton.frame.size.height)];
// This work
[_deleteButton setFrame: CGRectMake(
_deleteButton.frame.origin.x,
OUTSIDE_VIEW_Y_POSITION,
_deleteButton.frame.size.width,
_deleteButton.frame.size.height)];
}
[super layoutSubviews];
}