UIBarButtonItemに枠を付ける(別解)

前回は、画像リソースを使って枠を表示したが、
今回は画像を生成して、それを使って枠を表示する。

    @IBOutlet weak var myNavigationItem: UINavigationItem! // 接続済み

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        /* 省略 */
        
        let toneInitButton = UIBarButtonItem( title: "Init Tone", style: .Plain, target: self, action: Selector("toneInitButtonTapped:") )
        myNavigationItem.setRightBarButtonItem( toneInitButton, animated: false )

        let toneLoadButton = UIBarButtonItem( title: "Load", style: .Plain, target: self, action: Selector("toneLoadButtonTapped:") )
        let toneSaveButton = UIBarButtonItem( title: "Save", style: .Plain, target: self, action: Selector("toneSaveButtonTapped:") )
        myNavigationItem.setLeftBarButtonItems( [ toneLoadButton, toneSaveButton ], animated: false )

        for btn in [ toneLoadButton, toneSaveButton, toneInitButton ] {
            let backgroundImage = getBorderedBackgroundImage( 3.0 )
            btn.setBackgroundImage( backgroundImage, forState: UIControlState.Normal, barMetrics: UIBarMetrics.Default )
            btn.setTitleTextAttributes( [
                NSFontAttributeName : UIFont(name: "Futura-CondensedMedium", size: 17) as! AnyObject
                ], forState: .Normal )
        }

        /* 省略 */
    }

    func getBorderedBackgroundImage(r: CGFloat) -> UIImage {
        let w = 1.0 + ( (0.0 < r) ? ceil(r) : 1.0 ) + 1.0
        let imageWidth = (w * 2.0) + 1.0
        let imageSize = CGSize( width: imageWidth, height: imageWidth )
        
        UIGraphicsBeginImageContextWithOptions( imageSize, false, 3.0 )
        let context = UIGraphicsGetCurrentContext()
        
        var rect = CGRect( origin: CGPointZero, size: imageSize )
        rect.inset( dx: +1.5, dy: +1.5 )

        let strokeColor = UIColor.whiteColor()
        CGContextSetStrokeColorSpace( context, CGColorGetColorSpace(strokeColor.CGColor) )
        CGContextSetStrokeColor( context, CGColorGetComponents(strokeColor.CGColor) )
        CGContextClearRect( context, CGRect(x: 0, y: 0, width: imageWidth, height: imageWidth) )

        if ( 0.0 < r ) {
            let path = CGPathCreateWithRoundedRect( rect, r, r, nil )
            CGContextAddPath( context, path )
            CGContextStrokePath( context )
        }
        else {
            CGContextStrokeRectWithWidth( context, rect, 1.0 )
        }
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return image.resizableImageWithCapInsets(
            UIEdgeInsets(top: w, left: w, bottom: w, right: w) ).imageWithRenderingMode( .AlwaysTemplate )
    }
}

UIGraphicsBeginImageContextを使って背景を生成すると、
枠が拡大されてしまうので画像リソースを使った方法を紹介したけど、
UIGraphicsBeginImageContextWithOptionsを使えば、
scaleを指定することができるので、拡大されずに済む。(*1)

あと、前回同様に、
setBackgroundImageを呼ぶと、
アピアランスで設定したフォント設定がクリアされちゃうので、
今回も仕方なく再設定している。

という訳で、角丸じゃない長方形の枠も表示できました。

めでたし、めでたし。

(*1) 2015/08/05時点のお話

Leave a Comment