簡體   English   中英

更改設備方向時重繪自定義 uiview

[英]redraw a custom uiview when changing a device orientation

  1. 如果我在里面繪制圖表- (void)drawRect:(CGRect)rect就足以設置 [ _chartView setContentMode:UIViewContentModeRedraw]並且當設備改變它的方向時將調用此方法,並且可以為我的圖表計算新的中心點.
  2. 如果我使用- (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()
}

順便說一句: Loggertypealias的類型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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM