投稿日:

【Swift】UIbezierPathでiOS9システムキーボードのアイコンを描画する




カスタムキーボードを作っていると、iOSシステムキーボードのようなオフィシャルなキーアイコンを描画したくなります。
しかし、drawRect()内で一から描くのは大変だし、かといってドローイングソフトで描いてUIImageをセットしていては、extensionアプリではメモリ的にきついし、アイコンの数が多くなるほどコードも複雑化していきます。

保守性やキーサイズへの応変、手軽に色をカスタマイズできるといった利便性などを考慮してもやはりdrawRectで描くに限ることを痛感しました。

ありがたいことに、GitHubにtasty-imitation-keyboardというアイコンをUIBezierPathで描いたものがあったわけですが、アイコンのクオリティ的にアレだったので僕が見よう見まねでシステムキーボードにさらに近づけたのをここにアップしておきます。










プロジェクトに組み込む準備


まずGitHubからtasty-imitation-keyboardをダウンロードし、「Shapes.swift」ファイルのみをプロジェクトへ追加。

Shapesクラスの
・getFactors(fromSize: CGSize, toRect: CGRect)
・centerShape(fromSize: CGSize, toRect: CGRect)
・endCenter()

の3つのメソッドを利用します。

描画の流れとしては

1. スケーリングに必要なFactorなどを定義
2. centerShape()でアイコンを中央に配置する
3. 各アイコンを描く
4. endCenter()で終了

これらを各UIButtonクラスのdrawRect()メソッドにオーバーライドします。

ここでご紹介するアイコンは主にiPadの分割キーボードを基準にしています。
また、自分のプロジェクトのコードを記事用に修正したものを貼っただけのもので、下記のコードのままの動作確認は行っていません。

載せているアイコンはデリート、グローブ、シフト、キーボードを閉じるの4種類です。



デリートアイコンを描く


左がシステムキーボードのアイコンで、
右が真似て描いたアイコンです。

Delete iOS Xcode Swift アイコン 描画 icon draw


Buttonのサイズに合わせてbaseIconSizeやscaleRateなどを適宜調節する必要があります。



override func drawRect(rect: CGRect) {

let baseIconSize = CGSizeMake(37, 32) // アイコンのベースとなるサイズ
let factors = getFactors(baseIconSize, toRect: bounds)
let scaleRate: CGFloat = 1.6  // Buttonのサイズに合わせてスケールさせる

let xScalingFactor = factors.xScalingFactor * scaleRate // x軸のスケール
let yScalingFactor = factors.yScalingFactor * scaleRate // y軸のスケール
let lineWidthScalingFactor = factors.lineWidthScalingFactor * 2.0 // lineWidthにそのまま放り込む
        
// アイコンをButtonの中心に描画させる
        centerShape(CGSizeMake(baseIconSize.width * xScalingFactor, baseIconSize.height * yScalingFactor), toRect: bounds)

// 別メソッドでアイコンの外枠とばつ印を描く
drawBackwardIconFrame(xScalingFactor, yScalingFactor: yScalingFactor, lineWidthScalingFactor: lineWidthScalingFactor)

            drawBackwardCross(xScalingFactor, yScalingFactor: yScalingFactor, lineWidthScalingFactor: lineWidthScalingFactor)
}

// 外枠の描画
func drawBackwardIconFrame(xScalingFactor: CGFloat, yScalingFactor: CGFloat, lineWidthScalingFactor: CGFloat) {
        let sharpX: CGFloat = 0 // 先端のx
        let sharpY: CGFloat = 16 // 先端のy
        let mostRightX: CGFloat = 36  // アイコン右マージン
        let mostLeftX: CGFloat = 13 // アイコン左マージン
        let mostBottomY: CGFloat = 29.5 // アイコンボトムマージン
        let mostTopY: CGFloat = 2.5  // アイコントップマージン
        let rightCurveEndPointY: CGFloat = 5  // 右側カーブの(先端から見た)終着点
        let rightCurveBeforePointX: CGFloat = mostRightX - 6 // 右側カーブの(先端から見た)手前の点
        
        //// デリートキーの枠
        let frameBezierPath = UIBezierPath()
        frameBezierPath.moveToPoint(CGPointMake((mostLeftX + 3) * xScalingFactor, mostBottomY * yScalingFactor)) // 左下の角
        
        frameBezierPath.addLineToPoint(CGPointMake(rightCurveBeforePointX * xScalingFactor, mostBottomY * yScalingFactor)) // 右下カーブ手前
        
        frameBezierPath.addCurveToPoint(CGPointMake(mostRightX * xScalingFactor, (mostBottomY - rightCurveEndPointY) * yScalingFactor), controlPoint1: CGPointMake(rightCurveBeforePointX * xScalingFactor, mostBottomY * yScalingFactor), controlPoint2: CGPointMake(mostRightX * xScalingFactor, mostBottomY * yScalingFactor)) // 右下カーブ後の点へ向かって曲線
        
        frameBezierPath.addLineToPoint(CGPointMake(mostRightX * xScalingFactor, (mostTopY + rightCurveEndPointY) * yScalingFactor)) // 右の縦線
        
        frameBezierPath.addCurveToPoint(CGPointMake(rightCurveBeforePointX * xScalingFactor, mostTopY * yScalingFactor), controlPoint1: CGPointMake(mostRightX * xScalingFactor, (mostTopY + rightCurveEndPointY) * yScalingFactor), controlPoint2: CGPointMake(mostRightX * xScalingFactor, mostTopY * yScalingFactor)) // 右上カーブ後の点へ向かって曲線
        
        frameBezierPath.addLineToPoint(CGPointMake((mostLeftX + 3) * xScalingFactor, mostTopY * yScalingFactor)) // トップの横線
        // とんがりへ向かう手前のカーブ
        frameBezierPath.addCurveToPoint(CGPointMake((mostLeftX - 2) * xScalingFactor, (mostTopY + 2) * yScalingFactor), controlPoint1: CGPointMake((mostLeftX + 3) * xScalingFactor, mostTopY * yScalingFactor), controlPoint2: CGPointMake(mostLeftX * xScalingFactor, mostTopY * yScalingFactor))
        
        frameBezierPath.addLineToPoint(CGPointMake(sharpX * xScalingFactor, (sharpY - 0.5) * yScalingFactor)) // 左端のとんがり上
        frameBezierPath.addLineToPoint(CGPointMake(sharpX * xScalingFactor, (sharpY + 0.5) * yScalingFactor)) // 左端のとんがり下
        
        frameBezierPath.addLineToPoint(CGPointMake((mostLeftX - 2) * xScalingFactor, (mostBottomY - 2) * yScalingFactor)) // 左下のカーブの手前までの直線
        frameBezierPath.addCurveToPoint(CGPointMake((mostLeftX + 3) * xScalingFactor, mostBottomY * yScalingFactor), controlPoint1: CGPointMake((mostLeftX - 2) * xScalingFactor, (mostBottomY - 2) * yScalingFactor), controlPoint2: CGPointMake(mostLeftX * xScalingFactor, mostBottomY * yScalingFactor)) // 左下のカーブ
        
        frameBezierPath.closePath()
        standardKeyTextColor().setStroke()
        frameBezierPath.lineWidth = 1.4 * lineWidthScalingFactor
        frameBezierPath.stroke()
    }

// ばつ印の描画
func drawBackwardCross(xScalingFactor: CGFloat, yScalingFactor: CGFloat, lineWidthScalingFactor: CGFloat) {
        let leftX: CGFloat = 17
        let rightX: CGFloat = leftX + 10
        let topY: CGFloat = 11
        let bottomY: CGFloat = topY + 10
        
        //// 右肩下がりのバツ線
        let downFromLeftToRightBezierPath = UIBezierPath()
        downFromLeftToRightBezierPath.moveToPoint(CGPointMake(leftX * xScalingFactor, topY * yScalingFactor))
        downFromLeftToRightBezierPath.addLineToPoint(CGPointMake(rightX * xScalingFactor, bottomY * yScalingFactor))
        downFromLeftToRightBezierPath.lineCapStyle = CGLineCap.Round
        standardKeyTextColor().setStroke()
        downFromLeftToRightBezierPath.lineWidth = 1.5 * lineWidthScalingFactor
        downFromLeftToRightBezierPath.stroke()
        
        //// 右肩上がりのバツ線
        let upFromLeftToRightBezierPath = UIBezierPath()
        upFromLeftToRightBezierPath.moveToPoint(CGPointMake(leftX * xScalingFactor, bottomY * yScalingFactor))
        upFromLeftToRightBezierPath.addLineToPoint(CGPointMake(rightX * xScalingFactor, topY * yScalingFactor))
        upFromLeftToRightBezierPath.lineCapStyle = CGLineCap.Round
        standardKeyTextColor().setStroke()
        upFromLeftToRightBezierPath.lineWidth = 1.5 * lineWidthScalingFactor
        upFromLeftToRightBezierPath.stroke()
    }



グローブアイコンを描画する


iOS Xcode Swift アイコン 描画 icon draw カスタムキーボード Globe 地球儀


// x,yFactorをかけたCGPointを渡す。
    private func scaledPoint(x: CGFloat, y: CGFloat) -> CGPoint {
        return CGPointMake(x * xScalingFactor, y * yScalingFactor)
    }

// xScalingFactorをかけた値を渡す。
    private func xScaledValue(value: CGFloat) -> CGFloat {
        return value * xScalingFactor
    }
    // yScalingFactorをかけた値を渡す。
    private func yScaledValue(value: CGFloat) -> CGFloat {
        return value * yScalingFactor
    }

let globeSizeH: CGFloat = 58
let globeSizeW: CGFloat = 56
let globeCenterY: CGFloat = 58 / 2.0
let globeCenterX: CGFloat = 56 / 2.0

var xScalingFactor = CGFloat()
var yScalingFactor = CGFloat()
var lineWidthScalingFactor = CGFloat()

override func drawRect(rect: CGRect) {
let scaleRate: CGFloat = 1.0
let factors = getFactors(CGSizeMake(globeSizeH, globeSizeW), toRect: bounds)
xScalingFactor = factors.xScalingFactor * scaleRate
yScalingFactor = factors.yScalingFactor * scaleRate
lineWidthScalingFactor = factors.lineWidthScalingFactor * 1.4

centerShape(CGSizeMake(xScaledValue(globeSizeW), yScaledValue(globeSizeH)), toRect: bounds)

drawGlobeIcon() // 地球儀アイコンを描く

endCenter()
}


// 地球儀アイコンを描く。2016/03/10
func drawGlobeIcon() {
	let color = UIColor.blackColor()        

        //// 円の描画
        let ovalPath = UIBezierPath(ovalInRect: CGRectMake(xScaledValue(0), yScaledValue(0), xScaledValue(globeSizeW), yScaledValue(globeSizeH)))
        color.setStroke()
        ovalPath.lineWidth = lineWidthScalingFactor
        ovalPath.stroke()
        
        
        //// 中央の縦線
        let centralVerticalPath = UIBezierPath()
        centralVerticalPath.moveToPoint(scaledPoint(globeCenterX, y: 0))
        centralVerticalPath.addLineToPoint(scaledPoint(globeCenterX, y: globeSizeH))
        color.setStroke()
        centralVerticalPath.lineWidth = lineWidthScalingFactor * 1.2
        centralVerticalPath.stroke()
        
        
        //// 中央の横線
        let centralHolizontalPath = UIBezierPath()
        centralHolizontalPath.moveToPoint(scaledPoint(0.5, y: globeCenterY))
        centralHolizontalPath.addLineToPoint(scaledPoint(globeSizeW - 0.5, y: globeCenterY))
        color.setStroke()
        centralHolizontalPath.lineWidth = lineWidthScalingFactor * 1.2
        centralHolizontalPath.stroke()
        
        
        //// 右側のたて曲線
        let rightVerticalCurvePath = UIBezierPath()
        let xPointR = (globeCenterX + 1.0)
        let yPoint: CGFloat = 0.42
        let rightSideHalfPoint = globeCenterX + globeCenterX / 2
        // 上の頂点から下へ向かって描く
        rightVerticalCurvePath.moveToPoint(scaledPoint(xPointR, y: 0))
        rightVerticalCurvePath.addCurveToPoint( // 上半分のカーブ
            scaledPoint(rightSideHalfPoint, y: globeCenterY + 2), 
            controlPoint1: scaledPoint(xPointR, y: yPoint), 
            controlPoint2: scaledPoint(rightSideHalfPoint, y: yPoint))
        
        rightVerticalCurvePath.addCurveToPoint( // 下半分のカーブ
            scaledPoint(xPointR, y: globeSizeH - yPoint), 
            controlPoint1: scaledPoint(rightSideHalfPoint, y: globeCenterY - 2), 
            controlPoint2: scaledPoint(rightSideHalfPoint, y: globeSizeH))
        
        rightVerticalCurvePath.lineCapStyle = .Round;
        color.setStroke()
        rightVerticalCurvePath.lineWidth = lineWidthScalingFactor
        rightVerticalCurvePath.stroke()
        
        
        //// 左側のたて曲線
        let leftVerticalCurvePath = UIBezierPath()
        let xPointL = (globeCenterX - 1.0)
        let leftSideHalfPoint = globeCenterX / 2
        // 上の頂点から下へ向かって描く
        leftVerticalCurvePath.moveToPoint(scaledPoint(xPointL, y: 0))
        leftVerticalCurvePath.addCurveToPoint( // 上半分のカーブ
            scaledPoint(leftSideHalfPoint, y: globeCenterY + 2), 
            controlPoint1: scaledPoint(xPointL, y: yPoint), 
            controlPoint2: scaledPoint(leftSideHalfPoint, y: yPoint))
        
        leftVerticalCurvePath.addCurveToPoint( // 下半分のカーブ
            scaledPoint(xPointL, y: globeSizeH - yPoint), 
            controlPoint1: scaledPoint(leftSideHalfPoint, y: globeCenterY - 2), 
            controlPoint2: scaledPoint(leftSideHalfPoint, y: globeSizeH))
        
        leftVerticalCurvePath.lineCapStyle = .Round;
        color.setStroke()
        leftVerticalCurvePath.lineWidth = lineWidthScalingFactor
        leftVerticalCurvePath.stroke()
        
        
        //// 上側のよこ曲線
        let basePointX: CGFloat = 8
        let basePointY: CGFloat = 10
        let topHorizontalCurvePath = UIBezierPath()
        topHorizontalCurvePath.moveToPoint(scaledPoint(basePointX, y: basePointY))
        topHorizontalCurvePath.addCurveToPoint(
            scaledPoint(globeSizeW - basePointX, y: basePointY), 
            controlPoint1: scaledPoint(basePointX, y: basePointY), 
            controlPoint2: scaledPoint(globeCenterX - 1, y: globeCenterY + 1))
        
        topHorizontalCurvePath.lineCapStyle = .Round
        color.setStroke()
        topHorizontalCurvePath.lineWidth = lineWidthScalingFactor
        topHorizontalCurvePath.stroke()
        
        
        //// 下側のよこ曲線
        let bottomBaseY: CGFloat = globeSizeH - basePointY
        let bottomHorizontalCurvePath = UIBezierPath()
        bottomHorizontalCurvePath.moveToPoint(scaledPoint(basePointX, y: bottomBaseY))
        bottomHorizontalCurvePath.addCurveToPoint(
            scaledPoint(globeSizeW - basePointX, y: bottomBaseY), 
            controlPoint1: scaledPoint(basePointX, y: bottomBaseY), 
            controlPoint2: scaledPoint(globeCenterX - 1, y: globeCenterY + 1))
        
        bottomHorizontalCurvePath.lineCapStyle = .Round
        color.setStroke()
        bottomHorizontalCurvePath.lineWidth = lineWidthScalingFactor
        bottomHorizontalCurvePath.stroke()
}



シフトアイコンを描く


上から通常アイコン、ハイライトアイコン、Capsアイコンです。

iOS Xcode Swift アイコン 描画 icon draw カスタムキーボード
iOS Xcode Swift アイコン 描画 icon draw カスタムキーボード Shift
iOS Xcode Swift アイコン 描画 icon draw カスタムキーボード caps

// MARK: アイコン描画
var xScalingFactor: CGFloat = 0
var yScalingFactor: CGFloat = 0
var lineWidthScalingFactor: CGFloat = 0
    
func initFactorsGetCenterShapeSize(bounds: CGRect) -> CGSize {
        var iconHeight = maxY
        if isCapsState() { iconHeight = capsMaxY }

        let factors = getFactors(CGSizeMake(maxX, iconHeight), toRect: bounds)
        let scaleRate: CGFloat = 1.0
        xScalingFactor = factors.xScalingFactor * scaleRate
        yScalingFactor = factors.yScalingFactor * scaleRate
        lineWidthScalingFactor = factors.lineWidthScalingFactor

	return CGSizeMake(maxX * xScalingFactor, iconHeight * yScalingFactor)
}
    
// x,yFactorをかけたCGPointを渡す。
    private func scaledPoint(x: CGFloat, y: CGFloat) -> CGPoint {
        return CGPointMake(x * xScalingFactor, y * yScalingFactor)
    }

override func drawRect(rect: CGRect) {
        
        centerShape(initFactorsGetCenterShapeSize(bounds), toRect: bounds)
        
        let color = getTitleColor()
        if ハイライト or Caps {
            
            model.drawHighlightedArrow(color: color)

        }else {
            // 通常モード
            model.drawNormalArrow(color: color)
        }
        
        endCenter()
    }

func drawNormalArrow(color clr: UIColor) {
        
        //// Bezier Drawing
        let bezierPath = UIBezierPath()
        bezierPath.moveToPoint(scaledPoint(bodyRightX, y: middleY)) // 矢印の右内側かど
        let beforeRightSharpPoint = scaledPoint(maxX - 3, y: middleY)
        bezierPath.addLineToPoint(beforeRightSharpPoint) // 矢印の右端角の手前
        // 矢印の右端かどのCurve
        bezierPath.addCurveToPoint(scaledPoint(maxX - 2, y: middleY - 3),
            controlPoint1: beforeRightSharpPoint, 
            controlPoint2: scaledPoint(maxX, y: middleY))
        
        bezierPath.addLineToPoint(scaledPoint(maxX / 2, y: 0)) // 頂点
        let beforeLeftSharpPoint = scaledPoint(2, y: middleY - 3)
        bezierPath.addLineToPoint(beforeLeftSharpPoint) // 矢印の左端角の手前
        // 矢印の左端かどのCurve
        bezierPath.addCurveToPoint(scaledPoint(4, y: middleY),
            controlPoint1: beforeLeftSharpPoint, 
            controlPoint2: scaledPoint(0, y: middleY))
        
        bezierPath.addLineToPoint(scaledPoint(bodyLeftX, y: middleY)) // 矢印の左内側かど
        bezierPath.addLineToPoint(scaledPoint(bodyLeftX, y: maxY - 3)) // ボディ左Curveの手前
        // ボディ左Curve
        bezierPath.addCurveToPoint(scaledPoint(bodyLeftX + 3, y: maxY), 
            controlPoint1: scaledPoint(bodyLeftX, y: maxY - 3), 
            controlPoint2: scaledPoint(bodyLeftX, y: maxY))
        
        bezierPath.addLineToPoint(scaledPoint(bodyRightX - 3, y: maxY)) // ボディの底辺
        // ボディ右Curve
        bezierPath.addCurveToPoint(scaledPoint(bodyRightX, y: maxY - 3), 
            controlPoint1: scaledPoint(bodyRightX - 3, y: maxY), 
            controlPoint2: scaledPoint(bodyRightX, y: maxY))
        
        bezierPath.addLineToPoint(scaledPoint(bodyRightX, y: middleY)) // ボディの右たて線
        
        bezierPath.closePath()
        bezierPath.lineWidth = lineWidthScalingFactor * 2.5
        clr.setStroke()
        bezierPath.stroke()
    }

func drawHighlightedArrow(color clr: UIColor) {
        
        //// Bezier Drawing
        let bezierPath = UIBezierPath()
        bezierPath.moveToPoint(scaledPoint(bodyRightX, y: middleY)) // 矢印の右内側かど
        let beforeRightSharpPoint = scaledPoint(maxX - 3, y: middleY)
        bezierPath.addLineToPoint(beforeRightSharpPoint) // 矢印の右端角の手前
        // 矢印の右端かどのCurve
        bezierPath.addCurveToPoint(scaledPoint(maxX - 2, y: middleY - 3),
            controlPoint1: beforeRightSharpPoint, 
            controlPoint2: scaledPoint(maxX, y: middleY))
        
        bezierPath.addLineToPoint(scaledPoint(maxX / 2, y: 0)) // 頂点
        let beforeLeftSharpPoint = scaledPoint(2, y: middleY - 3)
        bezierPath.addLineToPoint(beforeLeftSharpPoint) // 矢印の左端角の手前
        // 矢印の左端かどのCurve
        bezierPath.addCurveToPoint(scaledPoint(4, y: middleY),
            controlPoint1: beforeLeftSharpPoint, 
            controlPoint2: scaledPoint(0, y: middleY))
        
        bezierPath.addLineToPoint(scaledPoint(bodyLeftX, y: middleY)) // 矢印の左内側かど
        bezierPath.addLineToPoint(scaledPoint(bodyLeftX, y: maxY - 3)) // ボディ左Curveの手前
        // ボディ左Curve
        bezierPath.addCurveToPoint(scaledPoint(bodyLeftX + 3, y: maxY), 
            controlPoint1: scaledPoint(bodyLeftX, y: maxY - 3), 
            controlPoint2: scaledPoint(bodyLeftX, y: maxY))
        
        bezierPath.addLineToPoint(scaledPoint(bodyRightX - 3, y: maxY)) // ボディの底辺
        // ボディ右Curve
        bezierPath.addCurveToPoint(scaledPoint(bodyRightX, y: maxY - 3), 
            controlPoint1: scaledPoint(bodyRightX - 3, y: maxY), 
            controlPoint2: scaledPoint(bodyRightX, y: maxY))
        
        bezierPath.addLineToPoint(scaledPoint(bodyRightX, y: middleY)) // ボディの右たて線
        
        bezierPath.closePath()
        clr.setFill()
        bezierPath.fill()
        
        if isCapsState() { // Capsのみ長方形も描く
            let rectanglePath = UIBezierPath(roundedRect: CGRectMake(10 * xScalingFactor, (capsMaxY - 2) * yScalingFactor, 18 * xScalingFactor, capsRectangleHeight * yScalingFactor), cornerRadius: capsRectangleHeight / 2)
            clr.setFill()
            rectanglePath.fill()
        }
    }




キーボードを閉じるアイコンを描く


最後はキーボードを閉じるときに使うキーボードアイコンですが、
僕が描いたものはiOS8のアイコンを真似たものなのでiOS9のそれとは異なることをご了承ください。

iOS Xcode Swift アイコン 描画 icon draw カスタムキーボード Close 閉じる



var xScalingFactor = CGFloat()
var yScalingFactor = CGFloat()
    
override func drawRect(rect: CGRect) {

        let baseIconSize = CGSizeMake(44, 34)
        let factors = getFactors(baseIconSize, toRect: bounds)
        var scaleRate: CGFloat = 1.6
       
        xScalingFactor = factors.xScalingFactor * scaleRate
        yScalingFactor = factors.yScalingFactor * scaleRate
        let lineWidthScalingFactor = factors.lineWidthScalingFactor * 1.5
        
        centerShape(CGSizeMake(baseIconSize.width * xScalingFactor, baseIconSize.height * yScalingFactor), toRect: bounds)
        
        // キーボードアイコンの枠を描画。
        drawKeyboardFrame(lineWidthScalingFactor, color: getTitleColor())
        // キーボードアイコンのキーを描画。
        drawKeys(lineWidthScalingFactor, color: getTitleColor())
        // キーボード下の矢印を描画。
        drawDownArrow(lineWidthScalingFactor, color: getTitleColor())
        
        endCenter()
}

// 描画に必要な定数
let mostLeftX: CGFloat = 0
let mostRightX: CGFloat = 44
let mostTopY: CGFloat = 2
let frameBottomY: CGFloat = 20 //キーボードの枠のボトム

// キーボードアイコンの枠を描く。
func drawKeyboardFrame(lineWidthScalingFactor: CGFloat, color: UIColor) {
        
        let frameBezierPath = UIBezierPath()
        frameBezierPath.moveToPoint(scaledPoint(mostLeftX, y: mostTopY + 1))
        // 左の縦線
        frameBezierPath.addLineToPoint(scaledPoint(mostLeftX, y: frameBottomY - 1))
        
        // 左下のカーブ
        frameBezierPath.addCurveToPoint(scaledPoint(mostLeftX + 1, y: frameBottomY), 
            controlPoint1: scaledPoint(mostLeftX, y: frameBottomY), 
            controlPoint2: scaledPoint(mostLeftX, y: frameBottomY - 1))
        
        // 下の横線
        frameBezierPath.addLineToPoint(scaledPoint(mostRightX, y: frameBottomY))
        
        // 右下のカーブ
        frameBezierPath.addCurveToPoint(scaledPoint(mostRightX, y: frameBottomY - 1), 
            controlPoint1: scaledPoint(mostRightX, y: frameBottomY), 
            controlPoint2: scaledPoint(mostRightX - 1, y: frameBottomY))
        
        // 右の縦線
        frameBezierPath.addLineToPoint(scaledPoint(mostRightX, y: mostTopY))
        
        // 右上のカーブ
        frameBezierPath.addCurveToPoint(scaledPoint(mostRightX - 1, y: mostTopY), 
            controlPoint1: scaledPoint(mostRightX, y: mostTopY), 
            controlPoint2: scaledPoint(mostRightX, y: mostTopY + 1))
        
        // 上の横線
        frameBezierPath.addLineToPoint(scaledPoint(mostLeftX, y: mostTopY))
        
        // 左上のカーブ
        frameBezierPath.addCurveToPoint(scaledPoint(mostLeftX, y: mostTopY + 1), 
            controlPoint1: scaledPoint(mostLeftX, y: mostTopY), 
            controlPoint2: scaledPoint(mostLeftX + 1, y: mostTopY))
        
        frameBezierPath.lineCapStyle = CGLineCap.Round
        color.setStroke()
        frameBezierPath.lineWidth = lineWidthScalingFactor
        frameBezierPath.stroke()
}

let keyWidthPlusMargin: CGFloat = 4.5
let keySize: CGFloat = 2.5
    
// キーボードアイコンのキーを描く。
func drawKeys(lineWidthScalingFactor: CGFloat, color: UIColor) {
        
        let spaceKeyWidth: CGFloat = getSpaceKeyWidth(keySize: keySize)
        let keyTopMargin: CGFloat = 2.5
        
        for row in 0..<2 {// 1,2段目のキー
            for column in 0..<9 { 
                let topMargin = (mostTopY + keyTopMargin + (keySize + keyTopMargin) * CGFloat(row))
                let squareBezierPath = UIBezierPath(roundedRect: scaledRect(getKeyLeftMargin(index: column), y: topMargin, width: keySize, height: keySize), cornerRadius: 0)
                color.setFill()
                squareBezierPath.fill()
            }
        }
        
        for idx in 0..<9 { 
            let topMargin = (mostTopY + keyTopMargin + (keySize + keyTopMargin) * 2)
            if !(2 <= idx && idx <= 6) {  // 3段目のキー
                let squareBezierPath = UIBezierPath(roundedRect: scaledRect(getKeyLeftMargin(index: idx), y: topMargin, width: keySize, height: keySize), cornerRadius: 0)
                color.setFill()
                squareBezierPath.fill()
            }else if idx == 2 {   // 3段目のスペースキー
                let rectangleBezierPath = UIBezierPath(roundedRect: scaledRect(getKeyLeftMargin(index: idx), y: topMargin, width: spaceKeyWidth, height: keySize), cornerRadius: 0)
                color.setFill()
                rectangleBezierPath.fill()
            }
        }
}
    
// キーボード下の下矢印を描く。
func drawDownArrow(lineWidthScalingFactor: CGFloat, color: UIColor) {
        
        let spaceKeyWidth: CGFloat = getSpaceKeyWidth(keySize: keySize)
        let spaceKeyLeft = getKeyLeftMargin(index: 2)
        let arrowTopY = frameBottomY + 7
        let mostBottomY: CGFloat = arrowTopY + 6
        // 矢印の左側
        let arrowLeftBezierPath = UIBezierPath()
        arrowLeftBezierPath.moveToPoint(scaledPoint(spaceKeyLeft, y: arrowTopY))
        arrowLeftBezierPath.addLineToPoint(scaledPoint(spaceKeyLeft + spaceKeyWidth / 2, y: mostBottomY))
        arrowLeftBezierPath.lineCapStyle = CGLineCap.Round
        color.setStroke()
        arrowLeftBezierPath.lineWidth = lineWidthScalingFactor
        arrowLeftBezierPath.stroke()
        
        // 矢印の右側
        let spaceKeyRight = spaceKeyLeft + spaceKeyWidth
        let arrowRightBezierPath = UIBezierPath()
        arrowRightBezierPath.moveToPoint(scaledPoint(spaceKeyRight, y: arrowTopY))
        arrowRightBezierPath.addLineToPoint(scaledPoint(spaceKeyLeft + spaceKeyWidth / 2, y: mostBottomY))
        arrowRightBezierPath.lineCapStyle = CGLineCap.Round
        color.setStroke()
        arrowRightBezierPath.lineWidth = lineWidthScalingFactor
        arrowRightBezierPath.stroke()
}
    
// キーボードアイコンのスペースキーの幅を返す。
private func getSpaceKeyWidth(keySize size: CGFloat) -> CGFloat {
        let keyCount: CGFloat = 5
        let keyMargin = keyWidthPlusMargin - size
        return (size * keyCount) + (keyMargin * 4)
}

// 各キーの左マージンを計算して返す。
private func getKeyLeftMargin(index idx: Int) -> CGFloat {
        return mostLeftX + 2.5 + (CGFloat(idx) * 4.5)
}
    
// スケール処理をしたCGPointを返す。
private func scaledPoint(x: CGFloat, y: CGFloat) -> CGPoint {
        return CGPointMake(x * xScalingFactor, y * yScalingFactor)
}
// スケール処理をしたCGRectを返す。
private func scaledRect(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> CGRect {
        return CGRectMake(x * xScalingFactor, y * yScalingFactor, width * xScalingFactor, height * yScalingFactor)
}




以上です。
ではでは。


Sponsored Link





Comment