How do I display the standard checkmark on a UICollectionViewCell?
I ended up recreating the checkmarks using PaintCode. Here's what they look like:
They're drawn with vector graphics, so they'll look great at whatever size you want. These are 30x30. I also included an option to use a grayed-out checkmark instead of the open circle when an item is not selected.
To use these, copy the following class into your project. Then, add a UIView to your storyboard or xib, and set its custom class to SSCheckMark.
SSCheckMark.h
#import <UIKit/UIKit.h>
typedef NS_ENUM( NSUInteger, SSCheckMarkStyle )
{
SSCheckMarkStyleOpenCircle,
SSCheckMarkStyleGrayedOut
};
@interface SSCheckMark : UIView
@property (readwrite) bool checked;
@property (readwrite) SSCheckMarkStyle checkMarkStyle;
@end
SSCheckMark.m
#import "SSCheckMark.h"
@implementation SSCheckMark
- (void) drawRect:(CGRect)rect
{
[super drawRect:rect];
if ( self.checked )
[self drawRectChecked:rect];
else
{
if ( self.checkMarkStyle == SSCheckMarkStyleOpenCircle )
[self drawRectOpenCircle:rect];
else if ( self.checkMarkStyle == SSCheckMarkStyleGrayedOut )
[self drawRectGrayedOut:rect];
}
}
- (void) setChecked:(bool)checked
{
_checked = checked;
[self setNeedsDisplay];
}
- (void) setCheckMarkStyle:(SSCheckMarkStyle)checkMarkStyle
{
_checkMarkStyle = checkMarkStyle;
[self setNeedsDisplay];
}
- (void) drawRectChecked: (CGRect) rect
{
//// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();
//// Color Declarations
UIColor* checkmarkBlue2 = [UIColor colorWithRed: 0.078 green: 0.435 blue: 0.875 alpha: 1];
//// Shadow Declarations
UIColor* shadow2 = [UIColor blackColor];
CGSize shadow2Offset = CGSizeMake(0.1, -0.1);
CGFloat shadow2BlurRadius = 2.5;
//// Frames
CGRect frame = self.bounds;
//// Subframes
CGRect group = CGRectMake(CGRectGetMinX(frame) + 3, CGRectGetMinY(frame) + 3, CGRectGetWidth(frame) - 6, CGRectGetHeight(frame) - 6);
//// Group
{
//// CheckedOval Drawing
UIBezierPath* checkedOvalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(group) + floor(CGRectGetWidth(group) * 0.00000 + 0.5), CGRectGetMinY(group) + floor(CGRectGetHeight(group) * 0.00000 + 0.5), floor(CGRectGetWidth(group) * 1.00000 + 0.5) - floor(CGRectGetWidth(group) * 0.00000 + 0.5), floor(CGRectGetHeight(group) * 1.00000 + 0.5) - floor(CGRectGetHeight(group) * 0.00000 + 0.5))];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, shadow2Offset, shadow2BlurRadius, shadow2.CGColor);
[checkmarkBlue2 setFill];
[checkedOvalPath fill];
CGContextRestoreGState(context);
[[UIColor whiteColor] setStroke];
checkedOvalPath.lineWidth = 1;
[checkedOvalPath stroke];
//// Bezier Drawing
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(CGRectGetMinX(group) + 0.27083 * CGRectGetWidth(group), CGRectGetMinY(group) + 0.54167 * CGRectGetHeight(group))];
[bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(group) + 0.41667 * CGRectGetWidth(group), CGRectGetMinY(group) + 0.68750 * CGRectGetHeight(group))];
[bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(group) + 0.75000 * CGRectGetWidth(group), CGRectGetMinY(group) + 0.35417 * CGRectGetHeight(group))];
bezierPath.lineCapStyle = kCGLineCapSquare;
[[UIColor whiteColor] setStroke];
bezierPath.lineWidth = 1.3;
[bezierPath stroke];
}
}
- (void) drawRectGrayedOut: (CGRect) rect
{
//// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();
//// Color Declarations
UIColor* grayTranslucent = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 0.6];
//// Shadow Declarations
UIColor* shadow2 = [UIColor blackColor];
CGSize shadow2Offset = CGSizeMake(0.1, -0.1);
CGFloat shadow2BlurRadius = 2.5;
//// Frames
CGRect frame = self.bounds;
//// Subframes
CGRect group = CGRectMake(CGRectGetMinX(frame) + 3, CGRectGetMinY(frame) + 3, CGRectGetWidth(frame) - 6, CGRectGetHeight(frame) - 6);
//// Group
{
//// UncheckedOval Drawing
UIBezierPath* uncheckedOvalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(group) + floor(CGRectGetWidth(group) * 0.00000 + 0.5), CGRectGetMinY(group) + floor(CGRectGetHeight(group) * 0.00000 + 0.5), floor(CGRectGetWidth(group) * 1.00000 + 0.5) - floor(CGRectGetWidth(group) * 0.00000 + 0.5), floor(CGRectGetHeight(group) * 1.00000 + 0.5) - floor(CGRectGetHeight(group) * 0.00000 + 0.5))];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, shadow2Offset, shadow2BlurRadius, shadow2.CGColor);
[grayTranslucent setFill];
[uncheckedOvalPath fill];
CGContextRestoreGState(context);
[[UIColor whiteColor] setStroke];
uncheckedOvalPath.lineWidth = 1;
[uncheckedOvalPath stroke];
//// Bezier Drawing
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(CGRectGetMinX(group) + 0.27083 * CGRectGetWidth(group), CGRectGetMinY(group) + 0.54167 * CGRectGetHeight(group))];
[bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(group) + 0.41667 * CGRectGetWidth(group), CGRectGetMinY(group) + 0.68750 * CGRectGetHeight(group))];
[bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(group) + 0.75000 * CGRectGetWidth(group), CGRectGetMinY(group) + 0.35417 * CGRectGetHeight(group))];
bezierPath.lineCapStyle = kCGLineCapSquare;
[[UIColor whiteColor] setStroke];
bezierPath.lineWidth = 1.3;
[bezierPath stroke];
}
}
- (void) drawRectOpenCircle: (CGRect) rect
{
//// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();
//// Shadow Declarations
UIColor* shadow = [UIColor blackColor];
CGSize shadowOffset = CGSizeMake(0.1, -0.1);
CGFloat shadowBlurRadius = 0.5;
UIColor* shadow2 = [UIColor blackColor];
CGSize shadow2Offset = CGSizeMake(0.1, -0.1);
CGFloat shadow2BlurRadius = 2.5;
//// Frames
CGRect frame = self.bounds;
//// Subframes
CGRect group = CGRectMake(CGRectGetMinX(frame) + 3, CGRectGetMinY(frame) + 3, CGRectGetWidth(frame) - 6, CGRectGetHeight(frame) - 6);
//// Group
{
//// EmptyOval Drawing
UIBezierPath* emptyOvalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(group) + floor(CGRectGetWidth(group) * 0.00000 + 0.5), CGRectGetMinY(group) + floor(CGRectGetHeight(group) * 0.00000 + 0.5), floor(CGRectGetWidth(group) * 1.00000 + 0.5) - floor(CGRectGetWidth(group) * 0.00000 + 0.5), floor(CGRectGetHeight(group) * 1.00000 + 0.5) - floor(CGRectGetHeight(group) * 0.00000 + 0.5))];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, shadow2Offset, shadow2BlurRadius, shadow2.CGColor);
CGContextRestoreGState(context);
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow.CGColor);
[[UIColor whiteColor] setStroke];
emptyOvalPath.lineWidth = 1;
[emptyOvalPath stroke];
CGContextRestoreGState(context);
}
}
@end
Displaying checkmark on collectionview
UITapGestureRecognizer
tap
's sender
is the gesture. The checkmarkWasTapped
method definition is wrong. And you can get the checkmarView
using sender.view
. Try this.
func checkmarkWasTapped(_ sender: UIGestureRecognizer) {
let checkmarkView= sender.view as? SSCheckMark
let indexPath = IndexPath(row: checkmarkView.tag, section: 1)
if checkmarkView.checked == true {
checkmarkView.checked = false
} else {
checkmarkView.checked = true
}
collectionView.reloadItems(at: [indexPath])
}
UICollectionViewCell checkmark return nil
Your cell is loaded from storyboard. Thus, init(frame:)
is not called. You should initialize your checkmark in init(coder:)
as well.
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let contentBounds = contentView.bounds
checkmarkView = SSCheckMark(frame: CGRect(x: contentBounds.width - 40, y: 10, width: 35, height: 35))
checkmarkView.backgroundColor = UIColor.white
// adapt to changes in cell size
checkmarkView.autoresizingMask = [ .flexibleLeftMargin, .flexibleBottomMargin ]
contentView.addSubview(checkmarkView)
}
UI COLLECTION VIEW - how to set accessory type check mark / discloser on UICollectionView
No CollectionCell have not accessory type property.so you have to make checkmark custom way.
UICollectionCell
Get UICollectionViewCell from indexPath when UIBarButtonItem is tapped
There are a few steps. First, determine the selected indexPath, but don't assume there is a selection when the method is run....
// in your button method
NSArray *selection = [self.MessageCollectionView indexPathsForSelectedItems];
if (selection.count) {
NSIndexPath *indexPath = selection[0];
[self removeItemAtIndexPath:indexPath];
}
There are two more steps to remove items from a collection view: remove them from your datasource, and tell the view it has changed.
- (void)removeItemAtIndexPath:(NSIndexPath *)indexPath {
// if your arrays are mutable...
[self.Message_Heading removeObjectAtIndex:indexPath.row];
// OR, if the arrays are immutable
NSMutableArray *tempMsgHeading = [self.Message_Heading mutableCopy];
[tempMsgHeading removeObjectAtIndex:indexPath.row];
self.Message_Heading = tempMsgHeading;
// ...
Do one or the other above for each datasource array. The last step is to inform the collection view that the datasource has changed, and it must update itself. There are a few ways to do this. The simplest is:
// ...
[self.MessageCollectionView reloadData];
OR, a little more elegantly:
[self.MessageCollectionView deleteItemsAtIndexPaths:@[indexPath]];
} // end of removeItemAtIndexPath
UITableViewCell checkmark to be toggled on and off when tapped
Swift > 3.0
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
}
I solved by using two Swift functions: the didSelectRowAtIndexPath and the didDeselectRowAtIndexPath.
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .Checkmark
}
}
To make this work properly, add a line of code to your cellForRowAtIndexPath function to select a row when the table view is drawn on the screen, otherwise the didDeselectRowAtIndexPath will not be called the first time you select another row. Like so:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellData", forIndexPath: indexPath)
if (some condition to initially checkmark a row)
cell.accessoryType = .Checkmark
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.Bottom)
} else {
cell.accessoryType = .None
}
return cell
}
Related Topics
How to Generate a Barcode from a String in Swift
How to Mimic Keyboard Animation on iOS 7 to Add "Done" Button to Numeric Keyboard
How to Put the Uipagecontrol Element on Top of the Sliding Pages Within a Uipageviewcontroller
Set Uitableview's Height to the Height of Its Content with Auto Layout
Xcode - Symbol(S) Not Found for Architecture X86_64 (iOS Lib)
Uiview's Border Color in Interface Builder Doesn't Work
Rotate Uiview Around Its Center Keeping Its Size
How to Get the Frame of a View Inside Another View
Change Frame Programmatically with Auto Layout
Uitableviewrowaction Image for Title
The Document Main.Storyboard Requires Xcode 8.0 or Later
Layout Attributes Relative to the Layout Margin on iOS Versions Prior to 8.0
Apn (Apple Push Notification) Payload Size Limit
An Error Occurred Uploading to the Itunes Store
How to Add a Button with Click Event on Uitableviewcell in Swift
App Store Connect Message: Your Account Will Soon Need to Be Migrated to Federated Auth