Before asking this question I googled a lot but not able to find suitable answer.
I'm have a UITableView with n number of Columns. The thing is the Column is Grouped according to a key. So my UITableView header is splitted into two, one for the column group and and this column group is divided to show columns.
I have created a custom class for the cell there I display radio button in each column.
Code:
In cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GridTableViewCell *cell = nil; // My custom class for cell
CGFloat startX = 230;
if (cell == nil)
{
cell = [[GridTableViewCell alloc] initWithStyle1:UITableViewCellStyleDefault reuseIdentifier:#"Cell" withRows:[self.rowHeaderArray objectAtIndex:indexPath.row]];
for (int i = 0; i < [self.groupColumNmeArray count]; i++) { // groupColumNmeArray contains the Column Group name
NSArray *values = [_subColumnDict objectForKey:[self.groupColumNmeArray objectAtIndex:i]]; // subColumnDict contains the value for each column
self.originalDataArray = [CustomTableHeaderParser parseColumnInfo:values];// Parsing the values array for getting column name, type, width etc
for (CustomTableColumn *column in self.originalDataArray)
{
switch (column.columnType) // acc. to column type display the cell with values.
{
case RadioBtn:
{
_btTemp = [[UIButton alloc]initWithFrame:CGRectMake(startX, 2, subCellWidth , 40)];
[_btTemp setTag:indexPath.row];//indexPath.row];
[_btTemp addTarget:self action:#selector(radioButtonsClicked:) forControlEvents:UIControlEventTouchUpInside];
[_btTemp setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
[_btTemp setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_btTemp.titleLabel.font =[UIFont systemFontOfSize:14.f];
[self.radioButtons addObject:_btTemp];
[cell addSubview:_btTemp];
}
break;
startX += 2+subCellWidth;
}
}
}
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.frame];
cell.selectedBackgroundView.opaque = YES;
return cell;
}
Radio button click action method;
-(IBAction) radioButtonsClicked:(UIButton *) sender {
if ([sender isSelected]) {
[sender setSelected: NO];
[sender setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
} else {
[sender setSelected: YES];
[sender setImage:[UIImage imageNamed:#"radio-on.png"] forState:UIControlStateNormal];
}
NSLog(#"BUTTON TAG %ld",(long)sender.tag);
}
So I'm able to make selections for radio buttons in all column but actually what I want is For each column group only one radio button is selectable.
Can anybody help me. Any help would be greatly appreciable.
You can set other button's selection status as following
-(IBAction) radioButtonsClicked:(UIButton *) sender {
sender.selected = !sender.selected;
for (UIView *vw in sender.superview.subviews)
{
if([vw isKindOfClass:[UIButton class]] && vw != sender)
{
UIButton *otherBtn = (UIButton*)vw;
otherBtn.selected = NO;
}
}
}
for setting button Image - on/off, write that code at the time of creating button in cellforrow..
[_btTemp setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
[_btTemp setImage:[UIImage imageNamed:#"radio-on.png"] forState:UIControlStateSelected];
Related
I have students attendance list in UITableView. Where each cell having an UIButton to set student attendance like Present, Absent and Leave on button click. How can I achieve this on single button.
You can do this by simply implementing the following #selector for your UIButton in UITableViewCell.
- (void)btnSetMode:(id)sender
{
UIButton *btn = (UIButton *)sender;
if (btn.tag == 0)
{
[btn setTitle:#"Present" forState:UIControlStateNormal];
btn.tag = 1;
// Define your required task...
}
else if (btn.tag == 1)
{
[btn setTitle:#"Absent" forState:UIControlStateNormal];
btn.tag = 2;
// Define your required task...
}
else if (btn.tag == 2)
{
[btn setTitle:#"Leave" forState:UIControlStateNormal];
btn.tag = 3;
// Define your required task...
}
else if (btn.tag == 3)
{
[btn setTitle:#"Attendance" forState:UIControlStateNormal];
btn.tag = 0;
// Define your required task...
}
}
Your single button will do all the required task as you wanted.
If you have An UIButton in your tableViewCell then add Target to your UIButton and set button Tag with indexPath.row in cellForRowAtIndexPath like-
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
attendanceListTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.studentNameLbl.text=[NSString stringWithFormat:#"Student %ld",(long)indexPath.row];
cell.editBtn.tag=indexPath.row;
[cell.editBtn setTitle:[attandanceArry objectAtIndex:indexPath.row] forState:UIControlStateNormal];
[cell.editBtn addTarget:self action:#selector(editAttendance:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(void)editAttendance:(id)sender{
UIButton *btn=(UIButton*)sender;
if ([btn.titleLabel.text isEqualToString:#"P"]) {
[btn setTitle:#"A" forState:UIControlStateNormal];
[attandanceArry replaceObjectAtIndex:btn.tag withObject:#"A"];
}else if ([btn.titleLabel.text isEqualToString:#"A"]) {
[btn setTitle:#"L" forState:UIControlStateNormal];
[attandanceArry replaceObjectAtIndex:btn.tag withObject:#"L"];
}else if ([btn.titleLabel.text isEqualToString:#"L"]) {
[btn setTitle:#"P" forState:UIControlStateNormal];
[attandanceArry replaceObjectAtIndex:btn.tag withObject:#"P"];
}
}
In this attandanceArry is mutableArray having all default value is "P" with capacity of your number of students and editBtn is your cell UIButton. Here I use custom tableViewCell class i.e. attendanceListTableViewCell class having UIButton. At the end you can use attandanceArry as result array when you complete editing attendance. I hope this will help you...:)
Change the button title and background color when it's clicked. Personally, I would use three different buttons so that all different options would be visible at the same time. UIPicker is one option too.
Is a UISegmentedControl what you are looking for?
See the Apple Documentation here. It can be configured in a storyboard with the correct number of segments and segment titles. When the user selects a segment it will be highlighted, and any other segments are deselected.
I know this question is very similar to other questions, but i doesn't resolve the problem using that approach.i follow most of the available solution but it doesn't work for me..
I know that when tableview scrolls it reuse cell but i doesn't know the approach of maintaining the button state . i'll try with following link
How to use Reusable Cells in uitableview for IOS
IOS: Maintaining button state in uitableviewcell
How to Handle Favourite button clicks in custom Tableview cells iOS?
I done all the things.use tags, use touch points and all but nothing seems to work for me.so help me out..and here is my sample code
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
/*
* Set button for cell to subscribe with it
*/
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;
[cell.btnsubscribe addTarget:self action:#selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
if (![_arraybtnState containsObject:listid] )
{
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:YES];
}
else {
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:NO];
}
return cell;
}
_arrbtnstate contains the ids that user follows.
and listid contains unique id comes from database too
And the click event method...
- (IBAction)clickBtnSubscribe:(id)sender {
UIButton *button = (UIButton*)sender;
NSLog(#"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
if (button.selected) {
[self.arraybtnState addObject:tagnum];
[button setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
NSLog(#"Subscribe");
[self subscribeButton:button.tag];
[button setSelected:NO];
}
else
{
[self.arraybtnState removeObject:tagnum];
[button setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
NSLog(#"unsubscribe");
[self unsubscribeButton:button.tag];
[button setSelected:YES];
}
}
Note: In this code, button is created in storyboard.,but i'll also tried without storyboard too.
First of all this line cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303]; is to be changed. Follow the below steps and try
in custom subcategoryCell connect IBOutlet to btnsubscribe.
in storyboard, you can set both selected and not normal images to a UIButton, here it is btnsubscribe. If you find it difficult follow this
in cellForRowAtIndexPath: remove below lines
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
update the following lines
if (![_arraybtnState containsObject:listid] )
{
[cell.btnsubscribe setSelected:YES];
}
else {
[cell.btnsubscribe setSelected:NO];
}
or simply [cell.btnsubscribe setSelected:(![_arraybtnState containsObject:listid] )];
Keep the addTarget in cell for row method (since you have custom cell class, it is better to move the button action to cell class and pass the result to viewcontroller by callback or delegate. not discussing that now but recomments) and update the clickBtnSubscribe: by removing
[button setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
these lines. assumes other parts are working properly.
You are setting Selected and unselected image for button's Normal state in both cases i.e UIControlStateNormal.
When you are using selected method you do not require to setImage again. Just set Image for Normal and selected state for button properly in cellForRowAtIndexpath or in xib. You are done.
First remove the setting image in clickBtnSubscribe:() method.
Now in your storyboard set images for Normal and selected state.
Also remove set Image in cell for row at indexpath as you have already done in view.
You can maintain the state of the buttons as-
// initialize your array only once
_arraybtnState = [[NSMutableArray alloc] init];
// cell for row at index path would be
//initially each cell will have follow image
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
[cell.btnsubscribe setTag: indexPath.row];
[cell.btnsubscribe addTarget:self action:#selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] )
{
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:YES];
}
else
{
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:NO];
}
return cell;
}
- (IBAction)clickBtnSubscribe:(id)sender {
UIButton *button = (UIButton*)sender;
NSLog(#"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
if (button.selected) {
[self.arraybtnState addObject:tagnum];
NSLog(#"Subscribe");
[self subscribeButton:button.tag];
[button setSelected:NO];
}
else
{
[self.arraybtnState removeObject:tagnum];
NSLog(#"unsubscribe");
[self unsubscribeButton:button.tag];
[button setSelected:YES];
}
//after doing modification update the respective row as
UIButton *button = (UIButton *)sender;
// Find Point in Superview
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
// Infer Index Path
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInSuperview];
//relaod the row
NSArray* indexPathModel = [NSArray arrayWithObjects:indexPath, nil];
[self.tableView reloadRowsAtIndexPaths: indexPathModel withRowAnimation:UITableViewRowAnimationNone];
}
reloading row will reflect the changes done in the modal to the UI.
I think you can put this line in viewDidLoad or after you load what all have subscribed .
_arraybtnState = [NSMutableArray arrayWithArray:[self.strSubscribe componentsSeparatedByString:#","]];
Then the cellForRowAtIndexPath will loook like below
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
/*
* Set button for cell to subscribe with it
*/
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;
[cell.btnsubscribe addTarget:self action:#selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] ) {
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
}
else {
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
}
return cell;
}
and then the btn click method as
- (IBAction)clickBtnSubscribe:(id)sender {
UIButton *button = (UIButton*)sender;
NSLog(#"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
if (![_arraybtnState containsObject:tagnum] )
{
[_arraybtnState addObject:tagnum];
[button setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
NSLog(#"Subscribe");
[self subscribeButton:button.tag];
}
else {
[self.arraybtnState removeObject:tagnum];
[button setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
NSLog(#"unsubscribe");
[self unsubscribeButton:button.tag];
}
}
Two easy solutions and quite fast to implement :
Keep track of the state in an array/dictionary
You can store your states in an array of states, i'll make an example.
(Note: i'm coding this without compiling, I might mispel some stuff, feel free to edit my post)
in your viewDidLoad
arrState = [[NSMutableArray alloc]init];
for (yourObject *object in dataArray){
//For every object that you use to load your tableview, this can be strings or anything really
[arrState addObject:#NO];
}
In your cellForRow
...
//This will either put YES or NO depending on the element in the state array.
[cell.button setSelected:[arrState objectAtIndex:indexPath.row]];
...
Boom, done.
You can also keep track of this in a database or anything persistent, and then you'd simply load whatever your field contains for a selected record. This is more relevant if we're talking about, for example, something like favourites or something that will be there until the user decides otherwise. If it's just to keep track of your button states during the lifetime of your view, then ignore this part of the answer.
If you need to keep it alive forever (even when the app closes), then you'd most probably need a database :)
I have two button when i click on btn1 UITableview display same as below image 1 and i click on btn2 UIableView display same as below image 2
I am using custom cell. I have done with table reload but it display "checkbox" in both UITableview.
BOOL isChecked;
isChecked = true;
-(IBAction)btn1:(id)sender
{
isChecked = true;
[self.mytableview reload];
}
-(IBAction)btn2:(id)sender
{
isChecked = false;
[self.mytableview reload];
}
cellRowAtIndexPath method in:
if(isChecked)
{
customcell.trLabel.text = [arr1 objectAtIndex : indexpath.row]
[customcell.button setImage:[UIImage imageNamed:#"checked.png"] forState:UIstateselected];
[customcell.button setImage:[UIImage imageNamed:#"unchecked.png"] forState:UIstateNormal];
[customcell.button addTarget:self action:#selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
customcell.trLabel.text = [arr2 objectAtIndex : indexpath.row]
[customcell.buttton = NULL;
}
difrent method
-(void)checkButtonTapped:(id)sender
{
sender.selected = !sender.selected;
}
image 1
image 2
i have done select all.
didSelect Method:
DemoTableViewCell *cell;
if(indexPath.row == 0)
{
for (int i = 0; i < [self.tableview1 numberOfSections]; i++) {
for (int j = 0; j < [self.tableview1 numberOfRowsInSection:i]; j++) {
NSUInteger ints[2] = {i,j};
NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:ints length:2];
cell = (DemoTableViewCell *)[self.tableview1 cellForRowAtIndexPath:indexPath];
//Here is your code
UIButton *btn = cell.button;
if( [[btn imageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"checked.png"]])
{
[btn setImage:[UIImage imageNamed:#"unchecked.png"] forState:UIControlStateNormal];
// other statements
}
else
{
[btn setImage:[UIImage imageNamed:#"checked.png"] forState:UIControlStateNormal];
}
}
}
}
else
{
cell = (DemoTableViewCell *)[self.tableview1 cellForRowAtIndexPath:indexPath];
UIButton *btn = cell.button;
if( [[btn imageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"checked.png"]])
{
[btn setImage:[UIImage imageNamed:#"unchecked.png"] forState:UIControlStateNormal];
// other statements
}
else
{
[btn setImage:[UIImage imageNamed:#"checked.png"] forState:UIControlStateNormal];
}
}
My question is:
1) select all option select all "checkbox" that is done but when i "uncheck" any item of them select all option also be "uncheck".
2) Not display "checbox" in image 2 UITablevieCell.
3) When i "uncheck" item3 and click again select all option deselect all "checkbox" except item3 and item3 is checked.
Solution to 2) Not display "checbox" in image 2 UITablevieCell
You need to create a different prototype cell with no checkbox.
Then in cellRowAtIndexPath method use that cell if button 2 was clicked
For other questions, you need to store the state of each checkbox (in array or dictionary) . Then in cellRowAtIndexPath method depending on the state of checkbox in that row, tick or untick the checkbox of the cell
1) Have NSMutableArray in your ViewController where you would store all your checkboxes state (ticked or unticked).
2) In the method that is called when checkbox is ticked/unticked, update 1 or 0 in the array like:
- (void) actionCheckbox {
self.mydata[indexPath.row] = 1; // set 0 or 1
[self.tableview reloadRowsAtIndexPath ...]; // Don't remember exact method name
}
3) In cellRowAtIndexPath,
if(self.mydata[indexPath.row] == 1) {
// tick checkbox for this row
} else {
// untick checkbox for this row
}
i m having a simple section table view. I have added a button at the left side of image.This button is selectable.Only one button (each cell have single button of same type) can be selected at a time and selected button background image changes to a specific selected image, others button back ground image changes to deselect image.If you tap again on selected image it remains selected.
How ever i am not getting correct behaviour.
code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// UITableViewCell *cell=nil;
CustomCellMasterCustomer *cell=nil;
static NSString *cellIdentifier=#"Locations";
Customer *mCustomer;
cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell==nil){
// cell=[self reusableContentWithIdentifier:cellIdentifier];
cell=(CustomCellMasterCustomer *)[self reusableContentWithIdentifier:cellIdentifier];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = indexPath;
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageDisabled.png"] forState:UIControlStateNormal];
[button setFrame:CGRectMake(10, 5, 36, 30)];
[button addTarget:self action:#selector(viewDetail:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
cell.aCustomer = mCustomer;//alok added
if (indexPath == self.mPreviousIndex)
{
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];
}
else
{
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageDisabled.png"] forState:UIControlStateNormal];
}
return cell;
}
-(void)viewDetail:(id)sender
{
CGPoint buttonOrigin = [sender frame].origin;
// this converts the coordinate system of the origin from the button's superview to the table view's coordinate system.
CGPoint originInTableView = [self.allCustomerTable convertPoint:buttonOrigin fromView:[sender superview]];
// gets the row corresponding to the converted point
NSIndexPath *rowIndexPath = [self.allCustomerTable indexPathForRowAtPoint:originInTableView];
CustomCellMasterCustomer *cell = (CustomCellMasterCustomer *)[self.allCustomerTable cellForRowAtIndexPath:rowIndexPath];
[self fillDetailViewWithCustomerInformation:cell.aCustomer];
//change button background image
UIButton *btn = (UIButton *)sender;
[btn setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];
self.mPreviousIndex = rowIndexPath;
[self.allCustomerTable reloadData];
}
what wrong i am doing,
any suggestion
Try this. Because indexpath always recreate with same row and section number. It won't same as previous.
if (indexPath.row == self.mPreviousIndex.row && indexPath.section == self.mPreviousIndex.section)
{
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];
}
And this two line of code, not needed anymore
/* UIButton *btn = (UIButton *)sender;
[btn setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];*/
You should not add a button out side the if block. In UITableView cells will be reused, if the cell is reused and at already has a button added to contentView then you should not add one more on top of it. so create a custom cell and make the buttion instance visible outside the class by declaring the buttion property in customCell.h. Now check the condition -
if (selected)
{
cell.button.backgroundImage = selectedImage;
}
else
{
cell.button.backgroundImage = unselectedImage;
}
I have a collection view where each cell contains 7 buttons, (created via code not storyboard).
They are sharp initially, however if I scroll up / down a few times the quality decreases.
The sharpness is restored when I change views and return.
Any ideas ?
Addit:
I am making the buttons like this, within a loop (can be 1 to 7 buttons)
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"patientCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
Patient *aPt = [self.fetchedResultsController objectAtIndexPath:indexPath];
PatientCVCell *ptCell = (PatientCVCell *) cell;
ptCell.ptName.text = aPt.name;
ptCell.ptRoom.text = aPt.room;
ptCell.ptRx.text = aPt.diagnosis;
int xPos = 20;
NSArray *daysForRx = aPt.ofList.listDays;
// loop through to add button for each day of Rx
for (int i = 0; i < [daysForRx count]; i++) {
// get the treatment day that == postition in array
for (Treatment *t in aPt.patientRx) {
if (t.day == daysForRx[i]) {
//NSLog(#"%i", xPos);
StatusButton *testButton = [StatusButton buttonWithType:UIButtonTypeCustom];
testButton.frame = CGRectMake(xPos, 110, 28, 28);
testButton.btnTreatment = t;
// match status of the RX to the correct button
if ([t.status intValue] == NotSeen) {
[testButton setImage:[UIImage imageNamed:#"toSee"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeen;
}
else if ([t.status intValue] == SeenNotCharted) {
[testButton setImage:[UIImage imageNamed:#"seenNotCharted"] forState:UIControlStateNormal];
testButton.linkNumber = SeenNotCharted;
}
else if ([t.status intValue] == SeenCharted) {
[testButton setImage:[UIImage imageNamed:#"seenCharted"] forState:UIControlStateNormal];
testButton.linkNumber = SeenCharted;
}
else if ([t.status intValue] == NotSeeing) {
[testButton setImage:[UIImage imageNamed:#"notSeeing"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeeing;
}
else if ([t.status intValue] == NotSeeingDC) {
[testButton setImage:[UIImage imageNamed:#"notSeeingDischarged"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeeingDC;
}
[testButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:testButton];
xPos = xPos + 36;
}
}
}
return cell;
}
The image is correct size so no need to scale the image.
Occurs in simulator and on device.
After looking more closely, the inside of the images are sharp! So this issue has to do with the transparency for my circle shape of a button within a square button!
You are dequeuing a cell, then you add your buttons to the dequeued cell.
Those buttons never get removed. When you scroll up and down cells that go off screen are put on the dequeue queue. At this time they still have the buttons, then they are dequeued and you add more buttons. You have many buttons above each other, and that's why it looks blurry and your memory footprint gets bigger.
I would add the buttons from inside the cell. Save them in a array so you can remove them later. Then I would add a method to set the number of buttons you'll need. Like this:
// header
#property (strong, nonatomic) NSMutableArray *buttons;
// implementation
- (void)setNumberOfButtons:(NSInteger)numberOfButtons withTarget:(id)target selector:(SEL)selector {
// remove existing buttons from view
[self.buttons makeObjectsPerformSelector:#selector(removeFromSuperview)];
// "save" existing buttons in a reuse queue so you don't have to alloc init them again
NSMutableArray *reuseQueue = self.buttons;
self.buttons = [NSMutableArray arrayWithCapacity:numberOfButtons];
for (NSInteger i = 0; i < numberOfButtons; i++) {
UIButton *button = [reuseQueue lastObject];
if (button) {
[reuseQueue removeLastObject];
}
else {
button = [UIButton buttonWithType:UIButtonTypeCustom];
// you should always use the same target and selector for all your cells. otherwise this won't work.
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
}
[self.buttons addObject:button];
button.frame = ....
// don't set up images or titles. you'll do this from the collectionView dataSource method
}
}
you would then set the number of buttons in collectionView:cellForItemAtIndexPath: and configure each button according to your needs. something along those lines:
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Cell *cell = ... dequeue ...
Object *object = ... get from your backend ...
/* configure your cell */
if ([cell.buttons count] != object.numberOfItems) {
// no need to remove and add buttons if the item count stays the same
[cell setNumberOfButtons:object.numberOfItems withTarget:self selector:#selector(buttonPressed:)];
}
for (NSInteger i = 0; i < [object.numberOfItems count]; i++) {
UIButton *button = cell.buttons[i];
[button setImage:... forState:UIControlStateNormal];
}
}
And the action would look like this:
- (IBAction)buttonPressed:(UIButton *)sender {
UICollectionView *collectionView;
CGPoint buttonOriginInCollectionView = [sender convertPoint:CGPointZero toView:collectionView];
NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:buttonOriginInCollectionView];
NSAssert(indexPath, #"can't calculate indexPath");
Cell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell) {
NSInteger pressedButtonIndex = [cell.buttons indexOfObject:sender];
if (pressedButtonIndex != NSNotFound) {
// do something
}
}
else {
// cell is offscreen?! why?
}
}
pretty straight forward. Get the indexPath, get the collectionViewCell, check which index the pressed button has