2016-07-14 8 views
1

私のUIViewController私はUIViewという単一のサブクラスを持っています。その中で私はティックタックのトウボードを描きます。どういうわけか、私がUIBezierPath()を使って描画している仕切り(「#」形)は、ボードを均等に分割していません。 1/3-1/3-1/3の代わりに、縦の仕切りは、寸法のプリントアウトが意味をなさないにもかかわらず、45%-45%-10%に近くなります。私は何が欠けていますか?おかげで私のサブクラスでUIViewとしてティックタックトウボードを素早く描画する方法は?

import UIKit 

@IBDesignable class GameBoardView: UIView { 

    override func drawRect(rect: CGRect) { 

     // set up gameBoard dimensions everytime drawRect() is called 
     setUpGameBoardCells() 
     self.frame = CGRectMake(gameBoardPosX, gameBoardPosY, gameBoardLength, gameBoardLength) 
     print("gameBoard.frame: x=\(self.frame.origin.x), y=\(self.frame.origin.y), h=\(self.frame.height), w=\(self.frame.width)\n") 

     // draw dividers & cells 
     var divider = UIBezierPath(rect: CGRect(x: cellWidth, y: 0, width: dividerWidth, height: gameBoardLength)) 
     divider.lineWidth = 1 
     UIColor.orangeColor().setStroke() 
     divider.stroke() 

     divider = UIBezierPath(rect: CGRect(x: cellWidth * 2 + dividerWidth, y: 0, width: dividerWidth, height: gameBoardLength)) 
     divider.stroke() 
    } 
} 

そして、これは私が任意のサイズの画面を処理するために寸法を設定する方法です:奇妙である何

var screenSize = CGRect() 
let screenMargin: CGFloat = 20 // to the edge 

var gameBoardIsPortrait = Bool() 
var gameBoardLength = CGFloat() 
var gameBoardPosX = CGFloat() 
var gameBoardPosY = CGFloat() 

let cellsPerRow: Int = 3 
var cellWidth = CGFloat() 
let dividerWidthGuide: CGFloat = 0.02 // guideline % of gameBoardLength 
var dividerWidth = CGFloat() 

let debugPrint = true 

func setUpGameBoardCells() { 

    screenSize = UIScreen.mainScreen().bounds 

    // gameBoard is a square 
    gameBoardIsPortrait = (screenSize.height >= screenSize.width ? true : false) 
    gameBoardLength = min(screenSize.height, screenSize.width) - screenMargin * 2 
    gameBoardPosX = (screenSize.width - gameBoardLength)/2 
    gameBoardPosY = (screenSize.height - gameBoardLength)/2 

    // want cells & dividers on gameBoard to be whole numbers 
    dividerWidth = round(gameBoardLength * dividerWidthGuide) 
    let cellsTotalWidth: Int = Int(gameBoardLength) - Int(dividerWidth) * (cellsPerRow - 1) 
    let dividerWidthFudge: CGFloat = (cellsTotalWidth % cellsPerRow == 1 ? -1 : (cellsTotalWidth % cellsPerRow == 2 ? 1 : 0)) 
    dividerWidth += dividerWidthFudge 
    cellWidth = CGFloat((cellsTotalWidth - Int(dividerWidthFudge) * (cellsPerRow - 1))/cellsPerRow) 

    if debugPrint { 
     print("setUpCellDivision()->\nscreen: h=\(screenSize.height), w=\(screenSize.width)") 
     print("gameBoardIsPortrait=\(gameBoardIsPortrait), gameBoardLength=\(gameBoardLength), gameBoardPosX=\(gameBoardPosX), gameBoardPosY=\(gameBoardPosY)") 
     print("cellWidth=\(cellWidth), dividerWidth=\(dividerWidth)\n") 
    } 
} 

はXcodeで、それが右に見えるということです。

enter image description here

しかし、シミュレータではこのように:あなたの制約が正しく設定されていないかのように

enter image description here

答えて

1

問題がdrawRect内からframeの設定です。これは、ビューに対して自動レイアウト制約が定義されている場合は特に問題になります。

ビューのレイアウトとそのビューの描画は2つの異なるステップであるため、そのロジックを分離する必要があります。

個人的には、ビューに自動レイアウト制約を設定して、それが正方形で、中央に配置され、正しい間隔を持っていることを確認したいと思います。そして、ビューのレンダリングが簡略化されます。

@IBDesignable class GameBoardView: UIView { 

    override func drawRect(rect: CGRect) { 
     setUpGameBoardCells() 

     UIColor.orangeColor().setStroke() 

     var divider = UIBezierPath(rect: CGRect(x: cellWidth, y: 0, width: dividerWidth, height: bounds.size.height)) 
     divider.lineWidth = 1 
     divider.stroke() 

     divider = UIBezierPath(rect: CGRect(x: cellWidth * 2 + dividerWidth, y: 0, width: dividerWidth, height: bounds.size.height)) 
     divider.lineWidth = 1 
     divider.stroke() 
    } 

    let cellsPerRow = 3 
    let dividerWidthGuide: CGFloat = 0.02 // guideline % of gameBoardLength 

    var cellWidth: CGFloat! 
    var cellHeight: CGFloat! 
    var dividerWidth: CGFloat! 

    func setUpGameBoardCells() { 
     let gameBoardLength = min(bounds.size.height, bounds.size.width) 
     dividerWidth = round(gameBoardLength * dividerWidthGuide) 
     let cellsTotalWidth: Int = Int(gameBoardLength) - Int(dividerWidth) * (cellsPerRow - 1) 
     let dividerWidthFudge: CGFloat = (cellsTotalWidth % cellsPerRow == 1 ? -1 : (cellsTotalWidth % cellsPerRow == 2 ? 1 : 0)) 
     dividerWidth! += dividerWidthFudge 
     cellWidth = CGFloat((cellsTotalWidth - Int(dividerWidthFudge) * (cellsPerRow - 1))/cellsPerRow) 
    } 

} 

もたらすこと:明らかに

enter image description here

は、あまりにも、あなたの水平セパレータのために繰り返します。

+0

こんにちは、ロブ、あなたの応答に感謝します。私はdrawRect()のCGRectMake()を取り除くことで、分け前が適切な場所に現れることを確認します。もし私がまだプログラムのサイズを変更し、ボードを特定の場所に移動したいのであれば、どこにCGRectMake()コールを置くべきですか?私はviewWillAppear()に私のViewControllerで入れてみましたが、それは動作していないようです。ありがとう – rockhammer

+1

他のビューと同じように 'frame'を設定します。自動レイアウトを使用していて、ストーリーボードに追加した場合は、制約のアウトレットを追加するだけで、必要に応じて制約の 'constant'プロパティを調整できます。キーは、自動レイアウトを使用している場合、 'frame'を直接調整しないことです。制約を調整します。 – Rob

+0

制約!もちろん。ありがとう、ロブ、私はちょうどそれを働かせました。 – rockhammer

0

に思えます。制約をやり直して問題が解決するかどうか確認してください。

+0

私は故意に制約を加えませんでした。私はプログラム的にボードのサイズを変更して再配置しています。 – rockhammer

+0

ああ!その場合、screenSizeの前に自分自身を追加してみて謝罪します。 – Konsy

1

最も簡単な方法は、黄色のUIViewに(区切り線として)UIViewsを追加し、それらを適切に制約することです。あまりにも多くのコードを書く必要はありません。そのような場合にコードを避けることをお勧めします。

これを試すことができます。ビューのフレームを計算して線を描画します。フレームに応じて以下のサイズが変更されます。

func drawRect(frame frame: CGRect = CGRect(x: 52, y: 30, width: 90, height: 75)) { 

    //// Bezier Drawing 
    let bezierPath = UIBezierPath() 
    UIColor.blackColor().setStroke() 
    bezierPath.lineWidth = 1 
    bezierPath.stroke() 


    //// Rectangle Drawing 
    let rectanglePath = UIBezierPath(rect: CGRect(x: frame.minX + floor(frame.width * 0.32778) + 0.5, y: frame.minY + floor(frame.height * 0.06000) + 0.5, width: floor(frame.width * 0.35000) - floor(frame.width * 0.32778), height: floor(frame.height * 0.92667) - floor(frame.height * 0.06000))) 
    UIColor.blackColor().setStroke() 
    rectanglePath.lineWidth = 1 
    rectanglePath.stroke() 


    //// Rectangle 3 Drawing 
    let rectangle3Path = UIBezierPath(rect: CGRect(x: frame.minX + floor(frame.width * 0.68333) + 0.5, y: frame.minY + floor(frame.height * 0.06000) + 0.5, width: floor(frame.width * 0.70556) - floor(frame.width * 0.68333), height: floor(frame.height * 0.92667) - floor(frame.height * 0.06000))) 
    UIColor.blackColor().setStroke() 
    rectangle3Path.lineWidth = 1 
    rectangle3Path.stroke() 


    //// Rectangle 5 Drawing 
    let rectangle5Path = UIBezierPath(rect: CGRect(x: frame.minX + floor(frame.width * 0.07222) + 0.5, y: frame.minY + floor(frame.height * 0.63333) + 0.5, width: floor(frame.width * 0.92778) - floor(frame.width * 0.07222), height: floor(frame.height * 0.66000) - floor(frame.height * 0.63333))) 
    UIColor.blackColor().setStroke() 
    rectangle5Path.lineWidth = 1 
    rectangle5Path.stroke() 


    //// Rectangle 6 Drawing 
    let rectangle6Path = UIBezierPath(rect: CGRect(x: frame.minX + floor(frame.width * 0.07222) + 0.5, y: frame.minY + floor(frame.height * 0.31333) + 0.5, width: floor(frame.width * 0.92778) - floor(frame.width * 0.07222), height: floor(frame.height * 0.34000) - floor(frame.height * 0.31333))) 
    UIColor.blackColor().setStroke() 
    rectangle6Path.lineWidth = 1 
    rectangle6Path.stroke() 
} 

enter image description here

関連する問題