Kurze Antwort
Rahmen \= Position und Größe einer Ansicht mit Hilfe der das Koordinatensystem der übergeordneten Ansicht
- Wichtig für: Platzierung der Ansicht in der übergeordneten
Grenzen \= Position und Größe einer Ansicht mit ein eigenes Koordinatensystem
- Wichtig für: Platzierung des Inhalts der Ansicht oder von Unteransichten in der Ansicht selbst
Ausführliche Antwort
Um mich zu erinnern Rahmen denke ich an ein Bilderrahmen an einer Wand . Der Bilderrahmen ist wie der Rand einer Ansicht. Ich kann das Bild an die Wand hängen, wo immer ich will. Auf die gleiche Weise kann ich eine Ansicht an einer beliebigen Stelle innerhalb einer übergeordneten Ansicht (auch Superview genannt) platzieren. Die übergeordnete Ansicht ist wie eine Wand. Der Ursprung des Koordinatensystems in iOS ist oben links. Wir können unsere Ansicht am Ursprung der übergeordneten Ansicht platzieren, indem wir die x-y-Koordinaten des Ansichtsrahmens auf (0, 0) setzen, was dem Aufhängen unseres Bildes in der linken oberen Ecke der Wand entspricht. Um es nach rechts zu verschieben, erhöhen Sie x, um es nach unten zu verschieben, erhöhen Sie y.
Um mich zu erinnern Grenzen denke ich an einen Basketballplatz wo manchmal der Basketball wird aus dem Spielfeld geworfen . Du dribbelst den Ball über den ganzen Basketballplatz, aber es ist dir eigentlich egal, wo der Platz ist. Es könnte in einer Turnhalle sein, oder draußen an einer High School, oder vor deinem Haus. Es spielt keine Rolle. Du willst einfach nur Basketball spielen. Auf die gleiche Weise interessiert sich das Koordinatensystem für die Grenzen einer Ansicht nur für die Ansicht selbst. Es weiß nichts darüber, wo sich die Ansicht in der übergeordneten Ansicht befindet. Der Ursprung der Begrenzungen (standardmäßig der Punkt (0, 0)) ist die linke obere Ecke der Ansicht. Alle Unteransichten, die diese Ansicht hat, werden in Bezug auf diesen Punkt angeordnet. Es ist so, als würde man den Basketball in die vordere linke Ecke des Spielfelds werfen.
Die Verwirrung entsteht nun, wenn man versucht, Rahmen und Grenzen zu vergleichen. Es ist aber nicht so schlimm, wie es zunächst scheint. Nehmen wir einige Bilder zur Hilfe, um es zu verstehen.
Rahmen vs. Grenzen
Im ersten Bild auf der linken Seite haben wir eine Ansicht, die sich oben links von ihrer übergeordneten Ansicht befindet. Das gelbe Rechteck stellt den Rahmen der Ansicht dar. Auf der rechten Seite sehen wir wieder die Ansicht, aber dieses Mal wird die übergeordnete Ansicht nicht angezeigt. Das liegt daran, dass die Begrenzungen die übergeordnete Ansicht nicht kennen. Das grüne Rechteck stellt die Begrenzungen der Ansicht dar. Die roter Punkt in beiden Bildern stellt die Herkunft des Rahmens oder der Begrenzungen.
Frame
origin = (0, 0)
width = 80
height = 130
Bounds
origin = (0, 0)
width = 80
height = 130
![enter image description here]()
Der Rahmen und die Grenzen waren bei diesem Bild also genau gleich. Schauen wir uns nun ein Beispiel an, bei dem sie unterschiedlich sind.
Frame
origin = (40, 60) // That is, x=40 and y=60
width = 80
height = 130
Bounds
origin = (0, 0)
width = 80
height = 130
![enter image description here]()
Sie können also sehen, dass die Änderung der x-y-Koordinaten des Rahmens diesen in der übergeordneten Ansicht verschiebt. Aber der Inhalt der Ansicht selbst sieht immer noch genau gleich aus. Die Begrenzungen haben keine Ahnung, dass etwas anders ist.
Bisher waren die Breite und Höhe des Rahmens und der Begrenzungen genau gleich. Das ist aber nicht immer der Fall. Sehen Sie sich an, was passiert, wenn wir die Ansicht um 20 Grad im Uhrzeigersinn drehen. (Die Drehung wird mit Hilfe von Transformationen durchgeführt. Siehe die Dokumentation und diese siehe y Beispiele für Ebenen für weitere Informationen).
Frame
origin = (20, 52) // These are just rough estimates.
width = 118
height = 187
Bounds
origin = (0, 0)
width = 80
height = 130
![enter image description here]()
Sie können sehen, dass die Grenzen immer noch dieselben sind. Sie wissen immer noch nicht, dass etwas passiert ist! Die Rahmenwerte haben sich jedoch alle geändert.
Jetzt ist es etwas einfacher, den Unterschied zwischen Frame und Bounds zu erkennen, nicht wahr? Der Artikel Sie verstehen wahrscheinlich nicht, was Frames und Bounds sind definiert einen Ansichtsrahmen als
...das kleinste Begrenzungsrechteck dieser Ansicht in Bezug auf das übergeordnete Koordinatensystem, einschließlich aller auf diese Ansicht angewandten Transformationen.
Es ist wichtig zu beachten, dass der Rahmen undefiniert wird, wenn Sie eine Ansicht transformieren. Der gelbe Rahmen, den ich um die gedrehten grünen Begrenzungen im obigen Bild gezeichnet habe, existiert also eigentlich gar nicht. Das heißt, wenn Sie eine Ansicht drehen, skalieren oder auf andere Weise transformieren, sollten Sie die Rahmenwerte nicht mehr verwenden. Sie können die Werte für die Begrenzungen aber weiterhin verwenden. Die Apple-Dokumente warnen:
Das ist wichtig: Wenn die Ansicht transform
Eigenschaft nicht die Identitätstransformation enthält, ist der Rahmen dieser Ansicht undefiniert und auch die Ergebnisse des Verhaltens zur automatischen Größenanpassung.
Ziemlich unglücklich über die automatische Größenanpassung.... Es gibt jedoch etwas, das Sie tun können.
In den Apple-Dokumenten heißt es:
Bei der Änderung der transform
Eigenschaft Ihrer Ansicht, alle werden alle Transformationen relativ zum Mittelpunkt der Ansicht durchgeführt. Ansicht durchgeführt.
Wenn Sie also eine Ansicht in der übergeordneten Ansicht verschieben müssen, nachdem eine Transformation durchgeführt wurde, können Sie dies tun, indem Sie die view.center
Koordinaten. Wie frame
, center
verwendet das Koordinatensystem der übergeordneten Ansicht.
Okay, lassen wir die Rotation beiseite und konzentrieren uns auf die Begrenzungen. Bislang lag der Ursprung der Grenzen immer bei (0, 0). Das muss aber nicht so sein. Was ist, wenn unsere Ansicht eine große Unteransicht hat, die zu groß ist, um sie alle auf einmal anzuzeigen? Wir machen daraus eine UIImageView
mit einem großen Bild. Hier ist wieder unser zweites Bild von oben, aber dieses Mal können wir sehen, wie der gesamte Inhalt der Unteransicht unserer Ansicht aussehen würde.
Frame
origin = (40, 60)
width = 80
height = 130
Bounds
origin = (0, 0)
width = 80
height = 130
![enter image description here]()
Nur die linke obere Ecke des Bildes kann innerhalb der Grenzen der Ansicht liegen. Schauen Sie sich an, was passiert, wenn wir die Ursprungskoordinaten der Begrenzungen ändern.
Frame
origin = (40, 60)
width = 80
height = 130
Bounds
origin = (280, 70)
width = 80
height = 130
![enter image description here]()
Der Rahmen hat sich in der Superview nicht verschoben, aber der Inhalt innerhalb des Rahmens hat sich geändert, weil der Ursprung des Begrenzungsrechtecks an einem anderen Teil der Ansicht beginnt. Dies ist die ganze Idee hinter einer UIScrollView
und seine Unterklassen (zum Beispiel eine UITableView
). Siehe Verstehen von UIScrollView für weitere Erklärungen.
Wann wird ein Rahmen und wann eine Begrenzung verwendet?
Seit frame
sich auf die Position einer Ansicht in ihrer übergeordneten Ansicht bezieht, verwenden Sie sie, wenn Sie äußere Veränderungen wie das Ändern der Breite oder das Ermitteln des Abstands zwischen der Ansicht und dem oberen Rand der übergeordneten Ansicht.
Verwenden Sie die bounds
wenn Sie innere Veränderungen wie das Zeichnen von Dingen oder das Anordnen von Unteransichten innerhalb der Ansicht. Verwenden Sie auch die Grenzen, um die Größe der Ansicht zu ermitteln, wenn Sie eine Transfomation vorgenommen haben.
Artikel für die weitere Forschung:
Apple-Dokumente
Verwandte StackOverflow-Fragen
Andere Ressourcen
Üben Sie selbst
Zusätzlich zur Lektüre der oben genannten Artikel hilft es mir sehr, eine Testanwendung zu erstellen. Vielleicht möchten Sie versuchen, etwas Ähnliches zu tun. (Ich habe die Idee von dieser Videokurs aber leider ist es nicht kostenlos.)
![enter image description here]()
Hier ist der Code zu Ihrer Information:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
// Labels
@IBOutlet weak var frameX: UILabel!
@IBOutlet weak var frameY: UILabel!
@IBOutlet weak var frameWidth: UILabel!
@IBOutlet weak var frameHeight: UILabel!
@IBOutlet weak var boundsX: UILabel!
@IBOutlet weak var boundsY: UILabel!
@IBOutlet weak var boundsWidth: UILabel!
@IBOutlet weak var boundsHeight: UILabel!
@IBOutlet weak var centerX: UILabel!
@IBOutlet weak var centerY: UILabel!
@IBOutlet weak var rotation: UILabel!
// Sliders
@IBOutlet weak var frameXSlider: UISlider!
@IBOutlet weak var frameYSlider: UISlider!
@IBOutlet weak var frameWidthSlider: UISlider!
@IBOutlet weak var frameHeightSlider: UISlider!
@IBOutlet weak var boundsXSlider: UISlider!
@IBOutlet weak var boundsYSlider: UISlider!
@IBOutlet weak var boundsWidthSlider: UISlider!
@IBOutlet weak var boundsHeightSlider: UISlider!
@IBOutlet weak var centerXSlider: UISlider!
@IBOutlet weak var centerYSlider: UISlider!
@IBOutlet weak var rotationSlider: UISlider!
// Slider actions
@IBAction func frameXSliderChanged(sender: AnyObject) {
myView.frame.origin.x = CGFloat(frameXSlider.value)
updateLabels()
}
@IBAction func frameYSliderChanged(sender: AnyObject) {
myView.frame.origin.y = CGFloat(frameYSlider.value)
updateLabels()
}
@IBAction func frameWidthSliderChanged(sender: AnyObject) {
myView.frame.size.width = CGFloat(frameWidthSlider.value)
updateLabels()
}
@IBAction func frameHeightSliderChanged(sender: AnyObject) {
myView.frame.size.height = CGFloat(frameHeightSlider.value)
updateLabels()
}
@IBAction func boundsXSliderChanged(sender: AnyObject) {
myView.bounds.origin.x = CGFloat(boundsXSlider.value)
updateLabels()
}
@IBAction func boundsYSliderChanged(sender: AnyObject) {
myView.bounds.origin.y = CGFloat(boundsYSlider.value)
updateLabels()
}
@IBAction func boundsWidthSliderChanged(sender: AnyObject) {
myView.bounds.size.width = CGFloat(boundsWidthSlider.value)
updateLabels()
}
@IBAction func boundsHeightSliderChanged(sender: AnyObject) {
myView.bounds.size.height = CGFloat(boundsHeightSlider.value)
updateLabels()
}
@IBAction func centerXSliderChanged(sender: AnyObject) {
myView.center.x = CGFloat(centerXSlider.value)
updateLabels()
}
@IBAction func centerYSliderChanged(sender: AnyObject) {
myView.center.y = CGFloat(centerYSlider.value)
updateLabels()
}
@IBAction func rotationSliderChanged(sender: AnyObject) {
let rotation = CGAffineTransform(rotationAngle: CGFloat(rotationSlider.value))
myView.transform = rotation
updateLabels()
}
private func updateLabels() {
frameX.text = "frame x = \(Int(myView.frame.origin.x))"
frameY.text = "frame y = \(Int(myView.frame.origin.y))"
frameWidth.text = "frame width = \(Int(myView.frame.width))"
frameHeight.text = "frame height = \(Int(myView.frame.height))"
boundsX.text = "bounds x = \(Int(myView.bounds.origin.x))"
boundsY.text = "bounds y = \(Int(myView.bounds.origin.y))"
boundsWidth.text = "bounds width = \(Int(myView.bounds.width))"
boundsHeight.text = "bounds height = \(Int(myView.bounds.height))"
centerX.text = "center x = \(Int(myView.center.x))"
centerY.text = "center y = \(Int(myView.center.y))"
rotation.text = "rotation = \((rotationSlider.value))"
}
}
1 Stimmen
Rahmen verstehen macoscope.com/blog/verstehen-rahmen
0 Stimmen
Für mich ist die prägnanteste Erklärung hier zu finden: videos.raywenderlich.com/courses/99-scroll-view-school/lessons/
1 Stimmen
Ein 2:30-Video hat nichts Prägnantes an sich. Ich kann einen oder zwei Sätze viel schneller lesen als 2:30.
3 Stimmen
Für mich ist es viel klarer, wenn ich auf diese Weise denke: Rahmen = Grenzen & Position