[英]redraw a custom uiview when changing a device orientation
- (void)drawRect:(CGRect)rect
就足以設置 [ _chartView setContentMode:UIViewContentModeRedraw]
並且當設備改變它的方向時將調用此方法,並且可以為我的圖表計算新的中心點.- (id)initWithFrame:(CGRect)frame
創建一個類似於子視圖的視圖,然后將其添加到視圖控制器中,例如[self.view addSubview:chartView];
. 在這種情況下,我如何處理旋轉以重繪圖表?雖然首選解決方案需要零行代碼,但如果您必須觸發重繪,請在setNeedsDisplay
中執行此操作,然后調用drawRect
。
無需監聽通知,也無需重構代碼。
迅速
override func layoutSubviews() {
super.layoutSubviews()
self.setNeedsDisplay()
}
目標-C
- (void)layoutSubviews {
[super layoutSubviews];
[self setNeedsDisplay];
}
筆記:
layoutSubviews
是一個UIView
方法,而不是一個UIViewController
方法。
為了在設備方向更改時正確呈現圖表,您需要更新圖表的布局,以下是您應該添加到視圖控制器的代碼:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_chartView.frame = self.view.bounds;
[_chartView strokeChart];
}
使用.redraw
在創建自定義視圖時以編程方式調用myView.contentMode = .redraw
就足夠了。 它是IB 中的單個標志,因此, 0 行代碼首選方式。 請參閱堆棧溢出如何在 UIView 子類上觸發 drawRect 。
轉到此處了解如何在設備方向更改時接收通知。 當方向確實改變時,只需調用[chartView setNeedsDisplay];
使drawRect:
被調用,以便您可以更新您的視圖。 希望這可以幫助!
您將添加到視圖控制器的代碼:
- (void)updateViewConstraints
{
[super updateViewConstraints];
[_chartView setNeedsDisplay];
}
不幸的是,有些答案建議覆蓋控制器方法,但我有一些自定義的UITableViewCells
,周圍有陰影,旋轉設備會拉伸單元格,但不會重繪陰影。 所以我不想將我的代碼放在控制器中來(重新)繪制子視圖。 我的解決方案是在我的自定義UITableViewCell
收聽UIDeviceOrientationDidChange
通知,然后按照建議調用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()
}
順便說一句: Logger
是typealias
的類型SwiftyBeaver
。 感謝@Aderis 為我指明了正確的方向。
感謝 Keenle,提供上述 ObjC 解決方案。 我整個早上都在忙於創建程序化約束,扼殺了我的大腦,不明白為什么他們不會重新編譯/重新調整視圖。 我猜是因為我使用 CGRect 以編程方式創建了 UIView ......這是優先的。
但是,這是我快速的解決方案:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))
}
好釋懷! :)
我以十幾種方式嘗試了“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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.