it-swarm.com.de

benutzerdefinierte Ansicht neu erstellen, wenn Sie eine Geräteorientierung ändern

  1. Wenn ich mein Diagramm in - (void)drawRect:(CGRect)rect zeichne, reicht es aus, [_chartView setContentMode:UIViewContentModeRedraw] zu setzen. Diese Methode wird aufgerufen, wenn das Gerät seine Orientierung ändert und es möglich ist, f.e. neuer Mittelpunkt für mein Diagramm.
  2. Wenn ich eine Ansicht wie eine Unteransicht mit - (id)initWithFrame:(CGRect)frame erstelle und dann im Ansichtscontroller wie [self.view addSubview:chartView]; hinzufüge. Wie kann ich in diesem Fall mit der Drehung arbeiten, um mein Diagramm neu zu zeichnen?
17
pvllnspk

Damit das Diagramm korrekt dargestellt wird, wenn sich die Geräteorientierung ändert, müssen Sie das Layout des Diagramms aktualisieren.

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    _chartView.frame = self.view.bounds;
    [_chartView strokeChart];
}
14
Keenle

.Redraw verwenden

Das programmgesteuerte Aufrufen von myView.contentMode = .Redraw beim Erstellen der benutzerdefinierten Ansicht sollte ausreichen. Es ist ein einzelnes Flag in IB und daher die 0-Zeilen des Codes bevorzugt. Siehe Stack Overflow So lösen Sie drawRect für die UIView-Unterklasse aus.


Verwenden von setNeedsDisplay()

Wenn Sie eine Neuzeichnung auslösen müssen, tun Sie dies in setNeedsDisplay, wodurch wiederum drawRect aufgerufen wird.
Es ist nicht notwendig, Benachrichtigungen anzuhören oder den Code umzuwandeln.

Swift

override func layoutSubviews() {
    super.layoutSubviews()
    self.setNeedsDisplay()
}

Ziel c

- (void)layoutSubviews {
    [super layoutSubviews];
    [self setNeedsDisplay];
}

Hinweis:
layoutSubviews ist eine UIView-Methode, nicht eine UIViewController-Methode.

28
SwiftArchitect

Gehen Sie zu hier , um zu erfahren, wie Sie Benachrichtigungen erhalten, wenn sich die Ausrichtung des Geräts ändert. Wenn sich die Ausrichtung ändert, rufen Sie einfach [chartView setNeedsDisplay]; an, damit drawRect: aufgerufen wird, damit Sie Ihre Ansicht aktualisieren können. Hoffe das hilft!

4
Aderis

Der Code, den Sie zu Ihrem View-Controller hinzufügen:

- (void)updateViewConstraints
{
    [super updateViewConstraints];
    [_chartView setNeedsDisplay];
}
2
2cupsOfTech

Leider schlagen einige Antworten vor, Controller-Methoden zu überschreiben, aber ich habe ein benutzerdefiniertes UITableViewCells mit einem Schatten um und durch Drehen des Geräts werden die Zellen gedehnt, der Schatten jedoch nicht neu gezeichnet. Daher möchte ich meinen Code nicht in einen Controller einfügen, um eine Unteransicht (neu) zu zeichnen. Die Lösung für mich ist, eine UIDeviceOrientationDidChange-Benachrichtigung in meinem benutzerdefinierten UITableViewCell anzuhören und dann setNeedsDisplay() wie vorgeschlagen aufzurufen.

Swift 4.0 Code-Beispiel in einer meiner benutzerdefinierten 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()
}

Übrigens: Logger ist ein typealias bis SwiftyBeaver. Dank @Aderis weist ich in die richtige Richtung.

0
Sal

Ich habe "setNeedsDisplay" auf ein Dutzend Arten ausprobiert und es funktionierte nicht, um den Schatten einer Ansicht, die ich animierte, an eine neue Position anzupassen.

Ich habe mein Problem damit gelöst. Wenn Ihr Schatten anscheinend nicht zusammenarbeiten/aktualisieren möchte, können Sie einfach versuchen, den Schatten auf Null zu setzen und ihn dann erneut zu setzen:

    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
    })

Wenn Sie noch nicht einmal einen Schatten haben und diesen Code benötigen, können Sie Folgendes tun:

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
}
0
Dave G

Danke Keenle, für die obj-Lösung von ObjC. Ich machte den ganzen Morgen damit herum, programmierte Einschränkungen zu erzeugen, mein Gehirn zu töten und nicht zu verstehen, warum sie die Ansicht nicht neu zusammenstellen/ausrichten würden. Ich denke, weil ich UIView programmgesteuert mit CGRect erstellt hatte ... hatte dies Vorrang.

Hier war jedoch meine Lösung in Swift:

    override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    myUIView.center = CGPoint(x: (UIScreen.mainScreen().bounds.width / 2), y: (UIScreen.mainScreen().bounds.height / 2))

}

So erleichtert! :) 

0
David West