- (void)drawRect:(CGRect)rect
内绘制我的图表就足以设置[_chartView setContentMode:UIViewContentModeRedraw]
,当设备更改它的定向时将调用此方法,并且可以计算f.e.我的图表的新中心点。- (id)initWithFrame:(CGRect)frame
创建类似子视图的视图,然后将其添加到视图控制器中,例如[self.view addSubview:chartView];
。在这种情况下,我如何处理轮换以重绘我的图表?答案 0 :(得分:28)
使用.Redraw
在创建自定义视图时以编程方式调用myView.contentMode = .Redraw
就足够了。它是 IB 中的单个标记,因此 0行代码是首选方式。请参阅堆栈溢出How to trigger drawRect on UIView subclass。
使用setNeedsDisplay()
如果您必须触发重绘,请在setNeedsDisplay
中执行此操作,然后再调用drawRect
。
无需收听通知也不需要重构代码。
<强>夫特强>
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
<强>目标C 强>
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
注意:
layoutSubviews
是一种UIView
方法,不是一种UIViewController
方法。
答案 1 :(得分:14)
要在设备方向更改时正确呈现图表,您需要更新图表的布局,以下是您应添加到视图控制器的代码:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_chartView.frame = self.view.bounds;
[_chartView strokeChart];
}
答案 2 :(得分:4)
转到here了解如何接收设备方向更改时的通知。如果方向确实发生变化,只需致电[chartView setNeedsDisplay];
即可调用drawRect:
,以便您更新视图。希望这有帮助!
答案 3 :(得分:2)
您将添加到视图控制器的代码:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
答案 4 :(得分:0)
感谢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))
}
松了一口气! :)
答案 5 :(得分:0)
不幸的是,有些答案建议覆盖控制器方法,但我有一些带有阴影的自定义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()
}
BTW:Logger
是typealias
到SwiftyBeaver
。
感谢@Aderis指出我正确的方向。
答案 6 :(得分:0)
我以十几种方式尝试了“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
}
答案 7 :(得分:0)
使用.redraw
在创建自定义视图时以编程方式调用myView.contentMode = .redraw
就足够了。它是 IB 中的单个标志,因此, 0行代码是首选方式。请参阅堆栈溢出How to trigger drawRect on UIView subclass。