Je conçois une application iOS avec UICollectionView, et j'aimerais que les utilisateurs puissent sélectionner plusieurs éléments dans cette vue. Il semble qu'il existe un style standard de coche Apple utilise dans ce type de situation. Par exemple, dans l'image ci-dessous, vous pouvez le voir lors de la sélection de plusieurs photos dans une feuille de partage.
Selon la documentation , vous êtes responsable de la mise à jour de l'interface utilisateur de vos cellules pour refléter leur état de sélection. Je sais que sur un UITableViewCell, vous pouvez définir la propriété accessoryType pour ajouter une coche, mais je n'arrive pas à trouver d'équivalent pour un UICollectionViewCell.
Existe-t-il un moyen Apple prévoit d'utiliser cette coche dans mon application, en plus d'essayer d'extraire cette icône d'une capture d'écran?
J'ai fini par recréer les coches en utilisant PaintCode . Voici à quoi ils ressemblent:
Ils sont dessinés avec des graphiques vectoriels, donc ils auront fière allure quelle que soit la taille que vous souhaitez. Ce sont 30x30. J'ai également inclus une option pour utiliser une coche grisée au lieu du cercle ouvert lorsqu'un élément n'est pas sélectionné.
Pour les utiliser, copiez la classe suivante dans votre projet. Ensuite, ajoutez une UIView à votre storyboard ou xib et définissez sa classe personnalisée sur 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
Version Swift 3 de la belle solution de Chris Vasellis:
import UIKit
enum SSCheckMarkStyle : UInt {
case OpenCircle
case GrayedOut
}
class SSCheckMark: UIView {
private var checkedBool: Bool = false
// choose whether you like open or grayed out non-selected items
private var checkMarkStyleReal: SSCheckMarkStyle=SSCheckMarkStyle.GrayedOut
var checked: Bool {
get {
return self.checkedBool
}
set(checked) {
self.checkedBool = checked
self.setNeedsDisplay()
}
}
var checkMarkStyle: SSCheckMarkStyle {
get {
return self.checkMarkStyleReal
}
set(checkMarkStyle) {
self.checkMarkStyleReal = checkMarkStyle
self.setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
if self.checked {
self.drawRectChecked(rect: rect)
} else {
if self.checkMarkStyle == SSCheckMarkStyle.OpenCircle {
self.drawRectOpenCircle(rect: rect)
} else if self.checkMarkStyle == SSCheckMarkStyle.GrayedOut {
self.drawRectGrayedOut(rect: rect)
}
}
}
func drawRectChecked(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
let checkmarkBlue2 = UIColor(red: 0.078, green: 0.435, blue: 0.875, alpha: 1)
let shadow2 = UIColor.black
let shadow2Offset = CGSize(width: 0.1, height: -0.1)
let shadow2BlurRadius = 2.5
let frame = self.bounds
let group = CGRect(x: frame.minX + 3, y: frame.minY + 3, width: frame.width - 6, height: frame.height - 6)
let checkedOvalPath = UIBezierPath(ovalIn: CGRect(x: group.minX + floor(group.width * 0.00000 + 0.5), y: group.minY + floor(group.height * 0.00000 + 0.5), width: floor(group.width * 1.00000 + 0.5) - floor(group.width * 0.00000 + 0.5), height: floor(group.height * 1.00000 + 0.5) - floor(group.height * 0.00000 + 0.5)))
context!.saveGState()
context!.setShadow(offset: shadow2Offset, blur: CGFloat(shadow2BlurRadius), color: shadow2.cgColor)
checkmarkBlue2.setFill()
checkedOvalPath.fill()
context!.restoreGState()
UIColor.white.setStroke()
checkedOvalPath.lineWidth = 1
checkedOvalPath.stroke()
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: group.minX + 0.27083 * group.width, y: group.minY + 0.54167 * group.height))
bezierPath.addLine(to: CGPoint(x: group.minX + 0.41667 * group.width, y: group.minY + 0.68750 * group.height))
bezierPath.addLine(to: CGPoint(x: group.minX + 0.75000 * group.width, y: group.minY + 0.35417 * group.height))
bezierPath.lineCapStyle = CGLineCap.square
UIColor.white.setStroke()
bezierPath.lineWidth = 1.3
bezierPath.stroke()
}
func drawRectGrayedOut(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
let grayTranslucent = UIColor(red: 1, green: 1, blue: 1, alpha: 0.6)
let shadow2 = UIColor.black
let shadow2Offset = CGSize(width: 0.1, height: -0.1)
let shadow2BlurRadius = 2.5
let frame = self.bounds
let group = CGRect(x: frame.minX + 3, y: frame.minY + 3, width: frame.width - 6, height: frame.height - 6)
let uncheckedOvalPath = UIBezierPath(ovalIn: CGRect(x: group.minX + floor(group.width * 0.00000 + 0.5), y: group.minY + floor(group.height * 0.00000 + 0.5), width: floor(group.width * 1.00000 + 0.5) - floor(group.width * 0.00000 + 0.5), height: floor(group.height * 1.00000 + 0.5) - floor(group.height * 0.00000 + 0.5)))
context!.saveGState()
context!.setShadow(offset: shadow2Offset, blur: CGFloat(shadow2BlurRadius), color: shadow2.cgColor)
grayTranslucent.setFill()
uncheckedOvalPath.fill()
context!.restoreGState()
UIColor.white.setStroke()
uncheckedOvalPath.lineWidth = 1
uncheckedOvalPath.stroke()
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: group.minX + 0.27083 * group.width, y: group.minY + 0.54167 * group.height))
bezierPath.addLine(to: CGPoint(x: group.minX + 0.41667 * group.width, y: group.minY + 0.68750 * group.height))
bezierPath.addLine(to: CGPoint(x: group.minX + 0.75000 * group.width, y: group.minY + 0.35417 * group.height))
bezierPath.lineCapStyle = CGLineCap.square
UIColor.white.setStroke()
bezierPath.lineWidth = 1.3
bezierPath.stroke()
}
func drawRectOpenCircle(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
let shadow = UIColor.black
let shadowOffset = CGSize(width: 0.1, height: -0.1)
let shadowBlurRadius = 0.5
let shadow2 = UIColor.black
let shadow2Offset = CGSize(width: 0.1, height: -0.1)
let shadow2BlurRadius = 2.5
let frame = self.bounds
let group = CGRect(x: frame.minX + 3, y: frame.minY + 3, width: frame.width - 6, height: frame.height - 6)
let emptyOvalPath = UIBezierPath(ovalIn: CGRect(x: group.minX + floor(group.width * 0.00000 + 0.5), y: group.minY + floor(group.height * 0.00000 + 0.5), width: floor(group.width * 1.00000 + 0.5) - floor(group.width * 0.00000 + 0.5), height: floor(group.height * 1.00000 + 0.5) - floor(group.height * 0.00000 + 0.5)))
context!.saveGState()
context!.setShadow(offset: shadow2Offset, blur: CGFloat(shadow2BlurRadius), color: shadow2.cgColor)
context!.restoreGState()
context!.saveGState()
context!.setShadow(offset: shadowOffset, blur: CGFloat(shadowBlurRadius), color: shadow.cgColor)
UIColor.white.setStroke()
emptyOvalPath.lineWidth = 1
emptyOvalPath.stroke()
context!.restoreGState()
}
}
Pour l'utiliser dans votre code, créez un fichier appelé SSCheckMark.Swift avec le contenu ci-dessus et affectez-le à votre vue. Je l'utilise dans CollectionViewCells, pour lequel j'ai créé une classe personnalisée (code fortement simplifié):
class myCollectionViewCell: UICollectionViewCell {
var checkmarkView: SSCheckMark!
override init(frame: CGRect) {
super.init(frame: frame)
checkmarkView = SSCheckMark(frame: CGRect(x: frame.width-40, y: 10, width: 35, height: 35))
checkmarkView.backgroundColor = UIColor.white
myView.addSubview(checkmarkView)
}
}
Et dans mon UIViewController, j'ai ceci:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:ProductCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath) as! myCollectionViewCell
cell.checkmarkView.checked = myBoolValue
return cell
}
Une possibilité consiste à créer une vue UIV qui dessine des cercles concentriques, puis un caractère de coche à partir de la police de votre choix. Pour trouver des caractères de coche, allez dans Édition> Caractères spéciaux dans Xcode (ou toute autre application avec cet élément de menu) et recherchez "vérifier". Lorsque vous sélectionnez l'un des résultats de la recherche, vous verrez des variations de police en bas à droite.
Version C # du même code
public class CheckMarkView : UIView
{
private bool _checked;
private CheckMarkStyle _checkMarkStyle;
public CheckMarkView()
{
Opaque = false;
}
public bool Checked
{
get
{
return _checked;
}
set
{
_checked = value;
SetNeedsDisplay();
}
}
public CheckMarkStyle CheckMarkStyle
{
get
{
return _checkMarkStyle;
}
set
{
_checkMarkStyle = value;
SetNeedsDisplay();
}
}
public override void Draw(CGRect rect)
{
if (Checked)
DrawRectChecked(rect);
else if (CheckMarkStyle == CheckMarkStyle.OpenCircle)
DrawRectOpenCircle(rect);
else if (CheckMarkStyle == CheckMarkStyle.GrayedOut)
DrawRectGrayedOut(rect);
}
private void DrawRectChecked(CGRect rect)
{
var context = UIGraphics.GetCurrentContext();
var checkmarkBlue2 = UIColor.FromRGBA(0.078f, 0.435f, 0.875f, 1f);
// Shadow Declarations
var shadow2 = UIColor.Brown;
var shadow2Offset = new CGSize(0.1, -0.1);
nfloat shadow2BlurRadius = 2.5f;
var frame = Bounds;
// Subframes
var group = new CGRect(frame.GetMinX() + 3, frame.GetMinY() + 3, frame.Width - 6, frame.Height - 6);
// CheckedOval Drawing
var checkedOvalPath = UIBezierPath.FromOval(new CGRect(group.GetMinX() + Math.Floor(group.Width * 0.00000 + 0.5), group.GetMinY() + Math.Floor(group.Height * 0.00000 + 0.5), Math.Floor(group.Width * 1.00000 + 0.5) - Math.Floor(group.Width * 0.00000 + 0.5), Math.Floor(group.Height * 1.00000 + 0.5) - Math.Floor(group.Height * 0.00000f + 0.5f)));
context.SaveState();
context.SetShadow(shadow2Offset, shadow2BlurRadius, shadow2.CGColor);
checkmarkBlue2.SetFill();
checkedOvalPath.Fill();
context.RestoreState();
UIColor.White.SetStroke();
checkedOvalPath.LineWidth = 1;
checkedOvalPath.Stroke();
// Bezier Drawing
var bezierPath = new UIBezierPath();
bezierPath.MoveTo(new CGPoint(group.GetMinX() + 0.27083f * group.Width, group.GetMinY() + 0.54167f * group.Height));
bezierPath.AddLineTo(new CGPoint(group.GetMinX() + 0.41667f * group.Width, group.GetMinY() + 0.68750f * group.Height));
bezierPath.AddLineTo(new CGPoint(group.GetMinX() + 0.75000f * group.Width, group.GetMinY() + 0.35417f * group.Height));
bezierPath.LineCapStyle = CGLineCap.Square;
UIColor.White.SetStroke();
bezierPath.LineWidth = 1.3f;
bezierPath.Stroke();
}
private void DrawRectGrayedOut(CGRect rect)
{
var context = UIGraphics.GetCurrentContext();
var grayTranslucent = UIColor.FromRGBA(1, 1, 1, 0.6f);
// Shadow Declarations
var shadow2 = UIColor.Black;
var shadow2Offset = new CGSize(0.1, -0.1);
nfloat shadow2BlurRadius = 2.5f;
var frame = Bounds;
// Subframes
var group = new CGRect(frame.GetMinX() + 3, frame.GetMinY() + 3, frame.Width - 6, frame.Height - 6);
// UncheckedOval Drawing
var uncheckedOvalPath = UIBezierPath.FromOval(new CGRect(group.GetMinX() + Math.Floor(group.Width * 0.00000 + 0.5), group.GetMinY() + Math.Floor(group.Height * 0.00000 + 0.5), Math.Floor(group.Width * 1.00000 + 0.5) - Math.Floor(group.Width * 0.00000 + 0.5), Math.Floor(group.Height * 1.00000 + 0.5) - Math.Floor(group.Height * 0.00000 + 0.5)));
context.SaveState();
context.SetShadow(shadow2Offset, shadow2BlurRadius, shadow2.CGColor);
grayTranslucent.SetFill();
uncheckedOvalPath.Fill();
context.RestoreState();
UIColor.White.SetStroke();
uncheckedOvalPath.LineWidth = 1f;
uncheckedOvalPath.Stroke();
// Bezier Drawing
var bezierPath = new UIBezierPath();
bezierPath.MoveTo(new CGPoint(group.GetMinX() + 0.27083 * group.Width, group.GetMinY() + 0.54167 * group.Height));
bezierPath.AddLineTo(new CGPoint(group.GetMinX() + 0.41667 * group.Width, group.GetMinY() + 0.68750 * group.Height));
bezierPath.AddLineTo(new CGPoint(group.GetMinX() + 0.75000 * group.Width, group.GetMinY() + 0.35417 * group.Height));
bezierPath.LineCapStyle = CGLineCap.Square;
UIColor.White.SetStroke();
bezierPath.LineWidth = 1.3f;
bezierPath.Stroke();
}
private void DrawRectOpenCircle(CGRect rect)
{
var context = UIGraphics.GetCurrentContext();
// Shadow Declarations
var shadow = UIColor.Black;
var shadowOffset = new CGSize(0.1, -0.1);
nfloat shadowBlurRadius = 0.5f;
var shadow2 = UIColor.Black;
var shadow2Offset = new CGSize(0.1, -0.1);
nfloat shadow2BlurRadius = 2.5f;
var frame = Bounds;
// Subframes
var group = new CGRect(frame.GetMinX() + 3, frame.GetMinY() + 3, frame.Width - 6, frame.Height - 6);
// EmptyOval Drawing
var emptyOvalPath = UIBezierPath.FromOval(new CGRect(group.GetMinX() + Math.Floor(group.Width * 0.00000 + 0.5), group.GetMinY() + Math.Floor(group.Height * 0.00000 + 0.5), Math.Floor(group.Width * 1.00000 + 0.5) - Math.Floor(group.Width * 0.00000 + 0.5), Math.Floor(group.Height * 1.00000 + 0.5) - Math.Floor(group.Height * 0.00000 + 0.5)));
context.SaveState();
context.SetShadow(shadow2Offset, shadow2BlurRadius, shadow2.CGColor);
context.RestoreState();
context.SaveState();
context.SetShadow(shadowOffset, shadowBlurRadius, shadow.CGColor);
UIColor.White.SetStroke();
emptyOvalPath.LineWidth = 1;
emptyOvalPath.Stroke();
context.RestoreState();
}
}
public enum CheckMarkStyle
{
OpenCircle,
GrayedOut
}