33

我正在设计一个带有 UICollectionView 的 iOS 应用程序,我希望用户能够在此视图中选择多个项目。在这种情况下,Apple 似乎使用了一种标准的复选标记样式。例如,在下图中,您可以在共享表中选择多张照片时看到它。

根据文档,您负责更新单元格的 UI 以反映它们的选择状态。我知道在 UITableViewCell 上您可以设置附件类型属性以添加复选标记,但我似乎找不到任何与 UICollectionViewCell 等效的东西。

除了尝试从屏幕截图中撕下此图标之外,Apple 是否提供了一种在我的应用程序中使用此复选标记的方法?

在此处输入图像描述

4

4 回答 4

59

我最终使用PaintCode重新创建了复选标记。这是他们的样子:

定制的复选标记

它们是用矢量图形绘制的,因此无论您想要什么尺寸,它们都会看起来很棒。这些是 30x30。我还包括一个选项,当未选择项目时,使用灰色复选标记而不是空心圆圈。

要使用这些,请将以下类复制到您的项目中。然后,将 UIView 添加到您的故事板或 xib,并将其自定义类设置为 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
于 2013-10-12T09:48:05.363 回答
15

Swift 3 版本的 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()

}
}

要在您的代码中使用它,请使用上述内容创建一个名为 SSCheckMark.swift 的文件,并将其分配给您的视图。我在 CollectionViewCells 中使用它,为此我创建了一个自定义类(代码大大简化):

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)
    }
}

在我的 UIViewController 中,我有这个:

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
}
于 2017-02-23T21:48:27.063 回答
12

一种可能性是创建一个绘制同心圆的 UIView,然后从您选择的字体中创建一个复选标记字符。要查找复选标记字符,请转到 Xcode(或具有该菜单项的任何其他应用程序)中的 Edit > Special Characters,然后搜索“check”。当您选择其中一个搜索结果时,您会在右下角看到字体变体。

在此处输入图像描述

于 2013-09-24T09:26:28.493 回答
1

相同代码的C#版本

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
}
于 2018-04-13T12:10:31.987 回答