web-dev-qa-db-ja.com

デバイスの向きを変更するときにカスタムuiviewを再描画します

  1. - (void)drawRect:(CGRect)rect内にグラフを描画すると、[__chartView setContentMode:UIViewContentModeRedraw]_を設定するのに十分であり、デバイスが方向を変更したときにこのメソッドが呼び出され、f.eを計算することができます。チャートの新しい中心点。
  2. - (id)initWithFrame:(CGRect)frameを使用してサブビューのようなビューを作成し、それを_[self.view addSubview:chartView];_のようなビューコントローラーに追加した場合。この場合、回転を処理してチャートを再描画するにはどうすればよいですか?
19
pvllnspk

デバイスの向きが変わったときにチャートを正しくレンダリングするには、チャートのレイアウトを更新する必要があります。ViewControllerに追加する必要があるコードは次のとおりです。

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    _chartView.frame = self.view.bounds;
    [_chartView strokeChart];
}
15
Keenle

_.Redraw_の使用

カスタムビューの作成時にプログラムで_myView.contentMode = .Redraw_を呼び出すだけで十分です。 [〜#〜] ib [〜#〜]の単一フラグであり、そのため、 0行のコードが望ましい方法です。 Stack Overflow IViewサブクラスでdrawRectをトリガーする方法 を参照してください。


setNeedsDisplay()の使用

再描画をトリガーする必要がある場合は、setNeedsDisplayでトリガーし、drawRectを呼び出します。
通知を聞いたり、コードをリファクタリングする必要はありません。

Swift

_override func layoutSubviews() {
    super.layoutSubviews()
    self.setNeedsDisplay()
}
_

Objective-C

_- (void)layoutSubviews {
    [super layoutSubviews];
    [self setNeedsDisplay];
}
_

注:
layoutSubviewsUIViewメソッド、nota UIViewControllerメソッド。

29
SwiftArchitect

here に進み、デバイスの向きが変わったときに通知を受け取る方法を学習します。向きが変わったら、[chartView setNeedsDisplay]; 作る drawRect:が呼び出され、ビューを更新できるようになります。お役に立てれば!

4
Adam Evans

View Controllerに追加するコード:

- (void)updateViewConstraints
{
    [super updateViewConstraints];
    [_chartView setNeedsDisplay];
}
2
2cupsOfTech

残念ながら、いくつかの答えはコントローラーメソッドをオーバーライドすることを示唆していますが、いくつかのカスタムUITableViewCellsの周りに影があり、デバイスを回転させるとセルが引き伸ばされますが、影は再描画されません。したがって、サブビューを(再)描画するためにコントローラー内にコードを配置したくありません。私にとっての解決策は、カスタムUIDeviceOrientationDidChange内でUITableViewCell通知をリッスンし、提案どおりsetNeedsDisplay()を呼び出すことです。

カスタムUITableViewCellsのいずれかのSwift 4.0コード例

override func awakeFromNib() {
    super.awakeFromNib()

    NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChangeNotification), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}

@objc func deviceOrientationDidChangeNotification(_ notification: Any) {
        Logger.info("Orientation changed: \(notification)")
        setNeedsLayout()
}

ところで:LoggertypealiasからSwiftyBeaverです。 @Aderisが私を正しい方向に向けてくれてありがとう。

0
Sal

「setNeedsDisplay」をさまざまな方法で試してみましたが、アニメーション化するビューの影を新しい位置に調整するために機能しませんでした。

私はこれで私の問題を解決しました。シャドウが協力/更新したくない場合は、シャドウをnilに設定してから再度設定してみてください。

    UIView.animateKeyframes(withDuration: 0.2 /*Total*/, delay: 0.0, options: UIViewKeyframeAnimationOptions(), animations: {
        UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 10/10, animations:{
            // Other things to animate

            //Set shadow to nil
            self.viewWithShadow.layer.shadowPath = nil
        })
    }, completion: { finished in
        if (!finished) { return }
        // When the view is moved, set the shadow again
        self.viewWithShadow.layer.shadowPath = UIBezierPath(rect: self.descTextView.bounds).cgPath
    })

まだ影がなく、そのコードが必要な場合は、次のとおりです。

func addShadowTo (view: UIView) {
    view.layer.masksToBounds = false
    view.layer.shadowColor = UIColor.gray.cgColor
    view.layer.shadowOffset = CGSize( width: 1.0, height: 1.0)
    view.layer.shadowOpacity = 0.5
    view.layer.shadowRadius = 6.0
    view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
    view.layer.shouldRasterize = true
}
0
Dave G

上記のObjCソリューションをありがとう、Keenle。プログラムされた制約を午前中に作成し、脳を殺し、なぜそれらがビューを再コンパイル/再配置しないのか理解できずにいじっていました。私は、CGRectを使用してプログラムでUIViewを作成したためだと思います...これが優先されていました。

ただし、Swiftでの私のソリューションは次のとおりです。

    override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))

}

ほっとした! :)

0
David West