can't set subview's frame in scrollview after scrolling - ios

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
}

Related

UITableViewCell's subviews can't be round

I want to create a tableview that has some round subview as UIView. I set the UIView's layer.cornerRadius and clipsToBounds. But some views are not round. Who can help me to solve this problem or give me some advice?
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * settCellID = #"settingCellID";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:settCellID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:settCellID];
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(100, 10, 20, 20)];
view.layer.cornerRadius = 10;
view.clipsToBounds = 1;
view.layer.rasterizationScale = [UIScreen mainScreen].scale;
view.layer.shouldRasterize = 1;
view.backgroundColor = [UIColor blueColor];
[cell.contentView addSubview:view];
}
return cell;
}
result:
You Will Try it With Create a Custom Cell Class, and create your view not a programmatically its create using storyboard. and set property of view in custom cell class. then implement above code but a little changes here i have mention it.
static NSString * settCellID = #"settingCellID";
'CustomClassName' * cell = (CustomClassName*)[tableView dequeueReusableCellWithIdentifier:settCellID];
cell.viewPropertyName.layer.cornerRadius = 10;
cell.viewPropertyName.clipsToBounds = YES;
cell.viewPropertyName.maskToBounds =YES;
cell.viewPropertyName.backgroundColor = [UIColor blueColor];
The rasterizationScale and shouldRasterize is for "Off-Screen Rendering",but it has no effect on the round view. and the "view.clipsToBounds = YES" is eque to "view.layer.masksToBounds = 1". I already used the CGContextRef and UIBezierPath to create a round view on the UITableViewCell, but they can't create a real round view.
Inside this clipsToBound is Bool so you should Give YES or NO and Try To use maskToBound = YES for Corner Radius If you want to merge the below view Than use clipsToBound accordingly And I don't think that rasterizationScale and shouldRasterize is useful here. I hope This Will Help you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * settCellID = #"settingCellID";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:settCellID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:settCellID];
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(100, 10, 20, 20)];
view.layer.cornerRadius = 10;
view.clipsToBounds = YES;
view.maskToBounds =YES;
view.layer.rasterizationScale = [UIScreen mainScreen].scale;
view.layer.shouldRasterize = 1;
view.backgroundColor = [UIColor blueColor];
[cell.contentView addSubview:view];
}
return cell;
}
And If You Want To UITableViewCell rounded corners and clip subviews than Follow This Link Click here

How to darken an image (in a collection view) on highlight?

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;
}];
}

Add overlay to CollectionViewCell once it's clicked

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).

Changing the state of the CollectionView Cell

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//NSLog(#"enter category cell");
CategoryViewCell* cell = (CategoryViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.imgCat setImage:[UIImage imageNamed:[categoryImages objectAtIndex:indexPath.row]]];
[cell.labelCatName setText:[[NSString stringWithFormat:#"%#", [catName objectAtIndex:indexPath.row]] capitalizedString]];
if([categories[[NSString stringWithFormat:#"%d",(int)indexPath.row]] isEqual:#YES]) {
//NSLog(#"set border");
cell.layer.borderColor = [UIColor redColor].CGColor;
cell.layer.borderWidth = 3;
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
CategoryViewCell* cell = (CategoryViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
cell.layer.borderWidth = 3;
cell.layer.borderColor = [UIColor redColor].CGColor;
//NSLog(#"%i", (int)indexPath.item);
categories[[NSString stringWithFormat:#"%i", (int)indexPath.item]] = #YES;
}
-(void) collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
CategoryViewCell* cell = (CategoryViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
cell.layer.borderColor = [UIColor clearColor].CGColor;
categories[[NSString stringWithFormat:#"%i", (int)indexPath.item]] = #NO;
}
The problem:
The above code will show you a collectionView with cells that are selected at default. However, the states of these selected cells are not selected. So I have to tap twice to deselect them because the first tap is to select them, and second tap is to deselect them.
I have tried to set selected for cell but it doesn't work either. The cell will have a red border whenever the user selected a cell and clearColor when the user deselect the cell.
I tried:
cell.selected = YES;
But this permanently gives a collectionView Cell a red border.
And add it in cellForItemAtIndexPath method still doesn't do the trick.
[self collectionView:collectionView didSelectItemAtIndexPath:indexPath];
CategoryViewCell.m
-(void) setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected];
//NSLog(#"Pass Select Animated");
if (selected) {
self.flagHighlight = NO;
self.selected = NO;
self.layer.borderColor = [UIColor clearColor].CGColor;
self.layer.borderWidth = 3;
} else {
self.flagHighlight = YES;
self.selected = YES;
self.layer.borderColor = [UIColor redColor].CGColor;
self.layer.borderWidth = 3;
}
}
How would I pre-select a cell when the view is loaded programmatically?
Or even better just change the state of the cell being selected.
Thanks in advance.
Ending up answering my own problem.
so I use [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
in cellForItemAtIndexPath.
Serve the purpose nicely.

UICollectionView didSelectItemAtIndexPath Scrolling

I am using a CollectionView to display an image in. I am using horizontal scrolling with pagination enabled so the user is able to scroll from image to image right to left as they would on the apps screen on iOS. How might I be able to call didSelectItemAtIndexPath to detect which cell the collection view has stopped on without the user having to tap on the cell?
Though it is not relevant:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
titleLabel.alpha = 1.0;
mainTextLabel.alpha = 1.0;
availableLabel.alpha = 1.0;
sizeLabel.alpha = 0.0;
sizeImage.alpha = 0.0;
moreInfoOnSize.alpha = 0.0;
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor lightGrayColor]; // highlight selection
PFObject *selectedObject = [labelFileArray objectAtIndex:indexPath.row];
titleLabel.text = selectedObject[#"labelText"];
PFObject *selectedObject2 = [mainTextArray objectAtIndex:indexPath.row];
mainTextLabel.text = selectedObject[#"mainTextLabel"];
PFObject *selectedObject3 = [availableLabelArray objectAtIndex:indexPath.row];
availableLabel.text = selectedObject[#"availableLabel"];
if ([availableLabel.text isEqual:#"Available"]) {
availableLabel.backgroundColor = [UIColor greenColor];
} else if ([availableLabel.text isEqual:#"Sorry We Are Out!"])
{
availableLabel.backgroundColor = [UIColor redColor];
}
NSLog(#"%#", indexPath);
}
And Image
http://cl.ly/image/3x1R41073W2z
http://cl.ly/image/203Q2E3T2X44
Thank you so much!
You can call visibleCells on your collection view to get the cells currently visible on the screen like this:
// All visible cells (1 or more depending on your layout and cell sizes)
NSArray *visibleCells = [myCollectionView visibleCells];
// Get the first cell from the array
UICollectionViewCell *firstCell = visibleCells.firstObject;

Resources