2016-10-15 8 views
1

UIViewを回転させながら中央に留めるようにキャリブレーションしようとしています。これは、my previous questionへの最良の答えによって特定される問題に続く。私はone answerに基づいて、viewDidLoadの代わりにviewWillAppearまたはviewDidLayoutSubviewsを使用することを提案して以来、コードを考案しています。UIViewが回転中に中央に留まらないのはなぜですか?

私はSwiftを初めて使うので、Swiftチュートリアルを再訪しなければならなかったので、how to make a subClass of UIViewというカスタムコントロールを実装してください。私のコードは、viewWillAppear,viewDidLayoutSubviewsまたはviewDidLoadのいずれかの関数を使用して円を描くことができます。

しかし、コードをレンダリングすると、画面が回転するときに円が常に中心にとどまるわけではありません。以下は、viewDidLoadまたはviewWillAppearviewDidLoad or viewWillAppearを使用して発生する連続回転です。アプリケーションを縦向きの画面で起動すると、左または右に関係なく最初の回転の直後に問題が表示されます。横向きで起動すると、少なくとも4回連続して回転しないと問題が発生する可能性があります。

以下は、viewDidLayoutSubviewsを使用して発生する連続的な回転です。回転すると、中心から外れた円の上に中央の円が重なることがあります。 viewDidLayoutSubviewsこれは数回回転した後に発生する可能性がありますが、問題を認識するためには少なくとも4回転を完了する必要があります。ここで

CircleViewのコードです - UIViewの

import UIKit 

class CircleView: UIView { 
    let radius   = CGFloat(200) 
    let x: CGFloat  = 0 
    let y: CGFloat  = 0 

// MARK: Initialization 

required init?(coder aDecoder: NSCoder) { 
    fatalError("init(coder:) has not been implemented") 
} 

    override init(frame: CGRect) { 
    super.init(frame: frame) 
    setup() 
} 

func setup() { 

    // Create a CAShapeLayer 
    let shapeLayer = CAShapeLayer() 

    // The Bezier path that we made needs to be converted 
    // to a CGPath before it can be used on a layer. 

    shapeLayer.path = createBezierPath().cgPath 

    // apply other properties related to the path 

    shapeLayer.strokeColor  = UIColor.red.cgColor 
    shapeLayer.fillColor  = UIColor.white.cgColor 
    shapeLayer.lineWidth  = 8.0 

    // add the new layer to our custom view 
    self.layer.addSublayer(shapeLayer) 
} 

func createBezierPath() -> UIBezierPath { 
    // create a new path 

    let path = UIBezierPath(arcCenter: CGPoint(x: x, y: y), 
       radius: radius, 
       startAngle: CGFloat(M_PI * -0.5), 
       endAngle:CGFloat(M_PI * 1.5), 
       clockwise: true) 

    path.fill() 
    path.stroke() 
    return path 
    } 
} 

、ここでのサブクラスを作るために私の試みは、ViewControllerを

import UIKit 

class ViewController: UIViewController { 
    var circle: CircleView? 
    var x: CGFloat? 
    var y: CGFloat? 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    let centre = centreCircle() 

    // create a new UIView and add it to the view controller 
    let circleView = CircleView() 
    circleView.frame = CGRect(x: centre.x, y: centre.y, width: 0, height: 0) 
    view.addSubview(circleView) 
    } 

    func centreCircle() -> CGPoint { 
    circle?.bounds = UIScreen.main.bounds 
    return CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY) 
    } 
} 

ためのコードであり、ここで返しUIScreen拡張のためのコードです画面の中心点

import UIKit 

extension UIScreen { 
    var centre: CGPoint { 
    return CGPoint(x: bounds.midX, y: bounds.midY) 
    } 
} 

回転の上に私はviewWillAppear

override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
    let centre = centreCircle() 

    // create a new UIView and add it to the view controller 
    let circleView = CircleView() 
    circleView.frame = CGRect(x: centre.x, y: centre.y, width: 0, height: 0) 
    view.addSubview(circleView) 
    } 

またはviewDidLayoutSubviews

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    let centre = centreCircle() 

    // create a new UIView and add it to the view controller 
    let circleView = CircleView() 
    circleView.frame = CGRect(x: centre.x, y: centre.y, width: 0, height: 0) 
    view.addSubview(circleView) 
    } 

viewDidLoad機能を置き換える誰が働いてから回転を停止させる可能性があります私のコードで問題を見ることができますか?

答えて

1

まず、viewdidloadとviewwillappearでビューのレイアウトが正しく行われておらず、明示的に値を持つフレームが定義されています。新しいプログラマとしては非常に不満です。ラベルのサイズを変更するときは特に気になります。したがって、あなたのビューとメインスクリーンのcentreXとcentreYを置くと、あなたが回転したときにビューがそのポイントに固執することになります。

autolayoutを学習してこれを修正してください。それは最初は吸うが、結局はあなたの人生を楽にするだろう。この拡張モジュールのメソッドを見てください。私は別のビューにビューを中央に配置したいときに使用します。

extension UIView { 


    func constrainAndCenter(in view: UIView, withRelativeHeight: CGFloat, withRelativeWidth: CGFloat) -> [NSLayoutConstraint] { 
     self.translatesAutoresizingMaskIntoConstraints = false 

     let x = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0) 
     let w = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: withRelativeWidth, constant: 0) 
     let h = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: withRelativeHeight, constant: 0) 
     let y = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0) 

     return ([x,w,h,y]) 
    } 
} 

// then in viewdidload or whereever 
let circleView = CircleView() 
let circleViewConstraints = circleView.constrainAndCenter(in: view,....) 
view.addSubview(circleView) 
NSLayoutConstraint.activate(circleViewConstraints) 

それは真中に固定されます。また、インターフェースビルダーで行うこともできます。

+0

circleViewを与えます。 constrainAndCenterは、circleView内に存在しないような引数を提供する方法です。 NSLayoutConstraintをチェックしてみてください。時間がかかることがあります。 – Greg

0

センターを右に計算するには、frame.boundsframe.centerに置き換える必要があります。

+0

私は間違っているかもしれませんが、CGPoint(x:UIScreen.main.bounds.midX、y:UIScreen.main.bounds.midY)の.midXと.midYの値は、中心点 – Greg

関連する問題