UICollectionViewを使用してiOSアプリを設計しています。ユーザーがこのビュー内で複数のアイテムを選択できるようにしたいと考えています。チェックマークの標準スタイルがあるようですAppleはこのような状況で使用します。たとえば、下の画像では、共有シートで複数の写真を選択すると表示されます。
documentation によると、選択状態を反映するようにセルのUIを更新する必要があります。 UITableViewCellでアクセサリタイププロパティを設定してチェックマークを追加できることは知っていますが、UICollectionViewCellに相当するものを見つけることができないようです。
Appleが私のアプリでこのチェックマークを使用するために提供する方法に加えて、このアイコンをスクリーンショットから取り去る方法はありますか?
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
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
}
1つの可能性は、同心円を描くUIViewを作成してから、選択したフォントからチェックマーク文字を作成することです。チェックマーク文字を見つけるには、Xcode(またはそのメニュー項目を持つ他のアプリケーション)内の編集>特殊文字に移動し、「チェック」を検索します。検索結果の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
}