I'm creating Collection View Cells programmatically using Facade framework to position it right. Unfortunately buttons inside cells doesn't react to touches.
Collection View is created using storyboard.
CollectionViewCell appearance loading:
_likesButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_likesButton setBackgroundColor:[UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:0.10]];
_likesButton.contentEdgeInsets = UIEdgeInsetsMake(5, 8, 5, 8);
_likesButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
_likesButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
[_likesButton setAttributedTitle:[self attributedSpacedStringFromString:#"+10039" withColor:[UIColor flatWhiteColor] withFont:[UIFont fontWithName:#"OpenSans-Bold" size:12]] forState:UIControlStateNormal];
_likesButton.layer.cornerRadius = 12;
[_likesButton sizeToFit];
_likesButton.userInteractionEnabled = YES;
In Collection View:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
cell.likesButton.tag = indexPath.row;
[[cell likesButton] addTarget:self action:#selector(showAlert:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
What I'm doing wrong?
Best regards,
Adrian.
Ok I just figured it out...
I had image as background (UIButton was subview) and UIImageView has userInteractionEnabled disabled as default. Setting this property to YES, fixed issue.
Related
I need cells in a UICollectionView which will either show text or an image.
I am implementing this by creating my own UICollectionViewCell having two properties - UIImage property and NSString property.
Depending on which property the caller sets, I show either the image or the text. The calling collectionview is also reusing the cells by using :
cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
But whenever I reload the collectionview in my code the cells get all messed up - they show empty buttons. What am I doing wrong? Let me know if you need me to post any other specific code piece. I didn't want to clutter my question with useless code.
In my CollectionViewCell, I am resetting both the label and the image:
-(void) prepareForReuse {
[super prepareForReuse];
[_button setTitle:#"" forState:UIControlStateNormal];
[_button setImage:nil forState:UIControlStateNormal];
[_button removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
}
cellForItemAt code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
NSInteger position = indexPath.row;
long listIdx = position - 1;
if (listIdx == ADD_ICON_INDEX) {
UIImage * addImage = [self _getAddImage];
[cell setButtonImage:addImage target:self action:#selector(_addButtonClicked:)];
cell.button.tag = listIdx;
return cell;
}
NSString *title= _visibleButtons[listIdx];
[cell setButtonTitle:title target:self action:#selector(_buttonClicked:)];
cell.backgroundColor = [UIColor clearColor];
cell.button.tag = listIdx;
return cell;
}
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 have a UITableViewCell with a accessorytype detail indicator. When I resize the cell, the cells accessory centers itself horizontally. How can I make it stay on top, and not center itself?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
customCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellID" forIndexPath:indexPath];
return cell;
}
I'd prefer doing it in the storyboard if possible, if not, I'm happy to hear how to do it programatically.
My mistake, Actually you can't do any change in default accessoryView of tableView, You need to create a custom accessoryView for your cell. Just ignore the accessory type because it will not longer matters once you create your own accessoryView.
try this code in CellForRowAtIndexPath
if(!cell.accessoryView)
{
UIImage *image = [UIImage imageNamed:#"image.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
//add target if necessary
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
//apply customisations
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
}
I have code here that generates a list of cells that contain buttons.
I'm pretty sure there is a way to make it so that I am creating 1 button object instead of 20, but I'm not quite sure how to implement that?
I need some guidance as to where to make it so I only create 1 button object.
Additionally, I might be making 20 cell objects when I only need 1 as well?
I don't totally understand how to utilize memory well yet.
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"TimesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//[cell sizeToFit];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if([cell.contentView viewWithTag:3] != nil){
[[cell.contentView viewWithTag:3] removeFromSuperview];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(customActionPressed:)
forControlEvents:UIControlEventTouchDown];
[button setTitleEdgeInsets:UIEdgeInsetsMake(-10.0f, 0.0f, 0.0f, 0.0f)];
button.frame = CGRectMake(5, 5, 310, 50);
button.tag = 3;
int rows = [yourDefaultActivities count];
int rowsl = rows - 1;
float r = 1+(((255-1+75)/rowsl)*(indexPath.row));
if(r > 255){
r = 255;
}
float g = 255-(((255-1+75)/rowsl)*(indexPath.row));
if(g < 0){
g = 255-fabsf(g);
}else{
g = 255;
}
float b = 1;
UIColor *thisColor = [UIColor colorWithRed:r/255 green:g/255 blue:b/255 alpha:1];
button.backgroundColor = thisColor;
button.clipsToBounds = YES;
button.layer.cornerRadius = 15;
button.titleLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:14];
[button setTitle:[[yourDefaultActivities objectAtIndex:indexPath.row] objectAtIndex:0] forState:UIControlStateNormal];
[button.titleLabel setTextColor:[UIColor blackColor]];
[button.titleLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:14]];
[cell addSubview:button];
return cell;
}
EDIT: I tried to remove the buttons every time I created a new one, but I must be doing it wrong..
One button object can't appear in 8 cells at once -- you do need as many cells and buttons as will fit on the screen at any time (it looks like 8 or 9). But 8 or 9 cell with buttons in them should not cause any memory problems -- buttons aren't that expensive. The problem with the code you posted though, is that it is adding buttons every time cellForRowAtIndexPath is called, which happens a lot when you scroll. Since cells are reused, you don't want to be adding a button to a cell that already has one. The easiest solution, in my opinion, is to make a custom cell in the storyboard, and add you buttons there. You can still set their color in code based on the indexPath so you get the look you want. Alternately, you can check whether the cell (actually the cell.contentView which is where you should be adding them, not directly to the cell) has a subview of class UIButton, and only add a button if it doesn't already have one.
After Edit:
In answer to your comment, you don't need to make the rounded button in the storyboard, you can just add a button (type custom) to your subclassed cell, and then modify its look in code. Here is an example of what I mean. In this test app, I created a custom cell class (RDCell) and changed the class of the cell in the storyboard to that. I added a custom button to the cell, positioned and sized it with constraints, and made an IBOutlet to it in RDCell.h. Here is what I have in the table view controller:
#import "TableController.h"
#import "RDCell.h"
#implementation TableController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(RDCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.button.backgroundColor = [UIColor colorWithHue:.15 + (indexPath.row/30.0) saturation:1 brightness:1 alpha:1];
cell.button.layer.cornerRadius = 15;
cell.button.titleLabel.textColor = [UIColor blackColor];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
[cell.button addTarget:self action:#selector(customActionPressed:) forControlEvents:UIControlEventTouchUpInside];
cell.button.tag = indexPath.row;
return cell;
}
-(void)customActionPressed:(UIButton *) sender {
NSLog(#"button pressed in row: %d",sender.tag);
[self.tableView reloadRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:sender.tag inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
This was the resultant view:
I put a log in initWithCoder for RDCell, and it's called only 12 times (the max. number of cells on the screen at any one time), so there's never more than 12 cells or 12 buttons.
I'm trying to add subviews to a view according to the cell of the tableview .. i've done this code already
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
VerseCell *cell = (VerseCell *)[tableView cellForRowAtIndexPath:indexPath];
rowSelected = indexPath.row;
CGRect cellRect = cell.frame;
UIView *cellView =[[UIView alloc]initWithFrame:CGRectMake(cellRect.origin.x+4, cellRect.origin.y+15, cellRect.size.width-20, 70)];
UIImageView* background =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"FavoritePanelBackground"]];
background.frame =CGRectMake(cellRect.origin.x+4, cellRect.origin.y+15, cellRect.size.width-20, 70);
[cellView addSubview:background];
[cellView setBackgroundColor:[UIColor redColor] ];
UIButton * favoritsB = [[UIButton alloc]initWithFrame:CGRectMake(cellRect.origin.x+10, cellRect.origin.y+15, 60, 40)];
[favoritsB setBackgroundImage:[UIImage imageNamed:#"MofadalatNormalIcon.png"] forState:UIControlStateNormal];
[favoritsB setBackgroundImage:[UIImage imageNamed:#"MofadalatTappedIcon.png"] forState:UIControlStateHighlighted];
[favoritsB addTarget:self action:#selector(favorite) forControlEvents:UIControlEventTouchUpInside];
[cellView addSubview:favoritsB];
cellView=nil;
}
the problem is .. that this code work as expected in the first row only.. and when click on next cell it shows the main UIVIew (which i've mark with red background) in the expected position while the sub views of it is going really far down... so what i'm doing wrong here.. and is there another approach for what i'm doing if that will not work?
Where are you trying to add these view? Inside the table view cell? If so, you never add cellView as a subview of cell. IF that's what you're trying to do, add this line just above cellView = nil:
[cell addSubview:cellView];