Ios 更改设备方向时重新绘制自定义uiview 如果我在-(void)drawRect:(CGRect)rect内绘制图表,只需设置[\u chartView setContentMode:UIViewContentModeRedraw]即可,当设备更改其方向时,将调用此方法,并且可以计算图表的新中心点 如果我使用-(id)initWithFrame:(CGRect)frame创建类似子视图的视图,然后将其添加到视图控制器中,如[self.view addSubview:chartView]。在这种情况下,我如何处理旋转以重新绘制图表

Ios 更改设备方向时重新绘制自定义uiview 如果我在-(void)drawRect:(CGRect)rect内绘制图表,只需设置[\u chartView setContentMode:UIViewContentModeRedraw]即可,当设备更改其方向时,将调用此方法,并且可以计算图表的新中心点 如果我使用-(id)initWithFrame:(CGRect)frame创建类似子视图的视图,然后将其添加到视图控制器中,如[self.view addSubview:chartView]。在这种情况下,我如何处理旋转以重新绘制图表,ios,uiview,core-graphics,quartz-core,Ios,Uiview,Core Graphics,Quartz Core,转到了解如何在设备方向更改时接收通知。当方向发生变化时,只需调用[chartView setNeedsDisplay]使drawRect:被调用,以便更新视图。希望这有帮助 要在设备方向更改时正确呈现图表,您需要更新图表的布局,以下是应添加到视图控制器的代码: - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; _chartView.frame = self.view.bounds; [_char

转到了解如何在设备方向更改时接收通知。当方向发生变化时,只需调用
[chartView setNeedsDisplay]
使
drawRect:
被调用,以便更新视图。希望这有帮助

要在设备方向更改时正确呈现图表,您需要更新图表的布局,以下是应添加到视图控制器的代码:

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    _chartView.frame = self.view.bounds;
    [_chartView strokeChart];
}
- (void)updateViewConstraints
{
    [super updateViewConstraints];
    [_chartView setNeedsDisplay];
}

将添加到视图控制器的代码:

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    _chartView.frame = self.view.bounds;
    [_chartView strokeChart];
}
- (void)updateViewConstraints
{
    [super updateViewConstraints];
    [_chartView setNeedsDisplay];
}

虽然首选解决方案需要,但如果您必须触发重画,请在
setNeedsDisplay
中执行,然后调用
drawRect

无需监听通知,也无需重构代码

Swift

override func layoutSubviews() {
    super.layoutSubviews()
    self.setNeedsDisplay()
}
目标-C

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

注:

layoutSubviews
是一种
UIView
方法,not是一种
UIViewController
方法。

感谢Keenle提供上述ObjC解决方案。整个上午,我都在胡乱地创建程序约束,扼杀了我的大脑,不理解他们为什么不重新编译/重新调整视图。我猜是因为我使用CGRect以编程方式创建了UIView…这是优先考虑的

然而,以下是我在swift中的解决方案:

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

}

如释重负!:)

不幸的是,一些答案建议覆盖控制器方法,但我有一些自定义的
uitableviewcell
,周围有阴影,旋转设备会拉伸单元格,但不会重新绘制阴影。因此,我不想将代码放在控制器中(重新)绘制子视图。 我的解决方案是在我的自定义
UITableViewCell
中侦听
UIDeviceOrientationDidChange
通知,然后根据建议调用
setNeedsDisplay()

Swift 4.0代码示例在我的一个自定义UITableViewCells中

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()
}
顺便说一句:
Logger
typealias
SwiftyBeaver
。 感谢@Aderis为我指明了正确的方向。

我尝试了十几种方法“设置需要显示”,但它无法将我正在制作动画的视图的阴影调整到新位置

不过我确实用这个解决了我的问题。如果您的阴影似乎不想合作/更新,您可以尝试将阴影设置为零,然后再次设置:

    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
}
零行代码 使用
.redraw


在创建自定义视图时以编程方式调用
myView.contentMode=.redraw
就足够了。它是IB中的一个标志,因此是0行代码的首选方式。请参阅堆栈溢出。

@Keenle,@Kijug当您使用第二种方法绘制时,您不使用drawRect方法,请参阅f.e+仅在设备方向发生更改(如drawRect)时才需要调用重画方法。我已经更新了答案。必须创建一个带有图表控件的测试项目来解决问题。顺便说一句,图表组件是简单和伟大的!我认为,自从自动布局问世以来,在代码中设置框架是非常不鼓励的,请检查我的回答这似乎是一个很好的解决方案,但当我将其放入TableViewController时,它不会在旋转时调用。也许这是我的iOS(8.1)或其他什么的目标版本,但它不起作用。
layoutSubviews
UIView
方法,而不是
UIViewController
方法。您需要创建
UITableView
的子类,而不是
UITableViewController
,这可以在IB中完成。您可能想在上阅读更多关于布局子视图的信息。很酷,谢谢。实际上,我的视图已经从IB中的TableView上设置contentMode=.Redraw开始重新绘制。我遇到的问题是我自己的错,因为已经纠正了。谢谢这在我的测试中不起作用。方向更改不会触发重画。我在我创建的一个类上使用了它,子类UIVIEW我尝试了这个,但在设备旋转时它没有被调用。@DamiendalRusso可能还有其他原因,为什么在设备旋转时它没有被调用,环顾四周我会看,但我发现我的视图正在重画,contentMode设置为.Redraw。它对我不起作用的原因是我自己的愚蠢错误,因为已经修复了。谢谢这是正确的答案,UIView子类将自行处理此问题。