ios 更改设备方向时重绘自定义 uiview
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24683837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
redraw a custom uiview when changing a device orientation
提问by pvllnspk
- If I draw my chart inside
- (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. - If I create a view like a subview using
- (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?
- 如果我在里面绘制图表
- (void)drawRect:(CGRect)rect
就足以设置 [_chartView setContentMode:UIViewContentModeRedraw]
并且当设备改变它的方向时将调用此方法,并且可以计算图表的新中心点。 - 如果我创建一个像子视图一样的视图
- (id)initWithFrame:(CGRect)frame
,然后将它添加到像[self.view addSubview:chartView];
. 在这种情况下,我如何处理旋转以重绘图表?
采纳答案by Keenle
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];
}
回答by SwiftArchitect
While a preferred solution requires zero lines of code, if you musttrigger a redraw, do so in setNeedsDisplay
, which in turn invokes drawRect
.
No need to listen to notifications nor refactor the code.
虽然首选解决方案需要零行代码,但如果您必须触发重绘,请在 中执行此操作setNeedsDisplay
,这又会调用drawRect
.
无需监听通知,也无需重构代码。
Swift
迅速
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
Objective-C
目标-C
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
Note:layoutSubviews
is a UIView
method, nota UIViewController
method.
注:layoutSubviews
是一种UIView
方法,不是一个UIViewController
方法。
回答by Adam Evans
Go hereto 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!
转到此处了解如何在设备方向更改时接收通知。当方向发生变化时,只需调用[chartView setNeedsDisplay];
make drawRect:
get 即可更新视图。希望这可以帮助!
回答by 2cupsOfTech
The code you'll add to your view controller:
您将添加到视图控制器的代码:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
回答by Sal
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.
不幸的是,有些答案建议覆盖控制器方法,但我有一些自定义UITableViewCells
的阴影,旋转设备会拉伸单元格但不重绘阴影。所以我不想将我的代码放在控制器中来(重新)绘制子视图。我的解决方案是UIDeviceOrientationDidChange
在我的自定义中收听通知UITableViewCell
,然后setNeedsDisplay()
按照建议进行调用。
Swift 4.0 Code example in one of my custom UITableViewCells
我的自定义 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
is a typealias
to SwiftyBeaver
.
Thanks to @Aderis pointing me to the right direction.
BTW:Logger
是typealias
到SwiftyBeaver
。感谢@Aderis 为我指明了正确的方向。
回答by SwiftArchitect
Zero Lines of Code
零行代码
Use .redraw
用 .redraw
Programmatically invoking myView.contentMode = .redraw
when creating the custom view should suffice. It is a single flag in IBand, as such, the 0 lines of codeprefered way. See Stack Overflow How to trigger drawRect on UIView subclass.
myView.contentMode = .redraw
在创建自定义视图时以编程方式调用就足够了。它是IB 中的单个标志,因此,0 行代码首选方式。请参阅堆栈溢出如何在 UIView 子类上触发 drawRect。
回答by Dave G
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.
我以十几种方式尝试了“setNeedsDisplay”,但它无法将我正在制作动画的视图的阴影调整到新位置。
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:
尽管如此,我确实解决了我的问题。如果您的影子似乎不想合作/更新,您可以尝试将影子设置为 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
})
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
}
回答by David West
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.
感谢 Keenle,提供上述 ObjC 解决方案。我整个早上都在忙于创建程序化约束,扼杀了我的大脑,不明白为什么他们不会重新编译/重新调整视图。我猜是因为我使用 CGRect 以编程方式创建了 UIView ......这是优先的。
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! :)
好释怀!:)