ฉันมีมุมมองที่มีแถวและคอลัมน์ของมุมมองภาพอยู่ในนั้น
หากมุมมองนี้ถูกปรับขนาดฉันจำเป็นต้องจัดเรียงตำแหน่งการดูภาพใหม่
มุมมองนี้เป็นมุมมองย่อยของมุมมองอื่นที่ได้รับการปรับขนาด
มีวิธีตรวจจับเมื่อมีการปรับขนาดมุมมองนี้หรือไม่
ฉันมีมุมมองที่มีแถวและคอลัมน์ของมุมมองภาพอยู่ในนั้น
หากมุมมองนี้ถูกปรับขนาดฉันจำเป็นต้องจัดเรียงตำแหน่งการดูภาพใหม่
มุมมองนี้เป็นมุมมองย่อยของมุมมองอื่นที่ได้รับการปรับขนาด
มีวิธีตรวจจับเมื่อมีการปรับขนาดมุมมองนี้หรือไม่
คำตอบ:
ตามที่ 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:ก็ไม่ได้เรียกร้องให้ฉันUITextViewsubclass ในระหว่างการปรับขนาดที่เกิดจาก 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 นี่คือผู้ชายของคุณ ขออภัยไม่สามารถใช้ได้กับกรณีของคุณ