Using iOS, how would I go about creating a red \"delete\" button similar to the one used when deleting contacts on the iPhone?
Probably the simplest way to do it is to snag this iPhone GUI Photoshop file that contains lots of UI elements in PSD layers, then change the tint of the large button in Photoshop and save it as a PNG.
One advantage of doing it this way is that you can also create versions for button selected and/or highlight state and assign the images to a standard UIButton.
I think those ones are better (and they look fine on retina display too) :
.png generated from this very nice .psd file : http://www.teehanlax.com/blog/2010/08/12/iphone-4-gui-psd-retina-display/
And then use it as a strechable image for the background of your UIButton
:
UIImage* greenButton = [UIImage imageNamed:@"UIButton_green.png"];
UIImage *newImage = [greenButton stretchableImageWithLeftCapWidth:greenButton.size.width/2 topCapHeight:greenButton.size.height/2];
[callButton setBackgroundImage:newImage forState:UIControlStateNormal];
I would like to contribute a solution which does not use images but which gives the same look as the 'delete' button in Contacts. In the below example I will use assume a UITableView with grouped, static cells, designed in storyboard. Make one of the sections have only a single cell. That cell will be the 'delete' button. Give the cell a red background color (f.e. Red 221, Green 0, Blue 2)
What we will do is add two GradientLayers to the cell. The first will cover the upper half of the cell. The second will cover the lower half.
Add QuartzCore to your implementation file:
#import <QuartzCore/QuartzCore.h>
Start with making an outlet to this cell:
@property (strong, nonatomic) IBOutlet UITableViewCell *cellDelete;
Create a method in which the cell will be formatted:
- (void)formatCellDelete
{
// Top Gradient //
CAGradientLayer *gradientTop = [CAGradientLayer layer];
// Make a frame for the layer based on the size of the cells contentView
// Make it half the height
// The width will be -20 so the gradient will not overflow
CGRect frame = CGRectMake(0, 0, _cellDelete.contentView.frame.size.width - 20, _cellDelete.contentView.frame.size.height / 2);
gradientTop.frame = frame;
gradientTop.cornerRadius = 8;
UIColor* topColor = [UIColor colorWithWhite:1.0f alpha:0.75f];
UIColor* bottomColor = [UIColor colorWithWhite:1.0f alpha:0.0f];
gradientTop.colors = [NSArray arrayWithObjects:(id)[topColor CGColor], (id)[bottomColor CGColor], nil];
[_cellDelete.contentView.layer setMasksToBounds:YES];
[_cellDelete.contentView.layer insertSublayer:gradientTop atIndex:0];
// Bottom Gradient //
CAGradientLayer *gradientBottom = [CAGradientLayer layer];
// Make a frame for the layer based on the size of the cells contentView
// Make it half the height
// The width will be -20 so the gradient will not overflow
frame = CGRectMake(0, 0, _cellDelete.contentView.frame.size.width - 20, _cellDelete.contentView.frame.size.height / 2);
// And move to bottom
frame.origin.y = frame.size.height;
gradientBottom.frame = frame;
topColor = [UIColor colorWithWhite:0.0f alpha:0.05f]; //0.20
bottomColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
gradientBottom.colors = [NSArray arrayWithObjects:(id)[topColor CGColor], (id)[bottomColor CGColor], nil];
[_cellDelete.contentView.layer setMasksToBounds:YES];
[_cellDelete.contentView.layer insertSublayer:gradientBottom atIndex:0];
// Define a selected-backgroundColor so the cell changes color when the user tabs it
UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:[UIColor colorWithRed:(float)(0.502) green:0.0 blue:0.0 alpha:1.000]];
bgColorView.layer.cornerRadius = 10;
[_cellDelete setSelectedBackgroundView:bgColorView];
}
The above will give your cell the glass-look like the 'delete' button in Contacts. But we also want it to change color when the user taps it. This is what the last piece of code in the above method will do. It will set a different view with a darker color as the selectedBackgroundView.
After tapping the cell will stay selected and will keep its dark color. To automatically deselect the cell we do the following:
Start with a constant which defines the section nr of your delete cell:
static NSInteger const SECTION_DELETE = 1;
Now implement the (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
method (defined in UITableViewDelegate):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section == SECTION_DELETE){
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
// Navigation logic may go here. Create and push another view controller.
/*
 *detailViewController = [[ alloc] initWithNibName:@"" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
I've also made some buttons...retina and non-retina versions
If you want to use them in a Cell just use the following code in cellForRowAtIndexPath:
UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:[cell.contentView frame]];
[sampleButton setFrame:CGRectMake(0, 0, cell.bounds.size.width-20, 44)];
[sampleButton setBackgroundImage:[UIImage imageNamed:@"button_red.png"] forState:UIControlStateNormal];
[cell addSubview:sampleButton];
You first start with a stretchable image:
alt text http://grab.by/4lP
Then you make a button with the stretched image as the background and apply text.
UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(kLeftMargin, 10, self.view.bounds.size.width - kLeftMargin - kRightMargin, 52)];
[sampleButton setTitle:@"Button Title" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];
[sampleButton setBackgroundImage:[[UIImage imageNamed:@"redButton.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
[sampleButton addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton];
Obviously, you will need to adjust the frame origin and size to match your app, as well as the target, selector, and title.
You can create a separate section in your grouped table view, give that section only one row, and set that cell's background image to a red gradient image. You'll have to recreate that image on your own, though.