Reputation: 5767
- (void)drawRect:(CGRect)rect
is just enough to set [_chartView setContentMode:UIViewContentModeRedraw]
and this method will be called when device changes it's orienatation and it's possible to calculate f.e. new center point for my chart.- (id)initWithFrame:(CGRect)frame
and then add it in view controller like [self.view addSubview:chartView];
. How in this case I can handle rotation to redraw my chart?Upvotes: 29
Views: 32180
Reputation: 1590
Thanks Keenle, for the above ObjC solution. I was messing around with creating programmed constraints all morning, killing my brain, not understanding why they would not recompile/realign the view. I guess because I had created the UIView programmatically using CGRect...this was taking precedence.
However, here was my solution in swift:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))
}
So relieved! :)
Upvotes: 0
Reputation: 48524
While a preferred solution requires zero lines of code, if you must trigger a redraw, do so in setNeedsDisplay
, which in turn invokes drawRect
.
No need to listen to notifications nor refactor the code.
Swift
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
Objective-C
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
Note:
layoutSubviews
is a UIView
method, not a UIViewController
method.
Upvotes: 42
Reputation: 48524
Use .redraw
Programmatically invoking myView.contentMode = .redraw
when creating the custom view should suffice. It is a single flag in IB and, as such, the 0 lines of code prefered way. See Stack Overflow How to trigger drawRect on UIView subclass.
Upvotes: 8
Reputation: 12216
I tried "setNeedsDisplay" in a dozen ways and it didn't work for adjusting the shadow of a view I was animating to a new position.
I did solve my problem with this though. If your shadow doesn't seem to want to cooperate/update, you could try just setting the shadow to nil, then setting it again:
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
})
If you don't even have a shadow yet and need that code, here's that:
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
}
Upvotes: 0
Reputation: 1238
Unfortunately some answers suggest to override controller methods, but I've some custom UITableViewCells
with a shadow around and rotating the device stretches the cells but doesn't redraw the shadow. So I don't want to put my code within a controller to (re)draw a subview.
The solution for me is to listen to a UIDeviceOrientationDidChange
notification within my custom UITableViewCell
and then call setNeedsDisplay()
as suggested.
Swift 4.0 Code example in one of my custom 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()
}
BTW: Logger
is a typealias
to SwiftyBeaver
.
Thanks to @Aderis pointing me to the right direction.
Upvotes: 1
Reputation: 6073
The code you'll add to your view controller:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
Upvotes: 2
Reputation: 12220
To make your chart rendered correctly when device orientation changes you need to update chart's layout, here is the code that you should add to your view controller:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_chartView.frame = self.view.bounds;
[_chartView strokeChart];
}
Upvotes: 15
Reputation: 2082
Go here to learn how to receive notifications for when the device orientation changes. When the orientation does change, just call [chartView setNeedsDisplay];
to make drawRect:
get called so you can update your view. Hope this helps!
Upvotes: 4