ฉันมีมุมมองที่มีแถวและคอลัมน์ของมุมมองภาพอยู่ในนั้น
หากมุมมองนี้ถูกปรับขนาดฉันจำเป็นต้องจัดเรียงตำแหน่งการดูภาพใหม่
มุมมองนี้เป็นมุมมองย่อยของมุมมองอื่นที่ได้รับการปรับขนาด
มีวิธีตรวจจับเมื่อมีการปรับขนาดมุมมองนี้หรือไม่
ฉันมีมุมมองที่มีแถวและคอลัมน์ของมุมมองภาพอยู่ในนั้น
หากมุมมองนี้ถูกปรับขนาดฉันจำเป็นต้องจัดเรียงตำแหน่งการดูภาพใหม่
มุมมองนี้เป็นมุมมองย่อยของมุมมองอื่นที่ได้รับการปรับขนาด
มีวิธีตรวจจับเมื่อมีการปรับขนาดมุมมองนี้หรือไม่
คำตอบ:
ตามที่ Uli แสดงความคิดเห็นไว้ด้านล่างวิธีที่เหมาะสมในการทำคือการแทนที่layoutSubviews
และจัดวาง imageView ที่นั่น
หากด้วยเหตุผลบางประการคุณไม่สามารถซับคลาสและลบล้างlayoutSubviews
ได้การสังเกตbounds
ควรใช้งานได้แม้ว่าจะสกปรกก็ตาม ที่แย่กว่านั้นคือมีความเสี่ยงในการสังเกต - Apple ไม่รับประกันว่า KVO จะทำงานในคลาส UIKit อ่านการสนทนากับวิศวกรของ Apple ที่นี่: วัตถุที่เกี่ยวข้องจะถูกเผยแพร่เมื่อใด
คำตอบเดิม:
คุณสามารถใช้การสังเกตคีย์ - ค่า:
[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];
และใช้:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
// do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
}
}
viewWillTransition
ฯลฯ เป็นต้น
layoutSubviews
ยังคงใช้วิธีการที่แนะนำหากขึ้นอยู่กับขนาดปัจจุบันของมุมมองจำเป็นต้องเพิ่ม / ลบมุมมองย่อยที่แตกต่างกันและต้องเพิ่ม / ลบข้อ จำกัด ที่แตกต่างกันออกไปหรือไม่
ในUIView
คลาสย่อยสามารถใช้ผู้สังเกตการณ์คุณสมบัติ :
override var bounds: CGRect {
didSet {
// ...
}
}
หากไม่มีคลาสย่อยการสังเกตคีย์ - ค่าด้วยสมาร์ทคีย์ - พา ธจะทำ:
var boundsObservation: NSKeyValueObservation?
func beginObservingBounds() {
boundsObservation = observe(\.bounds) { capturedSelf, _ in
// ...
}
}
frame
เป็นคุณสมบัติที่ได้รับและรันไทม์คำนวณ อย่าลบล้างสิ่งนี้เว้นแต่คุณจะมีเหตุผลที่ชาญฉลาดและรู้เหตุผลในการทำเช่นนั้น มิฉะนั้นงาน: ใช้งานbounds
หรือ layoutSubviews
(ดียิ่งขึ้น)
override var bounds: CGRect { didSet { layer.cornerRadius = bounds.size.width / 2 }}
สร้างคลาสย่อยของ UIView และแทนที่เค้าโครง
ปุ่มกด Swift 4 KVO - นี่คือวิธีที่ฉันตรวจจับการหมุนอัตโนมัติและย้ายไปที่แผงด้านข้างของ iPad ควรทำงานในมุมมองใด ๆ ต้องสังเกตชั้นของ UIView
private var observer: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observer = view.layer.observe(\.bounds) { object, _ in
print(object.bounds)
}
// ...
}
override func viewWillDisappear(_ animated: Bool) {
observer?.invalidate()
//...
}
.layer
ได้เคล็ดลับ! คุณรู้หรือไม่ว่าทำไมการใช้view.observe
ไม่ได้ผล?
คุณสามารถสร้างคลาสย่อยของ UIView และแทนที่ไฟล์
setFrame: เฟรม (CGRect)
วิธี. นี่คือวิธีการที่เรียกว่าเมื่อเฟรม (เช่นขนาด) ของมุมมองเปลี่ยนไป ทำสิ่งนี้:
- (void) setFrame:(CGRect)frame
{
// Call the parent class to move the view
[super setFrame:frame];
// Do your custom code here.
}
setFrame:
ก็ไม่ได้เรียกร้องให้ฉันUITextView
subclass ในระหว่างการปรับขนาดที่เกิดจาก autorotation ในขณะที่layoutSubviews:
เป็น หมายเหตุ: ฉันใช้เค้าโครงอัตโนมัติและ iOS 7.0
setFrame:
ไม่เคยแทนที่ frame
เป็นคุณสมบัติที่ได้รับ ดูคำตอบของฉัน
ค่อนข้างเก่า แต่ก็ยังเป็นคำถามที่ดี ในโค้ดตัวอย่างของ Apple และในคลาสย่อย UIView ส่วนตัวบางคลาสพวกเขาจะแทนที่ setBounds โดยประมาณเช่น:
-(void)setBounds:(CGRect)newBounds {
BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves
[super setBounds:newBounds];
if (isResize) [self recoverFromResizing];
}
การลบล้างsetFrame:
ไม่ใช่ความคิดที่ดี frame
ที่ได้มาจากcenter
, bounds
และtransform
ดังนั้น iOS setFrame:
ของคุณจะไม่จำเป็นต้องโทร
setBounds:
จะไม่ถูกเรียกเมื่อตั้งค่าคุณสมบัติของเฟรม (อย่างน้อยบน iOS 7.1) นี่อาจเป็นการเพิ่มประสิทธิภาพที่ Apple เพิ่มเพื่อหลีกเลี่ยงข้อความเพิ่มเติม
frame
และbounds
จะได้มาจากมุมมองของพื้นฐานCALayer
; พวกเขาเพียงแค่เรียกผ่านไปยัง getter ของเลเยอร์ และsetFrame:
กำหนดกรอบของเลเยอร์ในขณะที่setBounds:
กำหนดขอบเขตของเลเยอร์ ดังนั้นคุณจึงไม่สามารถลบล้างสิ่งใดสิ่งหนึ่งได้ นอกจากนี้ยังlayoutSubviews
ถูกเรียกว่ามากเกินไป (ไม่ใช่แค่การเปลี่ยนแปลงรูปทรงเรขาคณิต) ดังนั้นจึงอาจไม่ใช่ตัวเลือกที่ดีเสมอไป ยังคงมองหา ...
หากคุณอยู่ในอินสแตนซ์ UIViewController การลบล้างviewDidLayoutSubviews
จะเป็นการหลอกลวง
override func viewDidLayoutSubviews() {
// update subviews
}
UIView
อินสแตนซ์และUIViewController
อินสแตนซ์ ดังนั้นหากคุณมีUIView
อินสแตนซ์ที่ไม่มี VC แนบมาคำตอบอื่น ๆ ก็เยี่ยมมาก แต่ถ้าคุณติด VC นี่คือผู้ชายของคุณ ขออภัยไม่สามารถใช้ได้กับกรณีของคุณ