Updating imageView on UIButton within UITableViewCell - iphone

I have custom UITableViewCells (created in interface builder) which are used for a static UITableView which for the sake of argument I will call the AddUserTableViewController (i.e. I do not use autoreleased cells as I only have 5 rows).
In the top cell (used for the user name) I have embedded a UIButton which I use to open an UIActionSheet which in turn allows an UIImagePicker to set an image on the UIButton (i.e. [button.imageView.image = imageFromImagePicker]). The button has a default image (added in IB) which says "add image".
The image on the button is set without issue and remains in place even when I navigate to the detail page of any of the table cells with the exception of the user name cell which contains the button. When I select this cell the image dissapears and does not reappear once I navigate back to the AddUserTableViewController from the "add name" detail view. The "add image" default image, referred to above, is displayed.
I have tried many strategies amongst which have been:
1) using [self.tableView reloadData], [button.imageView setNeedsDisplay], [self.view setNeedsDisplay] in the viewWillAppear method;
2) using the above methods in the cellForRowAtIndexPath method;
3) using the above methods in the overriden willDisplayCell:forRowAtIndexPath: method;
When I place debugging NSLog statements in the program I can see that the button.imageView.image property is still set to the image selected using the UIImagePicker but it is not displayed (the default image from the nib is displayed).
As I mentioned above, this only happens if I navigate away from the AddUserTableViewController by selecting the UITableViewCell within which the UIButton is embedded.
I am currently at a loss as to what to do and would be extremely grateful for any assistance that anyone could offer. I just need to find a way to update the image on the embedded UIButton in the above-mentioned circumstances.
I've added the a section of the code from the cellForRowAtIndexPath: method just for illustrative purposes -
//populates the personal info section
if (section == kPersonalInfoAddSection) {
//Covers the add image button and the name adding field
if (row == kNameRow) {
UILabel *nameLabel = (UILabel *)[nameCell viewWithTag:kMainTextTag];
UILabel *reqLabel = (UILabel *) [nameCell viewWithTag:kSubTextTag];
//UIButton *imageButton = (UIButton *) [nameCell viewWithTag:kImageTag];
if (mainUser.imagePath != nil) {
UIImage *img = [UIImage imageWithContentsOfFile:mainUserImagePath];
imageButton.imageView.image = img;
[imageButton.imageView setNeedsDisplay];
//[imageButton setNeedsDisplay];
//[nameCell setNeedsDisplay];
NSLog(#"************************** Added the BESPOKE image (%#)to the image button", img);
}
else {
NSLog(#"************************** Added the DEFAULT image (%#)to the image button", addUserImage);
imageButton.imageView.image = addUserImage;
}
UIColor *blackText = [[UIColor alloc] initWithWhite:0 alpha:1];
NSString *firstName;
if (mainUser.firstName){
nameLabel.textColor = blackText;
firstName = mainUser.firstName;
}
else {
nameLabel.textColor = reqLabel.textColor;
firstName = NAME_STRING;
}
NSString *lastName = (mainUser.lastName)? mainUser.lastName : EMPTY_STRING;
NSString *name = [[NSString alloc] initWithFormat:#"%# %#", firstName, lastName];
nameLabel.text = name;
reqLabel.text = REQUIRED_STRING;
[blackText release];
return nameCell;
}

In the cellForRowAtIndexPath are you doing something that would 'unset' the image?

Related

Creating many ViewControllers with different content and moving between them

Im having a ViewController in a storyboard that presents images, i want to have "next" and "prev" buttons to move through instances(10 viewControllers) of the same class that contains different images.
The "first" instance is part of a storyboard, i programmed manually all the images that are subview of a scrollbar. Now the question is how to add properly manual ViewControllers
How do i approach it? Ive been thinking and since only the images change should i make a instance method like "initWithImageArray" ?
Should i create a MutableArray of the class instances ?
If so , is there a way to know which instance of the array i am ? so i would know when to "stop" and not display "next" button or "prev" button
VCDecorations *page1 = [self.storyboard instantiateViewControllerWithIdentifier:#"VCDecorations"];
VCDecorations *page2 = [self.storyboard instantiateViewControllerWithIdentifier:#"VCDecorations"];
VCDecorations *page3 = [self.storyboard instantiateViewControllerWithIdentifier:#"VCDecorations"];
DecoViewControllers = [[NSArray alloc]initWithObjects:page1,page2,page3, nil];
Is there away to know if i"m currently in "page1" or "page2" ?
Thank you.
Instead of using different viewControllers use single viewController and add all images in a an array and when next or Previous button is tapped change the image in imageView according to your array.
Try this Example:
self.imageArray = [NSArray arrayWithObjects:#"image1.png",#"image2.png"],#"image3.png"],#"image4.png"],#"image5.png"],#"image6.png"],nil];
self.currentIndex = 0;
-(IBAction)nextImageClicked:(id)sender{
if (self.currentIndex < self.imageArray.count-1) {
self.currentIndex++;
NSString *imageName = [NSString stringWithFormat:#"%#",[self.imageArray objectAtIndex:self.currentIndex]];
UIImage * image = [UIImage imageNamed:imageName];
self.imageView.image = image;
}
}
-(IBAction)prevImageClicked:(id)sender{
if (self.currentIndex > 0) {
self.currentIndex--;
NSString *imageName = [NSString stringWithFormat:#"%#",[self.imageArray objectAtIndex:self.currentIndex]];
UIImage * image = [UIImage imageNamed:imageName];
self.imageView.image = image;
}
}

UITableView design

I have UITableView where I want design as below.
For this I have images as below.
bottomRow.png
middleRow.png
topAndBottomRow.png
topRow.png
For this I have used below code inside -(UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIImage *selectedImage;
if (indexPath.row==0) {
selectedImage = [UIImage imageNamed:#"topRow.png"];
} else if (indexPath.row == ([products count]-1)) {
selectedImage = [UIImage imageNamed:#"bottomRow.png"];
} else {
selectedImage = [UIImage imageNamed:#"middleRow.png"];
}
if ([products count]==1) {
selectedImage = [UIImage imageNamed:#"topAndBottomRow.png"];
}
UIImageView *selectedBackgroundImageView = [[UIImageView alloc] initWithImage:selectedImage];
cell.selectedBackgroundView = selectedBackgroundImageView;
selectedBackgroundImageView = [[UIImageView alloc] initWithImage:selectedImage];
cell.backgroundView = selectedBackgroundImageView;
Now, everything works perfect.
BUT my designer is insisting on below point.
On tableview, I can have 4 cells at one time. Now let's say I have 6 rows.
Now when I have 6 rows (and tableview can show only 4), the 4th row shows bottomRow.png which is obvious. But my designer is insisting, even the tableview is scrolled, you should have same design for all 4 rows.
Edit 1
First of all, sorry for not being clear.
Well when the UITableView loads, I can only see first 4 cells even there are 6 cells because I have set the height of tableview accordingly. To see rest 2 cells, I have to scroll down. I believe this is how table view works.
Now let's say there are only 4 records. For 4 records, table view looks like image I have.
Now when I have tableview size as 6 (with id as 1-6), the fourth row gets image middleRow.png. Here what my designer wanted is to see bottomRow.png.
Now let's say I scroll down. Now I see row with cell id as 3-6. Now cell with id 3 have middleRow.png, but my designer wanted to see topRow.png.
I know this is ugly, but this is what my designer wanted to see.
Any suggestions to get this done?
One way to achieve your goal: Use numberOfRows to find out if this cell is the last cell.
In your cellForRowAtIndexPath:
if (indexPath.row==0) {
selectedImage = [UIImage imageNamed:#"topRow.png"];
.....
else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1){
selectedImage = [UIImage imageNamed:#"bottomRow.png"];
}
EDIT:
Sorry, I misunderstood your question, I have another proposal that I think you may try...
customCell, with a custom method to set its image. For example,
[customCell setSelectedImage: [UIImage imageNamed:#"middleRow.png"];
2.
In cellForRowAtIndexPath, you can set all cells to be: middleRow.png
3.
After loading of tableView, run a checking method using [self.tableView visibleCells];
eg
- (void) setImageForTopAndBottomCells{
CustomCell *topCell = [[self.tableView visibleCells] objectAtIndex: 0];
CustomCell *bottomCell = [[self.tableView visibleCells] objectAtIndex: self.tableView.visibleCells.count-1];
[topCell setSelectedImage: [UIImage imageNamed:#"topRow.png"];
[bottomCell setSelectedImage: [UIImage imageNamed:#"bottomRow.png"];
}
If your tableView is scrollable, set your ViewController as a UIScrollView delegate, in your delegate method scrollViewDidScroll, run the setImageForTopAndBottomCells method again.
There could be better ways for achieving what you want than the one I proposed, let me know if you found one.
What about using a combination of scrollViewDidScroll:, indexPathsForVisibleRows and reloadRowsAtIndexPaths:withRowAnimation: with something like this:
Every time the table view scrolls you get the list of visible rows using the UIScrollViewDelegate method scrollViewDidScroll:
If it scrolled enough to change the background, call the UITableView's reloadRowsAtIndexPaths:withRowAnimation: passing all the index paths that needs new background
Instead of using indexPath.row == 0 to find the top you would use [indexPath isEqual:[tableView indexPathsForVisibleRows][0]] and the same thing for the other rows
Hope this helps.
You can use middlerow.png as background view of your UITableViewCell in CellForRowAtIndexPath method. Below is the code
cell.backgroundView = [[UIImageView alloc] initWithImage[[UIImageimageNamed:#"middlerow.png"]stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0]];
And after this you can change the Corner radius (add border color/width) of your table view. But for this first you will have to add QuartzCore framework.
self.table.layer.borderColor=[[UIColor colorWithRed:209.0/255 green:209.0/255 blue:209.0/255 alpha:1.0] CGColor];
self.table.layer.borderWidth =3.0;
self.table.layer.cornerRadius =10.0;
Hope this helps.
You can Use this:
NSArray *visible = [tableView indexPathsForVisibleRows];
NSIndexPath *indexpath = (NSIndexPath*)[visible objectAtIndex:0];
-(NSArray *)indexPathsForVisibleRows returns an array of index paths each identifying a visible row in the receiver.So once you get the visible rows, you can use the required image according to indexpath.row.

Every TableView Cell has an image, some are `hidden`, how can i test if all them are not hidden?

In my app, i have a table view and every row/cell has an imageView already on it. Each imageView already has its image assigned to it, each imageView's .hidden property is set to YES until otherwise specified by the user. My question is: How can i test to see if any images are hidden/not hidden. If 1 cell has a visible image, i want to Call a method. And if all the images are gone i want to fire a different method, Any ideas?
I was trying something along the lines of:
if ([self.hand.showBadge boolValue] == YES) {
self.handView.hidden = YES;
}
else{
self.handView.hidden = NO;
}
But unfortunately it didnt work.
Thank you!
One way could be to tag the imageView w/in the cell and then use that tag to iterate over the cells as needed.
Within tableView:cellForRowAtIndexPath, add:
myImageView.tag = MY_CELL_IMAGEVIEW_TAG;
Alternatively, you could just set the tag for your image view in a prototype cell (or your static cells), if using storyboards.
Then, if you wanted to check the visible cells, insert the following code where you'd like to check the image views.
BOOL cellImageViewsAreHidden = YES;
for (UITableViewCell *cell in self.tableView.visibleCells) {
UIImageView *cellImageView = [cell viewWithTag:MY_CELL_IMAGEVIEW_TAG];
if ([cellImageView isHidden] == NO) {
cellImageViewsAreHidden = NO;
break;
}
}
(cellImageViewsAreHidden) ? 'method for all hidden' : 'method for not all hidden' ;

iPhone - call UISwitch that is generated in a UIView when a button is pressed

To clarify my question, my program has three lightbulb on the screen (Customized UIButton)
when any lightbulb is pressed, I programatically generate a UIView with a switch on it
when I turn on the switch, corresponding lightbulb will light up (change its background image)
However, I have trouble accessing this UISwitch since I can't declare it publicly
My code goes something like this:
#property buttonA;
#synthesize buttonA;//all three buttons have their background image set to 'off.png'
- (IBAction)lightBulbPressed:(UIButton *)sender
{
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(1,1, 64, 64)];
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,64,64)];
[mySwitch addTarget:self action:#selector(onOrOff) forControlEvents:UIControlEventValueChanged];
[myView addSubview:mySwitch]
[self.view addSubview:myView];
}
So what troubles me is how to program the selector onOrOff, so that it knows which switch is being touched and change the background image of corresponding button accordingly.
Think about your method:
- (IBAction)lightBulbPressed:(UIButton *)sender {
// your method
}
You already know who called it. This piece of information is stored in sender.
So you can save it and use later in onOrOff
By the way, if you are using UISwitch you have to check
UIControlEventValueChanged
and not UIControlEventTouchUpInside.
EDIT: To pass your sender you can store its value to a NSString *buttonTapped declared in your .h file
- (IBAction)lightBulbPressed:(UIButton *)sender {
if (sender == bttOne) {
buttonTapped = #"ButtonOneTapped";
} else if (sender == bttTwo) {
buttonTapped = #"ButtonTwoTapped";
} else if (sender == bttThree) {
buttonTapped = #"ButtonThreeTapped";
}
// your method
}
- (void)onOrOff {
if ([buttonTapped isEqualToString:#"ButtonOneTapped"]) {
// Button One
} else if ([buttonTapped isEqualToString:#"ButtonTwoTapped"]) {
// Button Two
} else if ([buttonTapped isEqualToString:#"ButtonThreeTapped"]) {
// Button Three
}
}
One way to do so, is taht you give them distinct tag numbers in IB, and in - (IBAction)lightBulbPressed:(UIButton *)sender method, get their tag. e.g. NSInteger pressedButtonTag = [sender tag];, and go from there.
Also, instead of alloc/init myView every time user presses a button, you can add that view in IB, add the switch to it, put in the hierarchy of the owner but not the view, and set an outlet to it in .h. Call it whenever you need it, and again, access the switch by tag e.g. ( UISwitch *mySwitch = (UISwitch *)[myView viewWithTag:kSwitchTag]; ) and do whatever you want to do (on or off), add it to the subview and remove it later. This is more efficient.

UITableViewCell edit mode like contacts app

I'm currently working on an app where a user has to edit his/her profile. I would like to use the edit mode like in the contacts app. (Labels become Textfields)
Is there an easy way to achieve this? Or do I have to replace the cell.detailTextLabel.text with a uitextfield by myself?
Example contacts app editing view:
http://content.screencast.com/users/EricMulder/folders/Jing/media/0839c0c9-43df-4283-bcf1-65f49b43696f/00000047.png
For anyone interested, here is some sample code to add an UITextField to your cell:
cell.textLabel.text = NSLocalizedString(#"nameLabel", #"");
//add textField
if(![cell viewWithTag:101]) {
UITextField *aliasField = [[UITextField alloc] initWithFrame:CGRectMake(93, 13, 225, 44)];
aliasField.text = #"Eric Mulder";
aliasField.font = [UIFont boldSystemFontOfSize:15.0f];
aliasField.tag = 101;
[cell addSubview:aliasField];
}
cell.detailTextLabel.text = nil;
ejazz,
Why do you suppose that they are labels? ; )
You can draw custom cell with UITextField in interface builder. Load it from xib. And change textfields editable property in your implementation of setEditing:animated: method of your view controller.