所有控制器上的快速播放器小部件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了所有控制器上的快速播放器小部件相关的知识,希望对你有一定的参考价值。

我在我的应用程序中做广播播放器。并希望拥有带有信息+控制按钮的小部件,这些按钮将在播放时保留在应用程序中的所有控制器上。就像在itunes或像谷歌chromecast容器一样,将从底部推送其他viewcontroller的所有元素(不是覆盖元素)

enter image description here

我知道覆盖视图可以在appdelegate中添加到keywindow,因为GoogleCast Container添加了:

let appStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation")
let castContainerVC: GCKUICastContainerViewController = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController)
castContainerVC.miniMediaControlsItemEnabled = true
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = castContainerVC
self.window?.makeKeyAndVisible()

但我无法理解,我如何设计和实例化我的控制器+添加到窗口+隐藏什么都没有播放。

我忘了提,该应用程序已经启动并运行。导航栏内有大约30个视图控制器

答案

我会在当前窗口的顶部创建一个窗口,我将放置该无线电视图。然后,无线电视图将始终位于标准窗口中的视图层次结构之上。要允许触摸事件由无线电窗口下的标准窗口处理,您需要在无线电窗口中覆盖hitTest,以确保它不会处理不应由它处理的事件。

您可以将此作为示例:

import UIKit

class RadioController: UIViewController {

    fileprivate struct Static {
        static let window: UIHigherWindow = {
            let window = UIHigherWindow(frame: UIScreen.main.bounds)
            window.rootViewController = RadioController()
            window.windowLevel = UIWindowLevelAlert - 1
            return window
        }()
    }

    override func loadView() {
        // use passView, as it will pass the touch events tu underlying window
        self.view = PassView()
        self.view.backgroundColor = UIColor.clear
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // configure whatever subview you want, in your case the radio view
        let radioView = UIView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height - 50, width: UIScreen.main.bounds.width, height: 50))
        radioView.backgroundColor = .red
        self.view.addSubview(radioView)
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        // this will now define the status bar style, as it will become the topmost window for most of the time
        return .default
    }

    static var showing: Bool {
        get {
            return !Static.window.isHidden
        }
    }

    static func present() {
        Static.window.isHidden = false
    }

    static func hide() {
        Static.window.isHidden = true
    }
}

// MARK: Passing touch events to the back view
class PassView: UIView {}

class UIHigherWindow: UIWindow {

    // this will allow touch events to be processed by the default window
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let hitView = super.hitTest(point, with: event)
        if hitView!.isKind(of: PassView.self) {
            return nil
        }
        return hitView
    }
}
另一答案

  1. 将初始视图控制器嵌入容器视图控制器中
  2. 将子视图添加到容器vc的视图底部
  3. 对齐子视图,使它们位于主视图下方的屏幕外
  4. 创建一种方法,在调用时将子视图从底部设置为适当的位置,将另一个方法设置为将子视图设置为底部下方的动画
  5. 在适当的代码中调用动画方法

笔记

您将需要向容器vc添加自定义类,以便可以在其上调用动画方法

以上是关于所有控制器上的快速播放器小部件的主要内容,如果未能解决你的问题,请参考以下文章

此应用小部件片段中所有意图 (PendingIntents) 的逻辑流

如何将所有分类结果打印到 GUI 上的文本小部件?

AppCompat v22.1.0 没有为片段正确主题化所有 xml 小部件

ListView 不可点击,行中的所有小部件都是 TextView

Android小部件,启动一个片段?

Flutter 小部件显示在所有屏幕上