เพิ่ม UIView เหนือสิ่งอื่นใดแม้แต่แถบการนำทาง


181

ฉันต้องการแสดงเหนือมุมมองอื่น ๆ แม้แต่แถบการนำทางมุมมอง "ป๊อปอัป" ที่มีลักษณะเช่นนี้:

  • พื้นหลังสีดำแบบเต็มหน้าจอที่มี 0.5 อัลฟาเพื่อดูUIViewControllerด้านล่าง
  • UIViewหน้าต่างอยู่ตรงกลางที่มีข้อมูลบางส่วน (ปฏิทินถ้าคุณต้องการที่จะรู้ทุกอย่าง)

ในการทำเช่นนั้นฉันได้สร้าง UIViewController ที่มีสองUIViews(พื้นหลังและหน้าต่าง) และฉันพยายามที่จะแสดงมัน ฉันลองง่ายๆ[mySuperVC addSubview:myPopUpVC.view]แต่ฉันยังคงมีแถบนำทางด้านบน

ฉันพยายามที่จะนำเสนอมันเป็นกิริยาช่วย แต่UIViewControllerข้างใต้หายไปและฉันสูญเสียผลโปร่งใสของฉัน

ความคิดใด ๆ ที่จะทำเช่นนี้ฉันแน่ใจว่ามันค่อนข้างง่าย ...

ขอบคุณ!


เพิ่มมุมมองย่อยในหน้าต่างแอปพลิเคชันของคุณ การจัดการการวางแนวอาจเป็นเรื่องยุ่งยาก: stackoverflow.com/questions/8774495/…
Amar

คำตอบ:


197

คุณสามารถทำได้โดยเพิ่มมุมมองของคุณโดยตรงไปยัง keyWindow:

UIView *myView = /* <- Your custom view */;
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:myView];

อัปเดต - สำหรับ Swift 4.1 และสูงกว่า

let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(myView)

2
ขอบคุณ :) น่าเสียดายถ้าคุณอยู่ในโหมดแนวนอนคุณต้องหมุนมุมมอง ฉันไม่แน่ใจว่าฉันรู้วิธีการทำอย่างถูกต้อง
Nicolas Roy

ใช่ฉันอยู่ในโหมดแนวนอนเท่านั้นและ myView จะปรากฏขึ้นพร้อมการหมุน 90 องศา ดูเหมือนจะเป็นสิ่งที่พวกเขากำลังพูดถึงที่นี่: stackoverflow.com/questions/8774495/ …
Nicolas Roy

ปัญหาการปฐมนิเทศเกิดขึ้นกับอุปกรณ์ pre-iOS8 ซึ่งวิธีนี้แก้ปัญหาไม่ได้ผล
thgc

@NicolasRoy Autolayout จะช่วย
Darmen Amanbayev

4
มันไม่ครอบคลุมแถบแท็บ มีทางออกอะไรบ้าง?
Manisha

134

[self.navigationController.view addSubview:overlayView]; คือสิ่งที่คุณต้องการจริงๆ


5
คุณต้องตั้งกรอบ
กาเบรียล Goncalves

1
ทางออกที่ดีมากโดยเฉพาะอย่างยิ่งเมื่อคุณเพิ่มมุมมองที่เป็น "ตัวควบคุมมุมมองของเด็ก"
ริชาร์ด Topchii

2
สิ่งนี้ไม่ทำงานกับมุมมองของตัวควบคุมมุมมองลูก การเปลี่ยนระดับ z ของแถบนำทาง (ตามที่ Nam แนะนำ) ยังใช้ได้กับตัวควบคุมมุมมองลูก
Tapani

ดูเหมือนจะเป็นทางออกที่หรูหรากว่าการเพิ่มมุมมองไปที่หน้าต่างหลัก ด้วยเหตุนี้จึงทำให้มั่นใจได้ว่าจะมีการเพิ่มมุมมองย้ายตามภาพเคลื่อนไหวของมุมมองพื้นฐาน เพราะหากมีการเพิ่มมุมมองในหน้าต่างคีย์มันไม่ได้มาพร้อมกับภาพเคลื่อนไหวและจะต้องถูกลบออกอย่างแยกต่างหากหากคุณต้องการยกเลิกตัวควบคุม
soan saini

มันไม่ได้มากกว่าป๊อปอัพ แต่มันเป็นสิ่งที่ถูกต้องสำหรับกรณีของฉัน ขอบคุณ))
Dilshod Zopirov

112

นี่คือทางออกที่เรียบง่ายและสง่างามที่เหมาะกับฉัน คุณสามารถตั้งค่าตำแหน่ง z ของแถบนำทางไปด้านล่างมุมมอง:

self.navigationController.navigationBar.layer.zPosition = -1;

เพียงจำไว้ว่าให้ตั้งกลับเป็น 0 เมื่อเสร็จแล้ว


1
วิธีนี้ใช้งานได้ดีกว่าการเพิ่มมุมมองแบบซ้อนทับเป็นมุมมองย่อยไปยังมุมมองของตัวควบคุมการนำทาง (ซึ่งเป็นสาเหตุของความผิดพลาด) โซลูชันตำแหน่ง z นี้น่าเชื่อถือมากขึ้นและทำให้เกิดปัญหาน้อยลงในอนาคต
Tapani

มันใช้งานได้ดีเมื่อทำงานกับสตอรีบอร์ด คุณสามารถเพิ่มมุมมองภายในกระดานเรื่องราว!
Jos Koomen

ใช้งานได้ดีสำหรับฉันเช่นกัน มันจะเป็นการดีที่จะพูดถึงว่า zPosition ควรจะตั้งค่ากลับเป็นค่า 0 (คุณเพิ่งพูดถึงว่ามันควรจะถูกตั้งค่ากลับมาเมื่อเสร็จสิ้น) และฉันมี tabBar (จาก TabBarController ในหน้าจอของฉันด้วยฉันพยายามตั้ง zPosition แต่เมื่อกลับไปที่ 0 tabBar ค่ายังไม่ปรากฏดังนั้นสำหรับ tabBar จะดีกว่าที่จะใช้คุณสมบัติ isHidden
Libor Zapletal

1
ไม่ทำงานกับการเข้าถึงได้ง่าย การแพนบนมุมมองจะไม่โฟกัส
antonjn

ผมรักคุณ!! <3
chr0x

57

รุ่น Swift สำหรับการตอบสนองที่เลือก:

สวิฟท์ 4:

let view = UIView()
view.frame = UIApplication.shared.keyWindow!.frame
UIApplication.shared.keyWindow!.addSubview(view)

สวิฟท์ 3.1:

let view = UIView()
view.frame = UIApplication.sharedApplication().keyWindow!.frame 
UIApplication.sharedApplication().keyWindow!.addSubview(view)

6
ฉันสามารถทำให้มุมมองปัจจุบันทั้งหมด (ตัวควบคุมมุมมอง) แต่ทำให้ตัวควบคุมมุมมองที่ปรากฏใหม่ปรากฏอยู่ด้านบนได้หรือไม่
Michał Ziobro

24

เพิ่มมุมมองของคุณเป็นมุมมองย่อยของ NavigationController

[self.navigationController.navigationBar addSubview: overlayView)]

คุณสามารถเพิ่มลงในหน้าต่าง:

UIView *view = /* Your custom view */;
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:view];

หวังว่านี่จะช่วย .. :)


มุมมองกำลังจะมา แต่เมื่อเพิ่มปุ่มไม่สามารถรับการกระทำของปุ่มหรือตั้งค่าข้อความป้ายกำกับที่กำหนดเองบนภาพรวม
Vineesh TP

ทำงานได้ดีสำหรับฉัน:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Arthur Clemens


11

@ คำตอบของน้ำใช้งานได้ดีถ้าคุณเพียงต้องการที่จะแสดงมุมมองของคุณเองแต่ถ้ามุมมองที่กำหนดเองของคุณต้องการการโต้ตอบกับผู้ใช้ที่คุณจำเป็นต้องปิดการใช้งานสำหรับการทำงานร่วมกันnavigationBar

self.navigationController.navigationBar.layer.zPosition = -1
self.navigationController.navigationBar.isUserInteractionEnabled = false

อย่างที่กล่าวไว้ในคำตอบของนัมอย่าลืมย้อนกลับการเปลี่ยนแปลงเหล่านี้:

self.navigationController.navigationBar.layer.zPosition = 0
self.navigationController.navigationBar.isUserInteractionEnabled = true


คุณสามารถทำได้ด้วยวิธีที่ดีกว่าด้วยส่วนขยาย:

extension UINavigationBar {
    func toggle() {
        if self.layer.zPosition == -1 {
            self.layer.zPosition = 0
            self.isUserInteractionEnabled = true
        } else {
            self.layer.zPosition = -1
            self.isUserInteractionEnabled = false
        }
    }
}

และใช้มันอย่างนี้:

self.navigationController.navigationBar.toggle()

1
โซลูชั่นที่สมบูรณ์แบบ .. !! พยายามหลายสิ่งหลายอย่างและใช้เวลามาก .. แต่ก็ใช้ได้ดี .. !!
Dishant

8

คำตอบของ @Nicolas Bonnet อย่างรวดเร็ว:

    var popupWindow: UIWindow?

func showViewController(controller: UIViewController) {
    self.popupWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
    controller.view.frame = self.popupWindow!.bounds
    self.popupWindow!.rootViewController = controller
    self.popupWindow!.makeKeyAndVisible()
}

func viewControllerDidRemove() {
    self.popupWindow?.removeFromSuperview()
    self.popupWindow = nil
}

อย่าลืมว่าหน้าต่างจะต้องเป็นคุณสมบัติที่ดีเนื่องจากคำตอบดั้งเดิมนำไปสู่การยกเลิกการจัดสรรหน้าต่างทันที


6

ฉันแนะนำให้คุณสร้าง UIWindow ใหม่:

UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.rootViewController = viewController;
window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
window.opaque = NO;
window.windowLevel = UIWindowLevelCFShareCircle;
window.backgroundColor = [UIColor clearColor];

[window makeKeyAndVisible];

จากนั้นคุณสามารถจัดการมุมมองของคุณใน UIViewController อื่น ๆ วิธีลบหน้าต่าง:

[window removeFromSuperview];
window = nil;

หวังว่าจะช่วยได้!


3
ขอบคุณ แต่ฉันคิดว่ามีบางอย่างขาดหายไปเพราะไม่มีสิ่งใดปรากฏขึ้น: /
Nicolas Roy

6

มีมากกว่าหนึ่งวิธีที่จะทำ:

1- เพิ่มของคุณUIViewบนแทนการเพิ่มบนUIWindow UIViewControllerวิธีนี้จะอยู่ด้านบนของทุกสิ่ง

   [[(AppDelegate *)[UIApplication sharedApplication].delegate window] addSubview:view];

2- ใช้การเปลี่ยนแปลงแบบกำหนดเองที่จะทำให้ UIViewController ของคุณแสดงอยู่ด้านหลังด้วย 0.5 อัลฟา

เพื่อที่ฉันขอแนะนำให้คุณดูที่: https://github.com/Citrrus/BlurryModalSegue



3

ใน Swift 4.2 และ Xcode 10

var spinnerView: UIView? //This is your view

spinnerView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
//Based on your requirement change width and height like self.view.bounds.size.width
spinnerView?.backgroundColor = UIColor.black.withAlphaComponent(0.6)
//        self.view.addSubview(spinnerView)
let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(spinnerView!)

ในวัตถุประสงค์ C

UIView * spinnerView; // นี่คือมุมมองของคุณ

self.spinnerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height)];  
//Based on your requirement change width and height like self.view.bounds.size.width
self.spinnerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
// [self.view addSubview:self.spinnerView];
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:self.spinnerView];

สิ่งนี้สามารถทำงานได้ทั้งโหมดแนวตั้งหรือแนวนอนเท่านั้น

อีกหนึ่งรหัสง่าย ๆ คือ:

yourViewName.layer.zPosition = 1//Change you view name

2

หมายเหตุหากคุณต้องการเพิ่มมุมมองแบบเต็มหน้าจอให้ใช้โค้ดด้านล่างเท่านั้น

เพิ่มส่วนขยายของUIViewControllerเหล่านี้

public extension UIViewController {
   internal func makeViewAsFullScreen() {
      var viewFrame:CGRect = self.view.frame
      if viewFrame.origin.y > 0 || viewFrame.origin.x > 0 {
        self.view.frame = UIScreen.main.bounds
      }
   }
}

ดำเนินการตามกระบวนการเพิ่มปกติของการดูย่อย

ตอนนี้ใช้ในการเพิ่มviewDidAppear ของ UIViewController

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

     self.makeViewAsFullScreen()
}

1

ฉันจะใช้คลาสย่อย UIViewController ที่มี "มุมมองคอนเทนเนอร์" ที่ฝังตัวควบคุมมุมมองอื่น ๆ ของคุณ จากนั้นคุณจะสามารถเพิ่มตัวควบคุมการนำทางภายในมุมมองคอนเทนเนอร์ (โดยใช้ตัวอย่างความสัมพันธ์แบบฝัง)

ดูที่การใช้คอนเทนเนอร์มุมมองคอนโทรลเลอร์



0
[self.navigationController.navigationBar.layer setZPosition:-0.1];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 20, 35, 35)];
[view setBackgroundColor:[UIColor redColor]];
[self.navigationController.view addSubview:view];
[self.navigationController.view bringSubviewToFront:view];
self.navigationController.view.clipsToBounds = NO;
[self.navigationController.navigationBar.layer setZPosition:0.0];

ป้อนคำอธิบายรูปภาพที่นี่


0

คุณต้องเพิ่มมุมมองย่อยให้กับหน้าต่างแรกด้วยประเภท UITextEffectsWindow ในส่วนแรกเนื่องจากแป้นพิมพ์แบบกำหนดเองให้เพิ่ม UITextEffectsWindow และถ้าคุณเพิ่มมุมมองย่อยสิ่งนี้จะไม่ทำงานอย่างถูกต้อง นอกจากนี้คุณไม่สามารถเพิ่มมุมมองย่อยไปยังหน้าต่างสุดท้ายได้เพราะแป้นพิมพ์เป็นหน้าต่างและคุณไม่สามารถแสดงได้จากหน้าต่างแป้นพิมพ์ ดังนั้นทางออกที่ดีที่สุดที่ฉันพบคือการเพิ่ม subview (หรือแม้กระทั่ง push view controller) ในหน้าต่างแรกด้วยประเภท UITextEffectsWindow หน้าต่างนี้ครอบคลุมมุมมองอุปกรณ์เสริม navbar - ทุกอย่าง

let myView = MyView()
myView.frame = UIScreen.main.bounds

guard let textEffectsWindow = NSClassFromString("UITextEffectsWindow") else { return }
let window = UIApplication.shared.windows.first { window in
    window.isKind(of: textEffectsWindow)
}
window?.rootViewController?.view.addSubview(myView)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.