2017-02-02 26 views
2

私は自分の練習用のシンプルなシングルビューアプリケーションを作ろうとしていますが、問題に遭遇し、過去2〜3日間この問題を回避していません。私はこれらのスタイルのボタンのいずれかを押すか、スライダを調整したときに Swiftで描画されたCGContextを再描画しますか?

Screenshot of the current program

は基本的に、私はそれがスクリーン(赤点線)の下部にありますCGContextを再描画します。私はSTYLE 1ボタンを押した場合、それはdrawStyleOne(と呼ばれる関数)を呼び出すと、これら二つの異なる変化を適用する必要があります。

context?.setLineDash(phase: 0, lengths: [2,3]) 
context?.setStrokeColor(UIColor.green.cgColor) 

私の目標は、再描画の点線(小さなドット)であり、変更を緑のコンテキストの色(コンテキストはCGContextのインスタンスです)

私はすべてのオーバーライドfunc描画(_ rect:CGRect)に描画していますが、CGContextを必要な方法で再描画することはできません。

ここは、この状況を少し良く説明するためのコードです。

import UIKit 

class VectorView: UIView { 
private var context: CGContext? = nil 

override init(frame: CGRect) { 
    super.init(frame: frame) 
    //contentMode = .redraw //tried this, didn't work. 
} 

required init?(coder aDecoder: NSCoder) { 
    fatalError("init(coder:) has not been implemented") 
} 
override func draw(_ rect: CGRect) { 
    // lets us make calls 
    context = UIGraphicsGetCurrentContext()! 
    context?.move(to: CGPoint(x: 0.0, y: 10.0)) 
    context?.setLineDash(phase: 0, lengths: [2,3]) 
    context?.setLineJoin(CGLineJoin.bevel) 
    context?.setLineCap(CGLineCap.square) 

    context?.addLine(to: CGPoint(x: 50.0, y: 70.0)) 
    context?.addLine(to: CGPoint(x: 100.0, y: 20.0)) 

    context?.setLineWidth(1.0) 
    context?.setStrokeColor(UIColor.red.cgColor) 
    context?.drawPath(using: CGPathDrawingMode.stroke)   
} 

func drawStyleOne() { 

    context = UIGraphicsGetCurrentContext() 
    context?.move(to: CGPoint(x: 0.0, y: 10.0)) 
    context?.setLineDash(phase: 0, lengths: [2,3]) 
    context?.setLineJoin(CGLineJoin.bevel) 
    context?.setLineCap(CGLineCap.square) 

    context?.addLine(to: CGPoint(x: 50.0, y: 70.0)) 
    context?.addLine(to: CGPoint(x: 100.0, y: 20.0)) 

    context?.setStrokeColor(UIColor.green.cgColor) 

    context?.drawPath(using: CGPathDrawingMode.stroke) 
    self.setNeedsDisplay() 
    //contentMode = .redraw //Tried this and didn't work either.. 
    NSLog("drawStyleOne got called") 
} 

上記のクラスのdrawStyleOne関数は、AppDelegate内で呼び出されます。

import UIKit 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 
    let screenSize = UIScreen.main.bounds 

    private var _vectorView: VectorView? = nil 
    private var _buttonStylesView: ButtonStyleView? = nil 

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

     window = UIWindow() 
     window?.rootViewController = ViewController() 
     window?.rootViewController?.view.backgroundColor = UIColor.white 
     window?.makeKeyAndVisible() 

     _vectorView = VectorView() 
     _vectorView?.frame = CGRect(x: 0.0, y: 650, width: 414, height: 70) 
     _vectorView?.backgroundColor = UIColor.lightGray 
     window?.rootViewController?.view.addSubview(_vectorView!) 

     _buttonStylesView = ButtonStyleView() 
     _buttonStylesView?.frame = CGRect (x: screenSize.width/10, y: screenSize.height * 6/10, width: 414, height: 100) 
     _buttonStylesView?.backgroundColor = UIColor.clear 

     window?.rootViewController?.view.addSubview(_buttonStylesView!) 

     _buttonStylesView?.styleOne?.addTarget(self, action: #selector(styleButtonPressed), for: UIControlEvents.touchDown)  
     return true 
    } 

    func styleButtonPressed() { 
     NSLog("STYLE BUTTON PRESSED") 
     _vectorView?.drawStyleOne() 
    } 
} 

、しかし、それは関係なく、私がしようと何行を再描画しないだろう私もちょうど関数が呼び出さなっていることを確認するために、最後に(「drawStyleOneが呼ばれました」)のNSLogを入れて(そしてそれはありません)。

ご迷惑をおかけして申し訳ございません。

答えて

2

すべての図面内override func draw(_ rect: CGRect)(またはそこから呼び出される内部ルーチン)を実行する必要があります。したがって、あなたのdrawには、(あなたの行動によって)あなたのスタイルを描くためのフラグが必要です。 setNeedsDisplay()で再描画をトリガーしますが、これは描画コードからではなく、アクションから呼び出す必要があります。現在のfunc drawStyleOne()(実際には無効なcurrentContext)を描画しようとしてから、実際にdrawルーチンを実行するようにスケジュールするちょうど同じ「スタイル」を描画するsetNeedsDisplay()を呼び出します。

UIViewクラスは非常に多くのことを行うために舞台裏で働く - drawが不必要に呼び出されていないことを確認した場合、およびスケジュールことが必要であるときには、それは彼ら場合は、再描画され必要のあるビューの一部割り出し(それがあなたにrectを渡す理由です)、そしてとりわけdrawの現在のグラフィックスコンテキストを設定します。

このRay WenderlichチュートリアルまたはApple docsを参照してください。アップルのドキュメントが言うように:メソッドをし、その中 すべてあなたの描画を実行します。カスタムビューの場合

は、あなたがのdrawRectをオーバーライドする必要があります。

(私の強調)

だからあなたのコードは次のようになります。私はそれは本当にあなたの質問への答えではないのですが、知っているあなたは、あなたの問題で別の方法を探すことができ

class VectorView: UIView { 
    public var whichStyle: SomeEnumOfYours = // your default value 

    override func draw(_ rect: CGRect) { 
     switch self.whichStyle { 
     case .style1: 
      self.drawStyleOne() 
     case .style2: 
      self.drawStyleTwo() 
     //... 
     } 
    } 
} 

//... 
func styleButtonPressed() { 
    NSLog("STYLE BUTTON PRESSED") 
    _vectorView?.whichStyle = // whichever style required 
    _vectorView?.setNeedsDisplay() 
} 
+0

ありがとうございました。私はこれを投票するのが大好きですが、今は十分な評判ポイントがありません。:( – whgnsdlr7

+0

@ whgnsdlr7 - あなたはまだそれを正しい答えとして受け入れることができます(それだけで十分です担当者に投票してください!):) – Grimxn

0

を。コンテキストを使って作業したり、線を描くためにdrawRectをオーバーライドする必要はありません。レイヤーを使って直接作業することができます。それらをビューに追加し、スタイルを変更して別のスタイルを追加する場合は削除します。あなたはこのようにそれを使用します。

あなたappDelegateで次に
import UIKit 

class VectorView: UIView { 

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

    var myColor = UIColor.red 
    var myPhase = 0 
    var myLength = [2,3] 

    override func layoutSubviews() { 
     super.layoutSubviews() 
     guard let sublayers = self.layer.sublayers else { return } 
     // remove sublayer if any exists 
     for layer in sublayers { 
      layer.removeFromSuperlayer() 
     } 
     // draws your lines according to the style you have defined with your variables above 
     styledDrawing() 
    } 

    func styledDrawing() { 
     // creates a path and styles it 
     let path = UIBezierPath() 
     path.move(to: CGPoint(x: 0.0, y: 10.0)) 
     path.setLineDash(myLength, count: myLength.count, phase: myPhase) 
     path.lineJoinStyle = .bevel 
     path.lineCapStyle = .square 

     // add lines to the path 
     path.addLine(to: CGPoint(x: 50.0, y: 70.0)) 
     path.addLine(to: CGPoint(x: 100.0, y: 20.0)) 

     // creates a layer,adds your path to it and adds the layer to your view's layer 
     let layer = CAShapeLayer() 
     layer.path = path.cgPath 
     layer.lineWidth = 1.0 
     layer.strokeColor = myColor.cgColor 
     self.layer.addSublayer(layer) 
    } 
} 

func styleButtonPressed() { 
    NSLog("STYLE BUTTON PRESSED") 
    _vectorView?.myColor = UIColor.green 
    _vectorView?.myLength = [4,1] 
    _vectorView?.setNeedsLayout() 
} 

スタイルを変更したいときはいつでも、あなたは、変数myPhase、myLengthとmyColorを変更し、appDelegateでyourView.setNeedsLayout()を呼び出します。そうすれば、すべてのスタイルを描くために必要な方法は1つだけです。

+0

私はこれもうまくいくと思います。私はこれも試してみる必要があります。ありがとう! – whgnsdlr7

関連する問題