web-dev-qa-db-ja.com

UICollectionViewCellに標準のチェックマークを表示するにはどうすればよいですか?

UICollectionViewを使用してiOSアプリを設計しています。ユーザーがこのビュー内で複数のアイテムを選択できるようにしたいと考えています。チェックマークの標準スタイルがあるようですAppleはこのような状況で使用します。たとえば、下の画像では、共有シートで複数の写真を選択すると表示されます。

documentation によると、選択状態を反映するようにセルのUIを更新する必要があります。 UITableViewCellでアクセサリタイププロパティを設定してチェックマークを追加できることは知っていますが、UICollectionViewCellに相当するものを見つけることができないようです。

Appleが私のアプリでこのチェックマークを使用するために提供する方法に加えて、このアイコンをスクリーンショットから取り去る方法はありますか?

enter image description here

33
Chris Vasselli

PaintCode を使用してチェックマークを再作成しました。それらは次のようになります。

Custom-made checkmarks

ベクターグラフィックスで描かれているため、好きなサイズで見栄えがします。これらは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
56
Chris Vasselli

Chris VasellisのニースソリューションのSwift 3バージョン:

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
}
13
Skaarup

1つの可能性は、同心円を描くUIViewを作成してから、選択したフォントからチェックマーク文字を作成することです。チェックマーク文字を見つけるには、Xcode(またはそのメニュー項目を持つ他のアプリケーション)内の編集>特殊文字に移動し、「チェック」を検索します。検索結果の1つを選択すると、右下にフォントのバリエーションが表示されます。

enter image description here

10
bneely

同じコードの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
}
1
Alvaro Rivoir