You need to enable JavaScript to run this app.
导航

UI 定制

最近更新时间2024.04.02 17:52:36

首次发布时间2023.04.28 10:29:12

本文介绍了在使用 iOS 观播 SDK 时如何自定义直播间的 UI。

说明

  • SDK 的 UI 定制优先级高于企业直播控制台的自定义配置,例如同时通过 SDK 的 BDLCommentViewConfiguration.thumbUpButtonImage 方法和控制台自定义了直播间点赞按钮图片,观看页会展示 BDLCommentViewConfiguration.thumbUpButtonImage 方法自定义的按钮图片。
  • 建议在成功进入直播间后、显示直播间页面前配置 UI 定制内容。

自定义方式说明

您可以通过以下两种方式自定义直播间的 UI。

通过前缀为 customize 的属性自定义

您可以在 joinLiveRoomWithActivity:success:failuresuccess 回调中调用 getLivePullViewController方法,获取 BDLLivePullViewController 实例。然后,通过 BDLLivePullViewControllerconfig 属性,对 BDLLivePullViewController 进行自定义配置。BDLLivePullViewControllerConfig 中提供大量前缀为 customize 的 Block。您可以根据 Block 的参数获取对应的 view 并自定义 view 的属性。

  • 对于有返回值的 Block,在自定义属性后,您可以将 view 返回给 SDK,也可以直接替换成自己的实现,将您自己实现的实例返回给 SDK。
  • 对于没有返回值的 Block,则只支持自定义属性。

customizeAccountView 属性为例:

@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeAccountView)(BDLLivePullViewController *viewController, BDLBusinessAccountView *view);

customizeAccountView 属性可用来自定义主播账号功能的 UI。例如,您可以通过该属性获取到 BDLBusinessAccountView,然后设置 BDLBusinessAccountView.avatarImageView 来自定义主播账号头像除圆角、图片、位置外的所有属性。

说明

  • 如需隐藏 view,返回 nil 给 SDK 即可,或者在企业直播控制台中设置关闭该 view 对应的功能。不建议通过设置 hidden 属性隐藏 view,因为这种方式可能会被企业直播控制台中的设置覆盖。
  • 由于 view 内部使用自动布局,所以除特殊说明外,不建议自定义 view 的位置属性。如需自定义 view 的位置,建议您自行实现 view,然后替换默认的实现。
  • 不支持将 UI 控件自定义为常显示,即在企业直播控制台中关闭 UI 控件对应的功能,SDK 中却配置为显示。
  • 自定义文案时,除特殊说明外,均支持自定义多语言。不同语言的文案之间使用|分隔,SDK 会选取对应语言的内容,格式如下:
    简体中文|English|日本語|繁體中文

通过后缀为 Configuration 的属性自定义

SDK 在 liveRoomConfiguration 中提供大量后缀为 Configuration 的属性。您可以参考以下代码,获取对应的 Configuration 接口进行自定义:

[[BDLLiveEngine sharedInstance] liveRoomConfiguration].xxxxConfig

直播间定制

BDLLivePullViewController

@class BDLLivePullViewController;
/// 多语言选中回调
/// @param selectedLanguageType 选中的语言
typedef void (^BDLLanguageConfirmBlock)(BDLLanguageType selectedLanguageType);
/// 完整直播间的事件提供者
@protocol BDLLivePullViewControllerActionProvider <NSObject>

/// 显示完整直播间
- (void)showLivePullViewController:(BDLLivePullViewController *)livePullVC;
/// 隐藏完整直播间
- (void)hideLivePullViewController:(BDLLivePullViewController *)livePullVC;

@optional

/// 在观众点击完整直播间的关闭按钮时调用该方法
/// @return 是否执行 defaultCloseAction
- (BOOL)livePullViewController:(BDLLivePullViewController *)livePullVC onCloseClick:(UIButton *)closeButton;
/// 在观众点击浮窗关闭按钮时调用该方法
/// @return 是否执行 defaultFloatingPlayerCloseAction
/// 请使用 BDLLivePullViewController onFloatingPlayerCloseTapped Block,而非以下方法
- (BOOL)livePullViewController:(BDLLivePullViewController *)livePullVC onFloatingPlayerClose:(BDLPlayerView *)floatingPlayer DEPRECATED_MSG_ATTRIBUTE("use onFloatingPlayerCloseTapped Block instead");
/// 在观众点击浮窗时调用该方法
/// @return 是否执行 defaultFloatingPlayerTapAction 
/// 请使用 BDLLivePullViewController onFloatingPlayerTapped Block,而非以下方法
- (BOOL)livePullViewController:(BDLLivePullViewController *)livePullVC onFloatingPlayerTap:(BDLPlayerView *)floatingPlayer DEPRECATED_MSG_ATTRIBUTE("use onFloatingPlayerTapped Block instead");

@end

/// 完整直播间的代理方法
@protocol BDLLivePullViewControllerDelegate <NSObject>

@optional
/// 直播间关闭按钮点击回调
/// 请使用 BDLLivePullViewControllerActionProvider livePullViewController:onCloseClick: 方法,而非以下方法
- (void)livePullViewControllerCloseButtonDidClick:(BDLLivePullViewController *)livePullVC isFloating:(BOOL)isFloating DEPRECATED_MSG_ATTRIBUTE("use BDLLivePullViewControllerActionProvider livePullViewController:onCloseClick: instead");;

/// 在即将退出完整直播间时调用该方法,您需要在该方法中释放完整直播间相关的引用
- (void)livePullViewControllerWillLeaveLiveRoom:(BDLLivePullViewController *)livePullVC;
/// 在完整直播间对应的 view 加载完成时调用该方法,对应生命周期方法中的 viewDidLoad
- (void)livePullViewControllerDidLoad:(BDLLivePullViewController *)livePullVC;
/// 在完整直播间对应的 view 即将显示时调用该方法,对应生命周期方法中的 viewWillAppear
- (void)livePullViewControllerWillAppear:(BDLLivePullViewController *)livePullVC;
/// 在完整直播间对应的 view 已经显示时调用该方法,对应生命周期方法中的 viewDidAppear
- (void)livePullViewControllerDidAppear:(BDLLivePullViewController *)livePullVC;
/// 在完整直播间对应的 view 即将消失时调用该方法,对应生命周期方法中的 viewWillDisappear
- (void)livePullViewControllerWillDisappear:(BDLLivePullViewController *)livePullVC;
/// 在完整直播间对应的 view 已经消失时调用该方法,对应生命周期方法中的 viewDidDisappear
- (void)livePullViewControllerDidDisappear:(BDLLivePullViewController *)livePullVC;
/// 在完整直播间对应的 view 即将被销毁时调用该方法,对应生命周期方法中的 dealloc
- (void)livePullViewControllerWillDestroy:(BDLLivePullViewController *)livePullVC;
/// 在播放器即将进入全屏状态时调用该方法
- (void)livePullViewControllerEnterFullScreen:(BDLLivePullViewController *)livePullVC;
/// 在播放器即将退出全屏状态时调用该方法
- (void)livePullViewControllerLeaveFullScreen:(BDLLivePullViewController *)livePullVC;
/// 在浮窗即将显示时调用该方法
/// 请使用 BDLLivePullViewController floatingPlayerViewWillAppear Block,而非以下方法
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC floatingPlayerViewWillAppear:(BDLPlayerView *)playerView DEPRECATED_MSG_ATTRIBUTE("use floatingPlayerViewWillAppear Block instead");
/// 在浮窗消失时调用该方法
/// 请使用 BDLLivePullViewController floatingPlayerViewDidDisappear Block,而非以下方法
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC floatingPlayerViewDidDisappear:(BDLPlayerView *)playerView DEPRECATED_MSG_ATTRIBUTE("use floatingPlayerViewDidDisappear Block instead");
/// 浮窗点击回调
/// 请使用 BDLLivePullViewController onFloatingPlayerTapped Block,而非以下方法
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC floatingPlayerViewDidTap:(BDLPlayerView *)playerView DEPRECATED_MSG_ATTRIBUTE("use onFloatingPlayerTapped Block instead");
/// 在浮窗即将关闭时调用该方法
/// 请使用 BDLLivePullViewController floatingPlayerViewWillClose Block,而非以下方法
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC floatingPlayerViewWillClose:(BDLPlayerView *)playerView DEPRECATED_MSG_ATTRIBUTE("use floatingPlayerViewWillClose Block instead");
/// 显示多语言选择的弹窗
/// @param languageTypes 当前所有支持的语言类型
/// @param currentSelectedType 当前选中的语言
/// @param confirmBlock 选中回调
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC showCustomLanguageSelectionView:(NSArray<NSNumber *> *)languageTypes currentSelectedType:(BDLLanguageType)currentSelectedType confirm:(BDLLanguageConfirmBlock)confirmBlock;
/// 在观众点击分享按钮时触发该回调方法
/// 请使用 livePullViewController:showCustomShareView:shareInfo:inviteTokenModel: 方法,而非以下方法
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC showCustomShareView:(NSString *)shareLink DEPRECATED_MSG_ATTRIBUTE("use livePullViewController:showCustomShareView:shareInfo:inviteTokenModel: instead");

/// 在观众点击分享按钮时触发该回调方法并传入以下参数
/// @param livePullVC 当前完整直播间
/// @param shareLink 分享地址
/// @param shareInfo 分享信息
/// @param inviteTokenModel 当前观众的专属邀请信息
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC
           showCustomShareView:(NSString *)shareLink
                     shareInfo:(BDLGetShareInfoResult *)shareInfo
              inviteTokenModel:(nullable BDLGetInviteTokenResult *)inviteTokenModel;

/// 在观众点击页头广告时触发该回调方法并传入以下参数
/// @param livePullVC 当前完整直播间
/// @param url 页头广告链接地址
/// @param floatingEnable 是否开启浮层展示
- (void)livePullViewController:(BDLLivePullViewController *)livePullVC didClickHeaderAd:(NSString *)url floatingEnable:(BOOL)floatingEnable;

/// 自定义浮窗的初始位置
/// @return 浮窗的初始位置
/// 请使用 BDLLivePullViewController frameForFloatingPlayer Block,而非以下方法
- (CGRect)livePullViewController:(BDLLivePullViewController *)livePullVC frameForFloatingPlayer:(BDLPlayerView *)playerView DEPRECATED_MSG_ATTRIBUTE("use frameForFloatingPlayer Block instead");

@end

@interface BDLLivePullViewController : UIViewController

/// 代理方法,详见 BDLLivePullViewControllerDelegate
@property (nonatomic, weak) id<BDLLivePullViewControllerDelegate> delegate;
/// 事件提供者,用于 SDK 外部响应某些事件,详见 BDLLivePullViewControllerActionProvider
@property (nonatomic, weak) id<BDLLivePullViewControllerActionProvider> actionProvider;
/// 初始化方法传递进来的 isPortrait
@property (nonatomic, assign, readonly) BOOL isPortrait;
/// 是否正在浮窗播放
@property (nonatomic, assign, readonly) BOOL isFloating;

/// 完整直播间的配置
@property (nonatomic, strong, readonly) BDLLivePullViewControllerConfig *config;

/// 初始化方法
/// @param activityId 直播间活动 ID
/// @param isPortrait 是否为竖屏
- (instancetype)initWithActivityId:(NSNumber *)activityId isPortrait:(BOOL)isPortrait;

/// 初始化方法
/// @param activityId 直播间活动 ID
/// @param isPortrait 是否为竖屏
/// @param basePlayerView 已经开始播放的独立播放器
- (instancetype)initWithActivityId:(NSNumber *)activityId
                        isPortrait:(BOOL)isPortrait
                    basePlayerView:(nullable BDLBasePlayerView *)basePlayerView;

/// 将已经开始播放的 basePlayerView 传入 BDLLivePullViewController
/// @param basePlayerView 已经开始播放的独立播放器
- (void)addBasePlayerView:(BDLBasePlayerView *)basePlayerView;

/// 关闭完整直播间
/// @param showFloatingPlayerIfAvailable 在可以显示浮窗时,是否显示浮窗
- (void)close:(BOOL)showFloatingPlayerIfAvailable;

/// 在可以显示浮窗时,显示浮窗
/// @param close 是否关闭完整直播间。将值设置为 YES 时,如果浮窗显示失败,不会关闭完整直播间
/// @return 是否显示成功
- (BOOL)showFloatingPlayerIfAvailable:(BOOL)close;

/// 隐藏浮窗
/// @param show 是否显示完整直播间。YES:关闭浮窗,显示完整直播间。 NO:关闭浮窗,不显示完整直播间
- (void)hideFloatingPlayerIfAvailable:(BOOL)show;

/// 浮窗的方向
@property (nonatomic, assign) UIInterfaceOrientation floatingPlayerOrientation;

@end

/// 默认实现
@interface BDLLivePullViewController (BDLDefaultAction)

/// 完整直播间关闭事件的默认实现,即退出完整直播间,如正在播放直播或点播视频且开启了浮窗(InApp 画中画),则会在退出完整直播间的同时展示浮窗
- (void)defaultCloseAction;
/// 浮窗点击事件的默认实现,即关闭浮窗并返回完整直播间
- (void)defaultFloatingPlayerTapAction;
/// 浮窗关闭事件的默认实现,即关闭浮窗
- (void)defaultFloatingPlayerCloseAction;

/// 获取默认的浮窗展示位置
- (CGRect)defaultFloatingPlayerFrame;

@end

/// Blocks
@interface BDLLivePullViewController ()

/// 浮窗播放器

/// 在浮窗即将显示时调用该 Block
@property (nonatomic, copy, nullable) void (^floatingPlayerViewWillAppear)(BDLLivePullViewController *viewController, BDLFloatingPlayer *floatingPlayer);
/// 在浮窗消失时调用该 Block
@property (nonatomic, copy, nullable) void (^floatingPlayerViewDidDisappear)(BDLLivePullViewController *viewController, BDLFloatingPlayer *floatingPlayer);
/// 在浮窗即将关闭时调用该 Block
@property (nonatomic, copy, nullable) void (^floatingPlayerViewWillClose)(BDLLivePullViewController *viewController, BDLFloatingPlayer *floatingPlayer);
/// 自定义浮窗的初始位置
/// @return 浮窗的初始位置
@property (nonatomic, copy, nullable) CGRect (^frameForFloatingPlayer)(BDLLivePullViewController *viewController, BDLFloatingPlayer *floatingPlayer);

/// 浮窗播放器实现

/// 在观众点击浮窗时调用该 Block
/// @return 是否执行 defaultFloatingPlayerTapAction 
@property (nonatomic, copy, nullable) BOOL (^onFloatingPlayerTapped)(BDLLivePullViewController *viewController, BDLFloatingPlayer *floatingPlayer);
/// 在观众点击浮窗关闭按钮时调用该 Block
/// @return 是否执行 defaultFloatingPlayerCloseAction
@property (nonatomic, copy, nullable) BOOL (^onFloatingPlayerCloseTapped)(BDLLivePullViewController *viewController, BDLFloatingPlayer *floatingPlayer);

@end

BDLLivePullViewControllerConfig

/// BDLLivePullViewController 配置
@interface BDLLivePullViewControllerConfig : NSObject

/// 设置点击评论中的链接后是否在直播间浮层展示跳转内容
/// YES:在直播间浮层展示跳转内容
/// NO:跳转至 Safari
@property (nonatomic, assign) BOOL commentUrlFloatingEnable;

/// 是否禁用竖屏直播间的清屏功能(仅竖屏直播间支持清屏功能)。默认为 NO 不禁用,即支持清屏功能。观众可以右滑清屏或者点击更多(...)图标 > 清屏实现清屏效果。
@property (nonatomic, assign) BOOL disableClearScreen;

/// 是否在 viewDidAppear 时(即完整直播间对应的 view 已经显示时)关闭正在显示的浮窗
@property (nonatomic, assign) BOOL autoCloseFloatingPlayerWhenAppear;

/// 是否显示 InApp 画中画,即浮窗
/// @param status 当前的直播状态。仅在直播状态为预告且设置了预告片、回放、直播时调用该方法
/// @param isClose 是否为关闭当前页面。YES:关闭当前页面,默认显示 InApp 画中画 NO:打开新页面,默认不显示 InApp 画中画
/// @return YES: 显示 InApp 画中画  NO: 不显示 InApp 画中画
@property (nonatomic, copy, nullable) BOOL(^shouldShowInAppPipIfAvailable)(BDLLivePullViewController *viewController, BDLActivityStatus status, BOOL isClose);
/// 在 viewDidDisappear 时,如果 shouldShowInAppPipIfAvailable 属性传入的 isClose 参数值不符合预期,可以使用该属性修正参数值。
@property (nonatomic, copy, nullable) BOOL(^isCloseWhileDisappear)(BDLLivePullViewController *viewController);
/// 自定义背景图片
/// 可自定义除 image 和 hidden 外的所有属性
/// 如需更改 image,可在企业直播控制台中设置
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) __kindof UIImageView * _Nullable (^customizeBackgroundImageView)(BDLLivePullViewController *viewController, UIImageView *imageView);

/// 自定义移动端页头图片
/// 可自定义除 image 和 hidden 外的所有属性
/// 如需更改 image,可在企业直播控制台中设置
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) __kindof UIImageView * _Nullable (^customizeHeaderImageView)(BDLLivePullViewController *viewController, UIImageView *imageView);

/// 自定义横屏模式下的多语言按钮(竖屏模式下的多语言按钮可通过 BDLMoreOptionsViewConfiguration 自定义)
/// 可自定义除 hidden 外的所有属性
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) __kindof UIButton * _Nullable (^customizeMultiLanguageButton)(BDLLivePullViewController *viewController, UIButton *button);

/// 自定义主播账号,详见本文主播账号定制章节
/// 可自定义除 hidden 外的所有属性
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeAccountView)(BDLLivePullViewController *viewController, BDLBusinessAccountView *view);

/// 自定义竖屏模式下的人气显示,详见本文人气显示定制章节
/// 可自定义除 hidden 外的所有属性
/// 可通过 customizeViewConstraints 修改整体的布局,不支持自定义单个属性的布局
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizePopularityView)(BDLLivePullViewController *viewController, BDLPopularityView *view);

/// 自定义直播间关闭按钮
/// 可自定义所有属性
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) __kindof UIButton * _Nullable (^customizeCloseButton)(BDLLivePullViewController *viewController, UIButton *button);

/// 自定义横屏模式下的分享按钮(竖屏模式下的分享按钮可通过 BDLCommentView 自定义)
/// 可自定义除 hidden 外的所有属性
@property (nonatomic, copy, nullable) __kindof UIButton * _Nullable (^customizeShareButton)(BDLLivePullViewController *viewController, UIButton *button);

/// 自定义横屏模式下的顶部直播标题
/// 可自定义除内容外的属性
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) __kindof UILabel * _Nullable (^customizeTitleLabel)(BDLLivePullViewController *viewController, UILabel *label);

/// 自定义页中广告,详见本文页中广告定制章节
/// 可自定义除 hidden 外的所有属性
/// 如需自定义位置或者大小,可在 customizeViewConstraints 中通过 mas_remakeConstrain 设置位置以及大小
@property (nonatomic, copy, nullable) UIView<BDLPageAdViewProtocol> * _Nullable (^customizePageAdView)(BDLLivePullViewController *viewController, BDLPageAdView *view);

/// 自定义播放器,详见本文播放器定制章节
/// 可自定义除 frame 外的所有属性
@property (nonatomic, copy, nullable) void (^customizePlayerView)(BDLLivePullViewController *viewController, BDLPlayerView *view);

/// 自定义播放器容器 view
/// 可自定义除 frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof UIView * _Nullable (^customizePlayerContainerView)(BDLLivePullViewController *viewController, UIView *view);

/// 自定义直播描述,详见本文直播描述定制章节
/// 可自定义除 text、textColor、hidden 外的所有属性
/// 可通过 customizeViewConstraints 修改整体的布局,不支持自定义单个属性的布局
@property (nonatomic, copy, nullable) void (^customizeLiveDescriptionView)(BDLLivePullViewController *viewController, BDLLiveDescriptionView *describeView);

/// 自定义评论 view(竖屏)
/// 可自定义除 hidden 外的所有属性
/// 可通过 customizeViewConstraints 修改整体的布局,不支持自定义单个属性的布局
@property (nonatomic, copy, nullable) void (^customizeCommentView)(BDLLivePullViewController *viewController, BDLCommentView *view);

/// 自定义通知容器 view,可通过该 view 自定义系统消息(抽奖通知和自定义消息)
@property (nonatomic, copy, nullable) void (^customizeNoticeContainerView)(BDLLivePullViewController *viewController, BDLNoticeContainerView *view);

/// 自定义竖屏模式下的评论区(包含输入框)高度
/// 如果返回值小于 0,则使用默认配置,即完整直播间高度的 0.4 倍
@property (nonatomic, copy, nullable) CGFloat (^customizePortraitCommentViewHeight)(BDLLivePullViewController *viewController);

/// 自定义直播间背景颜色
/// 如果您在企业直播控制台设置了移动端背景图,则背景图会覆盖此方法设置的背景颜色
/// 不能设置为 clearColor
@property (nonatomic, copy, nullable) UIColor * _Nullable (^customizeBackgroundColor)(BDLLivePullViewController *viewController);

/// 自定义菜单栏,详见本文菜单栏定制章节
/// 可自定义除 hidden 外的所有属性
/// 可通过 customizeViewConstraints 修改整体的布局,不支持自定义单个属性的布局
@property (nonatomic, copy, nullable) void (^customizeMenuBarView)(BDLLivePullViewController *viewController, BDLMenuBarView *view);

/// 自定义竖屏模式下的互动工具菜单,详见 BDLInteractiveToolView
/// 可自定义所有属性
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeInteractiveToolView 方法替代之
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeInteractiveToolView)(BDLLivePullViewController *viewController, BDLInteractiveToolView *view);

/// 自定义多语言选择弹窗 view,详见本文多语言定制章节
/// 可自定义除 frame 外的所有属性
@property (nonatomic, copy, nullable) void (^customizeMultiLanguageView)(BDLLivePullViewController *viewController, BDLMultiLanguageView *view);

/// 自定义竖屏模式下的更多选项弹窗 view(竖屏直播间点击右下角 … 图标后出现的弹窗),详见本文更多选项弹窗定制章节
/// 可自定义除 frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeMoreOptionsView)(BDLLivePullViewController *viewController, BDLMoreOptionsView *view);

/// 自定义退出清屏按钮。在竖屏直播间开启清屏模式后,会出现退出清屏按钮
/// 可自定义除 hidden 外的所有属性
/// 可通过 customizeViewConstraints 修改整体的布局
@property (nonatomic, copy, nullable) __kindof UIButton * _Nullable (^customizeExitClearModeButton)(BDLLivePullViewController *viewController, UIButton *button);

/// 自定义弹窗 view,详见本文弹窗定制章节
/// 查看置顶评论详情、在当前页面展示 URL 跳转内容都会使用弹窗
/// 可自定义所有属性
@property (nonatomic, copy, nullable) __kindof UIViewController *(^customizeAlertController)(BDLLivePullViewController *viewController, BDLAlertController *controller);

/// 自定义浮窗广告 view,详见 BDLUpperAdView
/// BDLUpperAdView 涉及拖动,您需要设置 view.frame 调整其位置,而非自动布局,但是 BDLUpperAdView 内部和子 view 则采用自动布局
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLFloatingController 中的 customizeUpperAdView 方法替代之
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeUpperAdView)(BDLLivePullViewController *viewController, BDLUpperAdView *view);

/// 自定义浮窗商品卡片 view,详见 BDLFloatingCardView
/// BDLFloatingCardView 涉及拖动,您需要设置 view.frame 调整其位置,而非自动布局,但是 BDLFloatingCardView 内部和子 view 则采用自动布局
/// 可自定义除 hidden 外的所有属性
/// 可通过 customizeViewConstraints 修改整体的布局,不支持自定义单个属性的布局
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLFloatingController 中的 customizeFloatingCardView 方法替代之
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeFloatingCardView)(BDLLivePullViewController *viewController, BDLFloatingCardView *view);

/// 自定义抽奖浮窗 view,详见 BDLFloatingAwardView
/// BDLFloatingAwardView 涉及拖动,您需要设置 view.frame 调整其位置,而非自动布局,但是 BDLFloatingAwardView 内部和子 view 则采用自动布局
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeFloatingView 方法替代之
@property (nonatomic, copy, nullable) __kindof UIView * _Nullable (^customizeFloatingAwardView)(BDLLivePullViewController *viewController, BDLFloatingAwardView *view);

/// 自定义完善中奖信息弹窗 view,详见 BDLAwardContactView
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeAwardContactView 方法替代之
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeAwardContactView)(BDLLivePullViewController *viewController, BDLAwardContactView *view);

/// 自定义抽奖详情 view,详见 BDLAwardDetailsView
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeAwardDetailsView 方法替代之
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupBottomShowViewProtocol> * _Nullable (^customizeAwardDetailsView)(BDLLivePullViewController *viewController, BDLAwardDetailsView *view);

/// 自定义中奖名单 view,详见 BDLAwardWinnersView
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeAwardWinnersView 方法替代之
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeAwardWinnersView)(BDLLivePullViewController *viewController, BDLAwardWinnersView *view);

/// 自定义抽奖结果 view,详见 BDLAwardContactView
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeAwardResultView 方法替代之
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeAwardResultView)(BDLLivePullViewController *viewController, BDLAwardContactView *view);

/// 自定义风险提示 view
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeRiskWarningView)(BDLLivePullViewController *viewController, BDLRiskWarningView *view);

/// 自定义倒计时 view
@property (nonatomic, copy, nullable) __kindof UIView * _Nullable (^customizeCountdownView)(BDLLivePullViewController *viewController, BDLCountdownView *view);

/// 自定义倒计时 view 的布局(是否开启预约会影响倒计时页面的位置)
@property (nonatomic, copy, nullable) void (^customizeCountdownViewConstrains)(BDLLivePullViewController *viewController, UIView *view);

/// 自定义布局
/// 默认实现是通过 Masonry 进行布局,这里您可以通过 mas_remakeConstrain 修改整体的布局
@property (nonatomic, copy, nullable) void (^customizeViewConstraints)(BDLLivePullViewController *viewController);

/// 自定义播放器容器的布局
@property (nonatomic, copy, nullable) void (^customizePlayerContainerViewConstraints)(BDLLivePullViewController *viewController, UIView *view);

/// 自定义页中广告的位置
@property (nonatomic, copy, nullable) void (^customizePageAdViewConstraints)(BDLLivePullViewController *viewController, UIView *view);

/// 自定义昵称输入界面
@property (nonatomic, copy, nullable) __kindof BDLBaseView * (^customizedNickNameInputView)(BDLLivePullViewController *viewController, BDLPopupInputView *view);

/// 自定义互动工具相关 view。详见 BDLInteractiveToolController
@property (nonatomic, copy, nullable) void(^customInteractiveToolController)(BDLLivePullViewController *viewController, BDLInteractiveToolController *interactiveToolController);

/// 自定义浮窗相关 view。详见 BDLFloatingController
@property (nonatomic, copy, nullable) void(^customFloatingController)(BDLLivePullViewController *viewController, BDLFloatingController *floatingController);
@end

BDLLiveRoomConfiguration

/// 直播间配置
@interface BDLLiveRoomConfiguration : NSObject
 
/// 弹窗配置,详见 BDLAlertControllerConfiguration
@property (nonatomic, strong) BDLAlertControllerConfiguration *alertControllerConfig;
/// 昵称输入框配置,详见 BDLPopupInputViewConfiguration
@property (nonatomic, strong) BDLPopupInputViewConfiguration *popupInputViewConfig;
/// 评论区和热门评论配置,详见 BDLCommentViewConfiguration
@property (nonatomic, strong) BDLCommentViewConfiguration *commentViewConfig;
/// 私聊配置,详见 BDLPrivateChatConfiguration
@property (nonatomic, strong) BDLPrivateChatConfiguration *privateChatConfig;
/// 商品卡片配置,详见 BDLCardConfiguration
@property (nonatomic, strong) BDLCardConfiguration *cardConfig;
/// 播放器配置,详见 BDLPlayerConfiguration
@property (nonatomic, strong) BDLPlayerConfiguration *playerConfig;
/// 独立播放器配置,详见 BDLBasePlayerConfiguration
@property (nonatomic, strong) BDLBasePlayerConfiguration *basePlayerConfig;
/// 图文菜单配置,详见 BDLImageTextViewConfiguration
@property (nonatomic, strong) BDLImageTextViewConfiguration *imageTextViewConfig;
/// 互动工具菜单配置,详见 BDLInteractiveToolConfiguration
@property (nonatomic, strong) BDLInteractiveToolConfiguration *interactiveToolConfig;
/// 菜单栏配置,详见 BDLMenuBarConfiguration
@property (nonatomic, strong) BDLMenuBarConfiguration *menuBarConfig;
/// 菜单栏容器 view 配置,详见 BDLMenuViewConfiguration
@property (nonatomic, strong) BDLMenuViewConfiguration *menuViewConfig;
/// 浮窗商品卡片配置,详见 BDLFloatingCardConfiguration
@property (nonatomic, strong) BDLFloatingCardConfiguration *floatingCardConfig;
/// 页中广告配置,详见 BDLPageAdViewConfiguration
@property (nonatomic, strong) BDLPageAdViewConfiguration *pageAdViewConfig;
/// 更多选项弹窗配置,详见 BDLMoreOptionsViewConfiguration
@property (nonatomic, strong) BDLMoreOptionsViewConfiguration *moreOptionsViewConfig;
/// 抽奖配置,详见 BDLAwardConfiguration
@property (nonatomic, strong) BDLAwardConfiguration *awardConfig;
 
@end

人气显示定制

BDLPopularityView

/// 人气显示 view,对应企业直播控制台的人气显示功能
@interface BDLPopularityView : BDLBaseView
/// 人气图标
/// 可自定义除位置外的所有属性
@property (nonatomic, strong) UIImageView *imageView;
/// 人气标签
/// 可自定义除 text、位置外的所有属性
@property (nonatomic, strong) UILabel *label;

/// 初始化
/// @param isPortrait 是否为竖屏
- (instancetype)initWithPortrait:(BOOL)isPortrait;

@end

直播描述定制

BDLLiveDescriptionView

/// 直播描述 view
@interface BDLLiveDescriptionView : BDLBaseView 

/// 直播描述文字 view
@property (nonatomic, strong, readonly) BDLScrollTextView *scrollTextView;
/// 箭头图标
@property (nonatomic, strong, readonly) UIButton *arrowButton;
/// 箭头图标点击回调
@property (nonatomic, copy) void (^arrowButtonClickedBlock)(BDLLiveDescriptionView *view);
 
@end

BDLScrollTextView

/// 滚动方向
typedef NS_ENUM(NSInteger, BDLScrollDirection) {
    BDLScrollDirectionRight,  ///< 右
    BDLScrollDirectionLeft  ///< 左
};

/// 直播描述文字 view
@interface BDLScrollTextView : UIView

/// 滚动方向
@property (nonatomic, assign) BDLScrollDirection scrollDirection;
/// 滚动速度,即每秒滚动的 pixel 数量,默认为 30
@property (nonatomic, assign) float scrollSpeed;
/// 两次滚动之间的停顿间隔,单位为秒,默认为 0.0,即连续滚动
@property (nonatomic, assign) NSTimeInterval pauseInterval;
/// Label 左侧空白,单位为 pixel,默认为 20
@property (nonatomic, assign) NSInteger labelSpacing;
/// 滚动时的动画选项
@property (nonatomic, assign) UIViewAnimationOptions animationOptions;
/// 是否正在滚动
@property (nonatomic, assign, readonly) BOOL scrolling;
/// 渐变遮罩的长度,单位为 pixel
@property (nonatomic, assign) CGFloat fadeLength;
/// 字体
@property (nonatomic, strong) UIFont *font;
/// 文字
@property (nonatomic, copy, nullable) NSString *text;
/// 富文本
@property (nonatomic, copy, nullable) NSAttributedString *attributedText;
/// 文字颜色
@property (nonatomic, strong) UIColor *textColor;
/// 文本对齐方式,不自动滚动的时候生效
@property (nonatomic, assign) NSTextAlignment textAlignment; 
/// 阴影颜色
@property (nonatomic, strong, nullable) UIColor *shadowColor;
/// 阴影偏移量
@property (nonatomic, assign) CGSize shadowOffset;

/// 刷新 label
- (void)refreshLabels;

/// 设置文本
/// @param refresh 是否需要刷新
- (void)setText:(nullable NSString *)text refreshLabels:(BOOL)refresh;

/// 设置富文本
/// @param refresh 是否需要刷新
- (void)setAttributedText:(nullable NSAttributedString *)theText refreshLabels:(BOOL)refresh;

/// 滚动 label
- (void)scrollLabelIfNeeded;

/// 监听进入前台的通知(UIApplicationDidBecomeActiveNotification 和 UIApplicationWillEnterForegroundNotification),从而刷新并开始滚动 label
- (void)observeApplicationNotifications;

@end

多语言定制

BDLMultiLanguageView

/// 多语言选择弹窗 view 的代理方法
@protocol BDLMultiLanguageViewDelegate <NSObject>
/// 多语言选择弹窗隐藏的回调
/// @param view self,即当前隐藏的 BDLMultiLanguageView 实例
/// @param superview self.superview,即当前实例的 superView
- (void)multiLanguageView:(BDLMultiLanguageView *)view removeFromSuperview:(UIView *)superview;
@end

/// 多语言选择弹窗 view
@interface BDLMultiLanguageView : BDLBaseView
/// 代理方法
@property (nonatomic, weak) id<BDLMultiLanguageViewDelegate> delegate;
/// 语言列表的容器 view
/// 可自定义除 hidden 外的所有属性
/// 如果您将 hidden 设为 YES,会出现空白的弹窗
@property (nonatomic, strong) UITableView *tableView;
/// 标题 label
/// 可自定义除 text、frame 外的所有属性
@property (nonatomic, strong) UILabel *titleLabel;
/// 取消按钮
/// 可自定义除 normalText、frame 外的所有属性
@property (nonatomic, strong) UIButton *cancelButton;
/// 显示多语言选择弹窗 view
- (void)show;
/// 隐藏多语言选择弹窗 view
- (void)hide;

@end

评论/私聊定制

BDLCommentBaseView

/// 评论、热门评论以及私聊共同的基类
@interface BDLCommentBaseView : BDLBaseView
/// 初始化方法
/// @param isPortrait 是否为竖屏
- (instancetype)initWithPortrait:(BOOL)isPortrait;
/// 是否为竖屏
@property (nonatomic, assign, readonly) BOOL isPortrait;
/// 基类配置,详见 BDLCommentBaseConfiguration
@property (nonatomic, strong, readonly) BDLCommentBaseConfiguration *config;
/// 是否开启评论翻译
@property (nonatomic, assign, readonly) BOOL isCommentTranslateEnable;
/// 当前所有支持的语言类型
@property (nonatomic, copy, readonly) NSArray *langTypes;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType langType;
/// 评论区无评论时的 view,详见 BDLNoCommentView
/// 可自定义除 frame、hidden 外的所有属性
@property (nonatomic, strong) BDLNoCommentView *noCommentView;
/// 更新评论区无评论时的占位图
- (void)refreshNoCommentView;

@end

BDLCommentInputBaseView

/// 评论和私聊共同的父控件
@interface BDLCommentInputBaseView : BDLCommentBaseView 

/// 评论输入框
/// 可自定义除 attributedPlaceholder、backgroundColor、textColor、layer.cornerRadius、frame 外的属性
/// 可通过 BDLCommentBaseConfiguration.inputBoxPrompt 自定义 placeHolder
@property (nonatomic, strong, readonly) UITextField *textField;

///  弹窗显示的父 view。SDK 内部默认实现了昵称输入框等弹窗效果,弹窗会加到 popupSuperView 上面 
@property  (nonatomic,  weak)  UIView  *popupSuperView;

/// 新消息提示 view
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, strong, readonly) UIView *commentPromptView;
/// 新消息提示 label
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, strong, readonly) UILabel *commentPromptLabel;
/// 自定义评论输入框
@property (nonatomic, copy, nullable) void (^customizeTextField)(__kindof BDLCommentInputBaseView *commentView, UITextField *textField, BOOL willEdit);

/// 重置评论输入框 /// @param willEdit 是否为编辑状态
- (void)resetTextField:(BOOL)willEdit;

@end

BDLCommentView

/// 评论区 view
@interface BDLCommentView : BDLCommentInputBaseView 

/// 竖屏模式下的商品卡片(购物车)按钮
/// 可自定义除 hidden、frame 外的所有属性
/// 如需自定义 image,可通过 BDLLiveEngine.sharedInstance.liveRoomConfiguration.commentViewConfig.shoppingCardButtonImage 设置。详见 BDLCommentViewConfiguration 
@property (nonatomic, strong, readonly) UIButton *shoppingCardButton;
/// 竖屏模式下的互动工具按钮
/// 可自定义除 hidden、frame 外的所有属性
/// 如需自定义 image,可通过 BDLLiveEngine.sharedInstance.liveRoomConfiguration.commentViewConfig.interactiveButtonImage 设置。详见 BDLCommentViewConfiguration 
@property (nonatomic, strong, readonly) UIButton *interactiveButton;
/// 竖屏模式下的私聊互动按钮
/// 可自定义除 hidden、frame 外的所有属性
/// 如需自定义 image,可通过 BDLLiveEngine.sharedInstance.liveRoomConfiguration.commentViewConfig.privateChatButtonImage 设置。详见 BDLCommentViewConfiguration
@property (nonatomic, strong, readonly) UIButton *privateChatButton;

/// 竖屏模式下的内嵌链接按钮
/// 可自定义除 hidden、frame 外的所有属性
/// 如需自定义 image,可通过 BDLLiveEngine.sharedInstance.liveRoomConfiguration.commentViewConfig.embeddedUrlButtonImage 设置。详见 BDLCommentViewConfiguration
@property (nonatomic, strong, readonly) UIButton *embeddedUrlButton;

/// 竖屏模式下的更多选项按钮
/// 可自定义除 hidden、frame 外的所有属性
/// 如需自定义 image,可通过 BDLLiveEngine.sharedInstance.liveRoomConfiguration.commentViewConfig.moreOptionsButtonImage 设置。详见 BDLCommentViewConfiguration
@property (nonatomic, strong, readonly) UIButton *moreOptionsButton;
/// 竖屏模式下的互动工具未读数量 label
@property (nonatomic, strong, readonly) UILabel *interactiveToolUnreadLabel;
/// 进场消息 view
@property (nonatomic, strong, readonly, nullable) UIView<BDLJoinRoomNoticeViewProtocol> *joinRoomNoticeView;
/// 自定义进场消息 view
@property (nonatomic, copy)  __kindof UIView * (^customizeJoinRoomNoticeView)(BDLCommentView *view, BDLJoinRoomNoticeView *noticeView);

/// 自定义 BDLMoreOptionsController
/// @param controller BDLMoreOptionsController,实现了更多选项弹窗内多语言切换、清屏、分享、清晰度选择按钮的显示与隐藏逻辑
@property (nonatomic, copy) void (^customizeMoreOptionsController)(BDLCommentView *view, BDLMoreOptionsController *controller);

/// 置顶评论点击回调
@property (nonatomic, copy, nullable) void (^topCommentClickBlock)(BDLCommentView *view, BDLCommentModel *comment);
/// 互动工具按钮点击回调
@property (nonatomic, copy, nullable) void (^interactiveToolClickBlock)(BDLCommentView *view);
/// 商品卡片按钮点击回调
@property (nonatomic, copy, nullable) void (^shoppingCardClickBlock)(BDLCommentView *view);
/// 更多选项按钮点击回调
@property (nonatomic, copy, nullable) void (^moreOptionsClickBlock)(BDLCommentView *view);
/// 私聊互动按钮点击回调
@property (nonatomic, copy, nullable) void (^privateChatClickBlock)(BDLCommentView *view);
/// 内嵌链接按钮点击回调
@property (nonatomic, copy, nullable) void (^embeddedUrlClickBlock)(BDLCommentView *view);
/// 直播间点赞按钮点击回调
/// @return 是否显示点击动画
@property (nonatomic, copy, nullable) BOOL (^likeClickBlock)(BDLCommentView *view);
/// 置顶评论昵称点击回调
@property (nonatomic, copy, nullable) void (^topCommentNicknameClickBlock)(BDLCommentView *view, BDLCommentModel *comment);
/// 置顶图片评论点击回调
@property (nonatomic, copy, nullable) void (^topCommentImageClickBlock)(BDLCommentView *view, BDLCommentModel *comment);
/// 评论中的链接点击回调
@property (nonatomic, copy, nullable) void (^urlClickBlock)(__kindof BDLCommentBaseView *commentView, BDLCommentModel *comment, NSURL *url);
/// 昵称点击回调
@property (nonatomic, copy, nullable) void (^nicknameClickBlock)(__kindof BDLCommentBaseView *commentView, BDLCommentModel *comment);
/// 图片评论点击回调
@property (nonatomic, copy, nullable) void (^commentImageClickBlock)(__kindof BDLCommentBaseView *commentView, BDLCommentModel *comment);
@end

BDLPrivateChatView

/// 私聊 view
@interface BDLPrivateChatView : BDLCommentInputBaseView

/// 评论中的链接点击回调
@property (nonatomic, copy, nullable) void (^urlClickBlock)(__kindof BDLPrivateChatView *privateChatView, BDLPrivateChatMessageModel *privateChatMessage, NSURL *url);
/// 昵称点击回调
@property (nonatomic, copy, nullable) void (^nicknameClickBlock)(__kindof BDLPrivateChatView *privateChatView, BDLPrivateChatMessageModel *privateChatMessage);

@end

BDLNoCommentView

/// 评论区无评论时的 view
@interface BDLNoCommentView : BDLBaseView

/// imageView
/// 可自定义除 frame 或 image 外的所有属性
/// 如需自定义 image,可通过 BDLCommentBaseConfiguration.noCommentImage 设置
@property (nonatomic, strong) UIImageView *imageView;
/// 文字
/// 可自定义除 text 或 frame 外的所有属性
@property (nonatomic, strong) UILabel *titleLabel;

@end

BDLHotCommentView

/// 热门评论 view,继承自 BDLCommentBaseView
@interface BDLHotCommentView : BDLCommentBaseView

/// 评论中的链接点击回调
@property (nonatomic, copy, nullable) void (^urlClickBlock)(__kindof BDLCommentBaseView *commentView, BDLCommentModel *comment, NSURL *url);
/// 昵称点击回调
@property (nonatomic, copy, nullable) void (^nicknameClickBlock)(__kindof BDLCommentBaseView *commentView, BDLCommentModel *comment);
/// 图片评论点击回调
@property (nonatomic, copy, nullable) void (^commentImageClickBlock)(__kindof BDLCommentBaseView *commentView, BDLCommentModel *comment);

@end

BDLCommentBaseConfiguration

/// 评论、热门评论和私聊的基类配置
@interface BDLCommentBaseConfiguration : BDLRTBaseConfiguration

/// 横屏模式下是否显示头像
@property (nonatomic, assign) BOOL landscapeShouldShowAvatar;
/// 竖屏模式下是否显示头像
@property (nonatomic, assign) BOOL portraitShouldShowAvatar;
/// 观众的默认头像
@property (nonatomic, strong) UIImage *defaultAvatar;
/// 主持人默认头像
@property (nonatomic, strong) UIImage *defaultHostAvatar;
/// 发言间隔
@property (nonatomic, assign) NSTimeInterval voiceInterval;
/// 评论字体
@property (nonatomic, strong) UIFont *commentFont;
/// 昵称字体
@property (nonatomic, strong) UIFont *nickNameFont;
/// 主持人评论文字颜色
@property (nonatomic, strong) UIColor *hostCommentColor;
/// 主持人标签字体
@property (nonatomic, strong) UIFont *hostTagFont;
/// 昵称文字颜色
@property (nonatomic, strong) UIColor *nickNameColor;
/// 评论文字颜色
@property (nonatomic, strong) UIColor *commentColor;
/// 评论中可交互链接的颜色
@property (nonatomic, strong) UIColor *linkColor;
/// 背景颜色
@property (nonatomic, strong) UIColor *backgroundColor;
/// 输入框提示文字
@property (nonatomic, copy) NSString *inputBoxPrompt;
/// 发送频繁的提示文字
@property (nonatomic, copy) NSString *justSendPrompt;
/// 发送频繁提示的字体
@property (nonatomic, strong) UIFont *justSendFont;
/// 无评论时的提示图片
@property (nonatomic, strong) UIImage *noCommentImage;
/// 输入框左侧图标
@property (nonatomic, strong) UIImage *inputTextIconImage;
/// 是否允许点击观众评论中的链接
@property (nonatomic, assign) BOOL enableAudienceURLTap;

/// 评论展示行数
@property (nonatomic, assign) NSUInteger rowsOfComment;
/// 每次拉取评论条数
@property (nonatomic, assign) NSUInteger singlePullCount;
/// 最大拉取评论条数
@property (nonatomic, assign) NSUInteger pullMaxNumber;
/// 更新默认值
/// @param  isPortrait 是否为竖屏
- (void)updateDefaultValue:(BOOL)isPortrait;

@end

BDLCommentViewConfiguration

/// 评论区和热门评论配置
@interface BDLCommentViewConfiguration : BDLCommentBaseConfiguration

/// 评论未点赞状态的点赞按钮
@property (nonatomic, strong) UIImage *likeIconImage;
/// 评论已点赞状态的点赞按钮
@property (nonatomic, strong) UIImage *likedIconImage;
/// 竖屏模式下的商品卡片(购物车)按钮图片
@property (nonatomic, strong) UIImage *shoppingCardButtonImage;
/// 竖屏模式下的互动工具按钮图片
@property (nonatomic, strong) UIImage *interactiveButtonImage;
/// 竖屏模式下的私聊互动按钮图片
@property (nonatomic, strong) UIImage *privateChatButtonImage;
/// 竖屏模式下的内嵌链接按钮图片
@property (nonatomic, strong) UIImage *embeddedUrlButtonImage;
/// 竖屏模式下的更多选项按钮图片
@property (nonatomic, strong) UIImage *moreOptionsButtonImage;
/// 欢迎语文字颜色
@property (nonatomic, strong) UIColor *welcomeTextColor;
/// 置顶评论标签颜色
@property (nonatomic, strong) UIColor *topCommentTagColor;
/// 置顶评论字体
@property (nonatomic, strong) UIFont *topCommentFont;
/// 置顶评论左右是否需要间距
@property (nonatomic, assign) BOOL topCommentNeedMargin;
/// 置顶评论展示行数
@property (nonatomic, assign) NSUInteger rowsOfTopComment;
/// 置顶标签字体
@property (nonatomic, strong) UIFont *topTagFont;
/// 是否允许观众发送评论
@property (nonatomic, assign) BOOL isSendCommentEnable;
/// 直播间点赞按钮图片
@property (nonatomic, strong) UIImage *thumbUpButtonImage;
/// 直播间点赞按钮被点击时的漂浮动画图片
@property (nonatomic, strong) NSArray<UIImage *> *thumbUpImages;

@end

BDLPrivateChatConfiguration

/// 私聊配置
@interface BDLPrivateChatConfiguration : BDLCommentBaseConfiguration

@end

BDLTopCommentView

/// 置顶评论 view 的代理方法
@protocol BDLTopCommentViewDelegate <NSObject>

@optional
///  在观众点击评论昵称时调用该方法
- (void)topCommentView:(BDLTopCommentView *)view didClickNicknameWithComment:(BDLCommentModel *)comment;

/// 在观众点击图片评论时调用该方法
/// @param view 置顶评论 view
/// @param comment 点击的图片评论
- (void)topCommentView:(BDLTopCommentView *)view didClickImage:(BDLCommentModel *)comment;
@end
/// 置顶评论 view
@interface BDLTopCommentView : UIView
/// 代理方法
@property (nonatomic, weak) id<BDLTopCommentViewDelegate> delegate;
/// 当前 view 对应的评论
@property (nonatomic, weak, readonly) BDLCommentModel *comment;

/// 根据 comment 更新 view
/// @param comment 需要显示的评论
/// @param config 评论的配置
/// @param isPortrait 是否为竖屏
/// @param isCommentTranslateEnable 是否开启评论翻译
/// @param langType 当前的语言类型,详见 BDLLanguageType
/// @param langTypes 当前所有支持的语言类型
- (void)updateViewWithComment:(BDLCommentModel *)comment
                       config:(BDLCommentViewConfiguration *)config
                   isPortrait:(BOOL)isPortrait
     isCommentTranslateEnable:(BOOL)isCommentTranslateEnable
                     langType:(BDLLanguageType)langType
                    langTypes:(NSArray *)langTypes;

/// 是否处理手势。如果返回 NO,则 commentView 不再处理 topCommentView 的点击手势
- (BOOL)shouldHandleGestureRecognizerWithTouch:(UITouch *)touch;

@end

菜单栏定制

BDLMenuBarView

/// 菜单栏 view
@interface BDLMenuBarView : BDLBaseView 
/// 菜单栏配置,详见 BDLMenuBarConfiguration
@property (nonatomic, strong, readonly) BDLMenuBarConfiguration *config;
/// 菜单栏容器 view,用于实现菜单栏的左右滑动和切换,详见 BDLMenuView
@property (nonatomic, strong) BDLMenuView *menuView;
/// 菜单栏中的评论 view(横屏),详见 BDLCommentView
@property (nonatomic, strong, nullable) BDLCommentView *commentView;
/// 热门评论 view(横屏),详见 BDLHotCommentView
@property (nonatomic, strong, nullable) BDLHotCommentView *hotCommentView;
/// 私聊 view, 详见 BDLPrivateChatView
@property (nonatomic, strong, nullable) BDLPrivateChatView *privateChatView;

/// 自定义内嵌链接 view
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof UIView * _Nullable (^customizeEmbeddedUrlWebView)(BDLMenuBarView *view, WKWebView *webView);
/// 自定义菜单栏中的评论 view(横屏)
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, copy, nullable) void (^customizeCommentView)(BDLMenuBarView *view, BDLCommentView *commentView);
/// 自定义热门评论 view(横屏),详见 BDLHotCommentView
/// 如果您隐藏了 commentView,则热门评论 view 也不会显示
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeHotCommentView)(BDLMenuBarView *view, BDLHotCommentView *hotCommentView);
/// 自定义图文菜单 view(横屏),详见本文图文菜单定制章节
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeImageTextView)(BDLMenuBarView *view, BDLImageTextView *imageTextView);
/// 自定义商品卡片 view,详见本文商品卡片定制章节
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeCardView)(BDLMenuBarView *view, BDLCardView *cardView);
/// 自定义互动工具菜单 view(横屏),详见 BDLInteractiveToolView
/// 可自定义除 hidden、frame 外的所有属性
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 customizeInteractiveToolView 方法替代之
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeInteractiveToolView)(BDLMenuBarView *view, BDLInteractiveToolView *interactiveToolView);
/// 自定义私聊 view,详见 BDLPrivateChatView
/// 可自定义除 hidden、frame 外的所有属性
@property (nonatomic, copy, nullable) void (^customizePrivateChatView)(BDLMenuBarView *view, BDLPrivateChatView *privateChatView);
/// 自定义置顶评论的点击详情弹窗,详见本文弹窗定制章节
/// 可自定义除 frame 外的所有属性
@property (nonatomic, copy, nullable) __kindof UIViewController * _Nullable (^customizeAlertController)(BDLMenuBarView *view, BDLAlertController *controller);
/// 商品卡片点击回调
/// @param urlStr 点击的 url
/// @param enableFloating 是否浮层显示
@property (nonatomic, copy, nullable) void (^cardViewTappedBlock)(NSString * _Nullable urlStr, BOOL enableFloating);
/// 商品卡片搜索回调
@property (nonatomic, copy, nullable) void (^onCardSearchClickBlock)(BDLMenuBarView *menuBarView, BDLMenuModel *menu);
/// 互动工具中 URL 的点击回调
/// @param url 点击的 URL
/// @param enableFloating 是否浮层显示
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolController 中的 interactiveToolViewURLTappedBlock 方法替代之
@property (nonatomic, copy, nullable) void (^interactiveToolViewURLTappedBlock)(NSURL * _Nullable url, BOOL enableFloating);
/// 抽奖点击回调
/// @param model 抽奖信息
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolView 中的 onContextClickBlock 方法替代之
@property (nonatomic, copy, nullable) void (^interactiveToolAwardClickedBlock)(BDLInteractiveToolView *view, BDLInteractiveAwardModel *model);

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param filterOption 菜单过滤选项,只显示包含的菜单类型。详见 BDLMenuFilterOption
- (instancetype)initWithPortrait:(BOOL)isPortrait filterOption:(BDLMenuFilterOption)filterOption;

/// 获取初始化传进来的 filterOption
@property (nonatomic, assign, readonly) BDLMenuFilterOption filterOption;
/// 选中的菜单发生变化时调用该 Block
/// @param view 当前的 BDLMenuBarView 实例
/// @param index 当前选中菜单的数组下标,index 从 0 开始计数
@property (nonatomic, copy, nullable) void(^indexDidChangeBlock)(BDLMenuBarView *view, NSUInteger index);

@end

/// 菜单过滤选项
typedef NS_OPTIONS(NSUInteger, BDLMenuFilterOption) {
    /// 聊天互动菜单
    BDLMenuFilterOptionComment = 1 << 0,
    /// 热门评论菜单
    BDLMenuFilterOptionHotComment = 1 << 1,
    /// 图文菜单
    BDLMenuFilterOptionImageText = 1 << 2,
    /// 商品卡片菜单
    BDLMenuFilterOptionCard = 1 << 3,
    /// 互动工具菜单
    BDLMenuFilterOptionInteractiveTool = 1 << 4,
    /// 私聊互动菜单
    BDLMenuFilterOptionPrivateChat = 1 << 5,
    /// 内嵌链接菜单
    BDLMenuFilterOptionEmbeddedUrl = BDLMenuFilterOptionPrivateChat << 1,
    BDLMenuFilterOptionAll = NSUIntegerMax,
};

BDLMenuView

/// 菜单栏容器 view,用于实现菜单栏的左右滑动和切换
@interface BDLMenuView : BDLBaseView
/// 菜单栏容器 view 配置,详见 BDLMenuViewConfiguration
@property (nonatomic, strong, readonly) BDLMenuViewConfiguration *config;
/// 菜单栏标题区域的背景 view
/// 可自定义所有属性
@property (nonatomic, strong, readonly) UIView *titleBackgroundView;
/// 菜单栏标题区域可滑动的 scrollView
/// 可自定义除 contentSize 外的所有属性
@property (nonatomic, strong, readonly) UIScrollView *titleScrollView;
/// 当前选中标题底部的指示线
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly) UIView *titleBottomLine;
/// 菜单栏标题下方内容区域可滑动的 scrollView
/// 可自定义除 contentSize 外的所有属性
@property (nonatomic, strong, readonly) UIScrollView *contentScrollView;

/// 菜单栏容器 view 距离屏幕右侧的距离。单位为 pixel。如果有线路选择入口或回放视频列表入口,默认为 120,否则默认为 0
@property (nonatomic, assign) CGFloat titleRightMargin;
/// 更新方法
/// @param titleArray 标题的数组
/// @param contentViewArray 标题下方内容 view 的数组
/// @param normalColor 标题默认颜色
/// @param selectedColor 标题选中的颜色
/// @param selectIndex 默认选中的数组下标
- (void)updateWithTitleArray:(NSArray *)titleArray
            contentViewArray:(NSArray<__kindof UIView *> *)contentViewArray
                 normalColor:(UIColor *)normalColor
               selectedColor:(UIColor *)selectedColor
                 selectIndex:(NSInteger)selectIndex;
/// 当前选中数组下标变化的回调
@property (nonatomic, copy, nullable) void(^indexDidChangeBlock)(BDLMenuView *view, NSUInteger index);
/// 当前选中的数组下标
- (NSUInteger)currentIndex;
/// 当前显示的内容 view
- (UIView *)currentContentView;
/// 在旋转屏幕时调用该方法,用于修正 contentScrollView 的 contentOffSet 值
- (void)willRotate;
/// 在屏幕已经旋转完成后调用该方法
- (void)didRotate;
@end

BDLMenuViewConfiguration

/// 菜单栏容器 view 配置
@interface BDLMenuViewConfiguration : BDLRTBaseConfiguration

/// 标题字体
@property (nonatomic, strong) UIFont *titleFont;
/// 标题选中后底部的指示线宽度
@property (nonatomic, assign) CGFloat titleLineWidth;

@end

BDLMenuBarConfiguration

/// 菜单栏配置
@interface BDLMenuBarConfiguration : BDLBaseConfiguration
/// 标题默认颜色
@property (nonatomic, strong) UIColor *tabColor;
/// 标题选中的颜色
@property (nonatomic, strong) UIColor *selectedTabColor;

@end

商品卡片定制

BDLCardView

/// 商品卡片 view
@interface BDLCardView : BDLBaseView <BDLLanguageService, BDLPullStreamUrlService, BDLBasicService>
/// 商品卡片配置,详见 BDLCardConfiguration
@property (nonatomic, strong, readonly) BDLCardConfiguration *config;
/// “共 x 件商品”文案 label
/// 可自定义除 text、frame 外的所有属性
@property (nonatomic, strong, readonly) UILabel *totalCountLabel;
/// 商品卡片搜索按钮
/// 可自定义除文字内容外的所有属性
@property (nonatomic, strong, readonly) UIButton *searchButton;
/// 商品显示的容器 tableView
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly) UITableView *tableView;
/// 商品卡片选中回调
/// @param urlStr 商品卡片 URL
/// @param enableFloating 是否浮层展示商品详情页
@property (nonatomic, copy, nullable) void (^viewTappedBlock)(NSString * _Nullable urlStr, BOOL enableFloating);
/// 商品卡片搜索回调
@property (nonatomic, copy) void(^onSearchButtonClickBlock)(BDLCardView *cardView);
@end

BDLCardConfiguration

/// 商品卡片配置
@interface BDLCardConfiguration : BDLRTBaseConfiguration
/// 标题字体
@property (nonatomic, strong) UIFont *cardTitleFont;
/// 标题颜色
@property (nonatomic, strong) UIColor *cardTitleColor;
/// 划线文字字体
@property (nonatomic, strong) UIFont *strikeThroughFont;
/// 划线文字颜色
@property (nonatomic, strong) UIColor *strikeThroughTextColor;
/// 划线 style
@property (nonatomic, assign) NSUnderlineStyle strikeThroughStyle;
/// 高亮字体
@property (nonatomic, strong) UIFont *cardHighLightFont;
/// 高亮颜色
@property (nonatomic, strong) UIColor *cardHighLightColor;
/// cell 颜色
@property (nonatomic, strong) UIColor *cardCellColor;
/// 是否显示商品卡片序号
@property (nonatomic, assign) BOOL itemIndexEnable;
/// 是否开启商品直达链接
/// - YES: 如果您在企业直播控制台设置了直达链接,则优先读取直达链接
/// - NO: 读取跳转链接
@property (nonatomic, assign) BOOL enableDirectUrl;

@end

浮窗定制

BDLFloatingController

@interface BDLFloatingController : NSObject <
BDLPageUpperAdService
, BDLProductService
, BDLMenuService
>

/// 插入直播间的位置
typedef NS_ENUM(NSInteger, BDLFloatingControllerInsertPosition) {
    BDLFloatingControllerInsertPositionNone, /// 不参与 view 的展示顺序重新排列,展示位置由 view 的配置决定
    BDLFloatingControllerInsertPositionLeftTop, /// 在直播间左上角显示,与竖屏直播间的互动工具浮窗联动。根据 view.tag 重新排列 view 的展示顺序,tag 值越小,展示位置越靠上
    BDLFloatingControllerInsertPositionRightBottom,  /// 在直播间右下角显示,与浮窗商品卡片、浮窗广告,以及横屏直播间的互动工具浮窗联动。根据 view.tag 重新排列 view 的展示顺序,tag 值越小,展示位置越靠上
};

/// 拖拽方式
typedef NS_ENUM(NSUInteger, BDLDraggingMode) {
    BDLDraggingModeDisabled, /// 不能拖拽
    BDLDraggingModeNormal, /// 正常拖拽
    BDLDraggingModeRevert, /// 释放后还原
    BDLDraggingModePullOver, /// 自动靠边,只会靠左右两边
    BDLDraggingModeAdsorb, /// 靠边时自动吸附边缘,可吸附四周
};

/// 显示浮窗的 view
@property (nonatomic, strong, readonly) UIView *superview;
/// 隐藏所有浮窗
/// YES:隐藏所有浮窗
/// NO:显示所有应显示的浮窗
@property (nonatomic, assign, readonly) BOOL hideAllFloatingView;
/// 所有在展示的非互动工具浮窗
/// 该属性自 1.32.0 版本开始不再支持使用
@property (nonatomic, copy, readonly) NSArray<UIView *> *allShownNonInterToolViewArray;
/// 浮窗广告 view
@property (nonatomic, strong, readonly) UIView *upperAdView;
/// 浮窗商品卡片 view
@property (nonatomic, strong, readonly) UIView *floatingCardView;
/// 互动工具浮窗 view 的容器 view
@property (nonatomic, strong, readonly) UIStackView *floatingInteractiveToolContainerView;

/// 浮窗需要打开 URL 时调用该 block
/// @param url 需要打开的 URL
/// @param isFloatingEnable 是否浮层显示
@property (nonatomic, copy, nullable) void(^openUrlBlock)(BDLFloatingController *floatingController, NSURL *url, BOOL isFloatingEnable);

/// 插入自定义浮窗 view
/// @param view 自定义的浮窗 view,可插入直播间的指定位置。按照 view.tag 依次从上到下排列(tag 值越小,展示位置越靠上),不会影响 view 的层级结构。
/// 注意:您可以通过 self.xxx.tag 获取已有 view 的 tag 值。例如通过 self.upperAdView.tag 获取浮窗广告 view 的 tag 值
/// @param position 插入直播间的位置
/// @param dragMode 拖拽方式
- (void)insertFloatingView:(UIView *)view
                  position:(BDLFloatingControllerInsertPosition)position
                  dragMode:(BDLDraggingMode)dragMode;

/// 移除插入的自定义浮窗 view
- (void)removeInsertedFloatingView:(UIView *)view;

/// 自定义浮窗广告 view。BDLUpperAdView 涉及拖动,请设置 view.frame 调整其位置,而非自动布局,但 BDLUpperAdView 内部和子 view 则采用自动布局
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeUpperAdView)(BDLFloatingController *floatingController, BDLUpperAdView *view);
/// 自定义浮窗商品卡片 view。BDLFloatingCardView 涉及拖动,请设置 view.frame 调整其位置,而非自动布局,但 BDLFloatingCardView 内部和子 view 则采用自动布局
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeFloatingCardView)(BDLFloatingController *floatingController, BDLFloatingCardView *view);
/// 自定义互动工具浮窗 view 的容器 view。interactiveToolContainerView 涉及拖动,请设置 view.frame 调整其位置,而非自动布局,但 interactiveToolContainerView 内部和子 view 则采用自动布局
@property (nonatomic, copy, nullable) __kindof UIStackView * _Nullable (^customizeInteractiveToolContainerView)(BDLFloatingController *floatingController, UIStackView *view);

@end

/// 连麦入口 view
@property (nonatomic, strong, readonly, nullable) UIView *audienceLinkEntranceView;
/// 连麦中摄像头小窗 view
@property (nonatomic, strong, readonly, nullable) UIView *audienceLinkPreviewView;

浮窗商品卡片定制

BDLFloatingCardView

/// 浮窗商品卡片 view
@interface BDLFloatingCardView : BDLBaseView <BDLProductService, BDLCardExplainService>
/// 浮窗商品卡片配置,详见 BDLFloatingCardConfiguration
@property (nonatomic, strong, readonly) BDLFloatingCardConfiguration *config;

/// 容器 view,用于显示白色边框以及圆角
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly) UIView *containerView;

/// 标题文字 label
/// 可自定义除 text、位置外的所有属性
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// 高亮文字背景 view
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly) UIView *highLightBgView;
/// 高亮文字 label
/// 可自定义除 text、位置外的所有属性
/// 如需自定义 text,可通过 BDLLiveEngine.sharedInstance.liveRoomConfiguration.floatingCardConfig.highLightString 设置
@property (nonatomic, strong, readonly) UILabel *highLightLabel;
/// 介绍图
/// 可自定义除 image、位置外的所有属性
@property (nonatomic, strong, readonly) UIImageView *imageView;
/// 关闭按钮
/// 可自定义除位置外的所有属性
@property (nonatomic, strong, readonly) UIButton *closeButton;
/// GO 的 imageview
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly) UIImageView *goImageView;
/// 浮窗商品卡片点击回调
/// @param urlStr 对应的 URL
/// @param enableFloating 是否在企业直播控制台开启浮层展示
@property (nonatomic, copy, nullable) void (^viewTappedBlock)(NSString * _Nullable urlStr, BOOL enableFloating);
/// 关闭按钮点击回调
@property (nonatomic, copy, nullable) void (^closeButtonClickedBlock)(void);

@end

BDLFloatingCardConfiguration

/// 浮窗商品卡片配置
@interface BDLFloatingCardConfiguration : BDLRTBaseConfiguration
/// 是否开启商品直达链接
/// YES: 如果您在企业直播控制台设置了直达链接,则优先读取直达链接
/// NO: 读取跳转链接
@property (nonatomic, assign) BOOL enableDirectUrl;
/// 高亮文字
@property (nonatomic, copy, nullable) NSString *highLightString;
@end

图文菜单定制

BDLImageTextView

/// 图文菜单 view
/// 图文菜单 view 是基于 WKWebView 显示的
@interface BDLImageTextView : BDLBaseView
/// 图文菜单配置,详见 BDLImageTextViewConfiguration
@property (nonatomic, strong, readonly) BDLImageTextViewConfiguration *config;
/// 显示图文的 WKWebView
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong) WKWebView *webView;
/// 通过富文本进行更新
/// @param richText HTML5 代码
/// @param defaultColor 默认颜色,如果 config.imageTextTextColor 为空,则用该颜色显示
- (void)updateWithImageText:(NSString *)richText defaultColor:(UIColor *)defaultColor;

@end

BDLImageTextViewConfiguration

/// 图文菜单配置
@interface BDLImageTextViewConfiguration : BDLRTBaseConfiguration
/// WKWebView 相对于父控件 BDLImageTextView 的间距
@property (nonatomic, assign) CGFloat viewMargin;

/// 图文菜单下的文字颜色
@property (nonatomic, strong) UIColor *imageTextTextColor;

@end

互动工具菜单定制

BDLInteractiveToolController

/// 互动工具 controller
@interface BDLInteractiveToolController : NSObject

/// 显示弹窗的 view。当为 nil 时,则不显示相关弹窗
@property (nonatomic, strong, nullable) UIView *popupSuperview;
/// 在观看页显示互动工具浮窗时调用该方法。相同类型,floatingView 相同。默认为 BDLFloatingInteractiveToolView 的类型,可以通过 floatingView.type 判断浮窗的类型
/// @param floatingView 显示的互动工具浮窗
/// @param withoutCloseButtonView 同 floatingView,但无关闭按钮
@property (nonatomic, copy, nullable) void(^showFloatingViewBlock)(BDLInteractiveToolController *interactiveToolController, UIView *floatingView, UIView *withoutCloseButtonView);

/// 在观看页隐藏互动工具浮窗时调用该方法。相同类型,floatingView 相同。默认为 BDLFloatingInteractiveToolView 的类型,可以通过 floatingView.type 判断浮窗的类型
/// @param floatingView 隐藏的互动工具浮窗
/// @param withoutCloseButtonView 同 floatingView,但无关闭按钮
@property (nonatomic, copy, nullable) void(^hideFloatingViewBlock)(BDLInteractiveToolController *interactiveToolController, UIView *floatingView, UIView *withoutCloseButtonView);

/// 在需要关闭直播间时调用该方法。目前仅适用于强制关闭进入直播时问卷的场景
@property (nonatomic, copy, nullable) void(^closeLiveRoomBlock)(BDLInteractiveToolController *interactiveToolController);

/// 自定义互动工具菜单,可自定义所有属性。详见 BDLInteractiveToolView 
@property (nonatomic, copy, nullable) __kindof BDLBaseView * _Nullable (^customizeInteractiveToolView)(BDLInteractiveToolController *controller, BDLInteractiveToolView *interactiveToolView);
/// 自定义浮窗 view,详见 BDLFloatingInteractiveToolView
@property (nonatomic, copy, nullable) __kindof UIView * _Nullable (^customizeFloatingView)(BDLInteractiveToolController *controller, BDLFloatingInteractiveToolView *floatingView);

/// 自定义完善中奖信息弹窗 view,详见 BDLAwardContactView
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeAwardContactView)(BDLInteractiveToolController *controller, BDLAwardContactView *view);
/// 自定义抽奖详情 view,详见 BDLAwardDetailsView 
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupBottomShowViewProtocol> * _Nullable (^customizeAwardDetailsView)(BDLInteractiveToolController *controller, BDLAwardDetailsView *view);
/// 自定义中奖名单 view,详见 BDLAwardWinnersView 
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeAwardWinnersView)(BDLInteractiveToolController *controller, BDLAwardWinnersView *view);
/// 自定义抽奖结果 view,详见 BDLAwardResultView 
@property (nonatomic, copy, nullable) __kindof UIView<BDLPopupCenterShowViewProtocol> * _Nullable (^customizeAwardResultView)(BDLInteractiveToolController *controller, BDLAwardResultView *view);
/// 在观众点击互动消息中的 URL 时调用该方法
/// @param url 点击的 URL
/// @param enableFloating 是否浮层显示
@property (nonatomic, copy, nullable) void (^interactiveToolViewURLTappedBlock)(NSURL * _Nullable url, BOOL enableFloating);
@end

BDLFloatingInteractiveToolView

/// 互动工具浮窗 view 的类型
typedef NS_ENUM(NSInteger, BDLFloatingInteractiveToolViewType) {
    /// 公告
    BDLFloatingInteractiveToolViewTypeAnnouncement = 1,
    /// 投票
    BDLFloatingInteractiveToolViewTypeVote,
    /// 答题
    BDLFloatingInteractiveToolViewTypeQuiz,
    /// 正在进行的抽奖
    BDLFloatingInteractiveToolViewTypeOngoingAward,
    /// 已开奖的抽奖
    BDLFloatingInteractiveToolViewTypeOpenedAward,
    /// 问卷
    BDLFloatingInteractiveToolViewTypeQuestionnaire,
};

/// 互动工具浮窗 view
@interface BDLFloatingInteractiveToolView : BDLBaseView
/// 初始化方法
/// @param type 互动工具浮窗 view 的类型,详见 BDLFloatingInteractiveToolViewType
- (instancetype)initWithType:(BDLFloatingInteractiveToolViewType)type;
/// 当前 view 对应的互动工具数据。不同的 type,model 的类型不同
@property (nonatomic, strong) id model;
/// 初始化方法传递进来的 type
@property (nonatomic, assign, readonly) BDLFloatingInteractiveToolViewType type;
/// imageView,支持自定义
@property (nonatomic, strong, readonly) UIImageView *imageView;
/// 底部文字 label,可自定义除 text 外的所有属性
@property (nonatomic, strong, readonly) UILabel *label;
/// 关闭按钮,支持自定义
@property (nonatomic, strong, readonly) UIButton *closeButton;
/// 当前 view 点击回调
@property (nonatomic, copy) void(^clickBlock)(BDLFloatingInteractiveToolView *view);
/// 关闭按钮点击回调
@property (nonatomic, copy) void(^closeButtonClickBlock)(BDLFloatingInteractiveToolView *view, UIButton *button);

@end

BDLInteractiveToolView

/// 互动工具菜单 view
@interface BDLInteractiveToolView : BDLBaseView
/// 竖屏模式下的名字 label
/// 可自定义除 text、textColor、frame 外的所有属性
/// 可通过 BDLInteractiveToolConfiguration.nameTextColor 自定义 textColor
@property (nonatomic, strong) UILabel *nameLabel;
/// 是否为竖屏
@property (nonatomic, assign, readonly) BOOL isPortrait;
/// 点击评论中链接是否开启浮层
@property (nonatomic, assign, readonly) BOOL urlFloatingEnable;
/// 互动工具菜单配置,详见 BDLInteractiveToolConfiguration
@property (nonatomic, strong, readonly) BDLInteractiveToolConfiguration *config;
/// 互动工具中 URL 的点击回调
@property (nonatomic, copy, nullable) void (^urlClickBlock)(BDLInteractiveToolView *view, NSURL *url);
/// 抽奖点击回调
/// @param model 抽奖信息
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolView 中的 onContextClickBlock 方法替代之
@property (nonatomic, copy, nullable) void (^onAwardClickedBlock)(BDLInteractiveToolView *view, BDLInteractiveAwardModel *model);

/// 在观众点击互动工具 context 时调用该方法。互动工具 context 指互动工具菜单下的抽奖、投票、问卷等
/// @param view 互动工具菜单 view
/// @param model 互动工具数据
/// @param context 互动工具 context 数据
@property (nonatomic, copy, nullable) void (^onContextClickBlock)(BDLInteractiveToolView *view, BDLInteractiveToolModel *model, BDLInteractiveContextModel *context);
/// 初始化
/// @param isPortrait 是否为竖屏
- (instancetype)initWithPortrait:(BOOL)isPortrait;

@end

BDLInteractiveToolConfiguration

/// 互动工具菜单配置
@interface BDLInteractiveToolConfiguration : BDLRTBaseConfiguration

/// 名字文字颜色
@property (nonatomic, strong) UIColor *nameTextColor;
/// 内容文字颜色
@property (nonatomic, strong) UIColor *textColor;
/// 内容标题的颜色
@property (nonatomic, strong) UIColor *contextTitleTextColor;
/// Cell 背景颜色
@property (nonatomic, strong) UIColor *cellBackgroundColor;
/// Cell 圆角
@property (nonatomic, assign) CGFloat cellCornerRadius;
/// 是否显示参与投票人数。YES:显示。NO:不显示。默认值:YES
@property (nonatomic, assign) BOOL showPeopleCount;
@end

BDLInteractiveToolContentView

/// 互动工具内容 view 的代理方法
@protocol BDLInteractiveToolContentViewDelegate <NSObject>

/// URL 是否可以交互
/// @param textView URL 所在的文本 view
- (BOOL)interactiveToolTextView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL;
/// 在观众点击内容 view 时调用该方法
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolContentView 中的 didClickContextViewWithModel:contextModel: 方法替代之
- (void)didClickContextViewWithModel:(BDLInteractiveToolModel *)model;
/// 在观众点击内容 view 的按钮时调用该方法
/// @param index 按钮的下标。如果有多个按钮,可用于区分不同的按钮
/// 该方法自 1.28.0 版本开始不再支持使用,您可以使用 BDLInteractiveToolContentView 中的 didClickContextViewWithModel:contextModel: 方法替代之
- (void)didClickContextViewButtonWithModel:(BDLInteractiveToolModel *)model buttonIndex:(NSUInteger)index;

/// 在观众点击互动工具内容 view 时调用该方法
/// @param model 互动工具数据
/// @param contextModel 互动工具 context 数据。互动工具 context 指互动工具菜单下的抽奖、投票、问卷等
- (void)didClickContextViewWithModel:(BDLInteractiveToolModel *)model contextModel:(BDLInteractiveContextModel *)contextModel;
@end
/// 互动工具内容 view
@interface BDLInteractiveToolContentView : BDLBaseView <BDLMenuService>
/// 内容的容器 tableView
@property (nonatomic, strong) UITableView *tableView;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign) BDLLanguageType langType;
/// 当前所有支持的语言类型
@property (nonatomic, copy) NSArray<NSNumber *> *langTypes;
/// 当前互动工具内容 view 对应的数据
@property (nonatomic, strong) NSArray<BDLInteractiveToolModel *> *interactiveTools;
/// 代理方法
@property (nonatomic, weak) id<BDLInteractiveToolContentViewDelegate> delegate;
/// 根据 config 更新 view
- (void)updateWithConfig:(BDLInteractiveToolConfiguration *)config;

@end

主播账号定制

BDLBusinessAccountView

/// 主播账号 view,对应企业直播控制台的主播/品牌方账号功能
@interface BDLBusinessAccountView : BDLBaseView

/// 头像
/// 可自定义除圆角、图片、位置外的属性
@property (nonatomic, strong) UIImageView *avatarImageView;
/// 账号名称 label
/// 可自定义除 text 和 frame 外的所有属性
@property (nonatomic, strong) UILabel *nameLabel;
/// 点击回调,您可自定义实现
/// @param urlStr 在企业直播控制台设置的跳转链接
@property (nonatomic, copy, nullable) void (^viewTappedBlock)(NSString * _Nullable urlStr)

@end

页中广告定制

BDLPageAdView

/// 页中广告协议,自定义页中广告返回的 view(例如 BDLPageAdView)需要遵守该协议
@protocol BDLPageAdViewProtocol

/// 对于自定义页中广告 view,需要实现该方法,同时在隐藏页中广告时调用 block
- (void)setShowOrHideBlock:(void(^)(UIView *view))block;

@end

/// 页中广告 view,对应企业直播控制台的页中广告功能
@interface BDLPageAdView : BDLBaseView <BDLPageAdViewProtocol, BDLMarketService, BDLBasicService>

/// 初始化方法
/// @param isPortrait 是否为竖屏
- (instancetype)initWithPortrait:(BOOL)isPortrait;
/// 当前正在显示的广告的数据
@property (nonatomic, copy, readonly) NSArray<BDLAdvertisementModel *> *showingPageAdModels;

/// 当前页中广告所持有的配置
@property (nonatomic, strong, readonly) BDLPageAdViewConfiguration *config;
/// 页中广告的轮播基于 collectionView 实现
@property (nonatomic, strong) UICollectionView *collectionView;
/// 关闭按钮,可自定义除位置外的所有属性。自 SDK 1.31.0 版本开始不再支持使用
@property (nonatomic, strong) UIButton closeButton;
/// 页中广告点击回调,您可自定义实现
/// @param view 当前的 BDLPageAdView 实例
/// @param ad 在企业直播控制台配置的广告信息
/// @param isFloatingEnable 是否在应用内打开
@property (nonatomic, copy, nullable) void (^viewTappedBlock)(BDLPageAdView *view, BDLAdvertisementModel *ad, BOOL isFloatingEnable);
/// 关闭按钮点击回调,您可自定义实现
@property (nonatomic, copy, nullable) void (^closeButtonClickedBlock)(void);

/// 竖屏模式配置页中或页头广告时或者横屏模式配置页中广告时触发该 Block
/// 返回值为 YES:显示广告。返回值为 NO:不显示广告。默认返回 YES
/// @param adView 当前的 BDLPageAdView 实例
/// @param type 广告类型
@property (nonatomic, copy, nullable) BOOL (^shouldShowAdBlock)(BDLPageAdView *adView, BDLPageAdvertisementType type);
@end

BDLPageAdViewConfiguration

/// 页中广告配置
@interface BDLPageAdViewConfiguration : BDLRTBaseConfiguration

/// 设置页中广告的轮播时间间隔,即每隔多长时间向右滚动一次。单位为秒,默认为 3,需大于 0
@property (nonatomic, assign) NSTimeInterval scrollTimeInterval;
/// 圆角,默认为 4.0
@property (nonatomic, assign) CGFloat cornerRadius;
@end

浮窗广告定制

BDLUpperAdView

/// 浮窗广告 view,对应企业直播控制台的浮标广告功能
@interface BDLUpperAdView : BDLBaseView <BDLPageUpperAdService>

/// 关闭按钮
/// 可自定义除位置、hidden 外的所有属性
@property (nonatomic, strong) UIButton* closeButton;
/// 广告图片
/// 可自定义除位置、hidden 外的所有属性
@property (nonatomic, strong) UIImageView* imageView;
/// 浮窗广告点击回调
/// @param urlStr 在企业直播控制台设置的跳转链接
@property (nonatomic, copy, nullable) void (^viewTappedBlock)(NSString * _Nullable urlStr);
/// 关闭按钮点击回调
@property (nonatomic, copy, nullable) void (^closeButtonClickedBlock)(void);

@end

播放器定制

BDLBasePlayerView

@class BDLBasePlayerView;
 
/// 独立播放器 view 的代理方法 
@protocol BDLBasePlayerViewDelegate <NSObject>
 
@optional

/// 在直播封面即将显示时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView coverImageViewWillAppear:(UIImageView *)coverImageView;
/// 在显示直播封面时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView coverImageViewDidAppear:(UIImageView *)coverImageView;
/// 在直播封面即将消失时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView coverImageViewWillDisappear:(UIImageView *)coverImageView;
/// 在直播封面消失时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView coverImageViewDidDisappear:(UIImageView *)coverImageView;
/// 在直播封面改变时调用该方法
/// @param url 直播封面图地址
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView coverImageUrlDidChange:(nullable NSString *)url
/// 在直播封面改变时调用该方法
/// @param image 改变后的直播封面图
/// @param error 错误信息,有值则新的直播封面图获取失败,继续使用之前的直播封面图
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView coverImageDidChange:(nullable UIImage *)image error:(nullable NSError *)error;
 
/// 在播放内容改变时调用该方法
/// @param isLive 是否为直播
/// @param willPlay 是否将要播放
- (void)basePlayerViewPlayerItemDidChange:(BDLBasePlayerView *)basePlayerView isLive:(BOOL)isLive willPlay:(BOOL)willPlay;
/// 在播放器即将显示时调用该方法
/// @param videoView 播放器 view
/// @param isLive 是否为直播
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView videoViewWillAppear:(UIView *)videoView isLive:(BOOL)isLive;
/// 在显示播放器时调用该方法
/// @param videoView 播放器 view
/// @param isLive 是否为直播
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView videoViewDidAppear:(UIView *)videoView isLive:(BOOL)isLive;
/// 在播放器即将消失时调用该方法
/// @param videoView 播放器 view
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView videoViewWillDisappear:(UIView *)videoView;
/// 在播放器消失时调用该方法
/// @param videoView 播放器 view
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView videoViewDidDisappear:(UIView *)videoView;
/// 在视频大小改变时调用该方法
/// @param videoSize 视频大小
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView videoSizeDidChange:(CGSize)videoSize;
/// 在视频首帧图片渲染后调用该方法
- (void)basePlayerViewOnFirstVideoFrameRendered:(BDLBasePlayerView *)basePlayerView;
/// 在视频支持的清晰度发生改变时调用该方法
/// @param supportedVideoResolutions 当前视频支持的清晰度
/// @param currentVideoResolution 当前使用的清晰度
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView
supportedVideoResolutionsDidChange:(NSArray<NSNumber *> *)supportedVideoResolutions
currentVideoResolution:(BDLVideoResolution)currentVideoResolution;
/// 在视频开始卡顿时调用该方法
- (void)basePlayerViewStallStart:(BDLBasePlayerView *)basePlayerView;
/// 在视频卡顿结束时调用该方法
- (void)basePlayerViewStallEnd:(BDLBasePlayerView *)basePlayerView;
 
/// 在观众单击播放器时调用该方法
- (void)basePlayerViewDidSingleTap:(BDLBasePlayerView *)basePlayerView;
/// 在观众双击播放器时调用该方法
- (void)basePlayerViewDidDoubleTap:(BDLBasePlayerView *)basePlayerView;
 
/// 在即将开启系统画中画时调用该方法
- (void)basePlayerViewWillStartPictureInPicture:(BDLBasePlayerView *)basePlayerView;
/// 在开启系统画中画时调用该方法
- (void)basePlayerViewDidStartPictureInPicture:(BDLBasePlayerView *)basePlayerView;
/// 在开启系统画中画失败时调用该方法
/// @param error 失败信息
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView failedToStartPictureInPictureWithError:(NSError *)error;
/// 在即将停止系统画中画时调用该方法
- (void)basePlayerViewWillStopPictureInPicture:(BDLBasePlayerView *)basePlayerView;
/// 在结束系统画中画时调用该方法
- (void)basePlayerViewDidStopPictureInPicture:(BDLBasePlayerView *)basePlayerView;
 
/// 在直播加载状态发生改变时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView liveLoadStateDidChange:(TVLPlayerLoadState)loadState;
/// 在播放器状态发生变化时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView livePlayerItemStatusDidChange:(TVLPlayerItemStatus)itemStatus;
/// 在直播播放状态发生变化时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView livePlaybackStateDidChange:(TVLPlayerPlaybackState)playbackState;
/// 在即将获取点播的 URL 时调用该方法
- (void)basePlayerViewWillFetchVodUrl:(BDLBasePlayerView *)basePlayerView;
/// 在已经获取到点播的 URL 时调用该方法
/// @param error 错误信息,有值则获取失败
- (void)basePlayerViewDidFetchVodUrl:(BDLBasePlayerView *)basePlayerView error:(nullable NSError *)error;
/// 在点播播放结束时调用该方法
/// @param error 错误信息,有值则播放失败
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView vodDidFinishWithError:(nullable NSError *)error;
/// 在点播加载状态改变时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView vodLoadStateDidChange:(TTVideoEngineLoadState)loadState;
/// 在播放状态改变时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView vodPlaybackStateDidChange:(TTVideoEnginePlaybackState)playbackState;
/// 在点播播放失败,正在重试时调用该方法
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView vodRetryForError:(NSError *)error;
/// 在点播断点续播时调用该方法
/// @param playbackTime 断点续播时间,即上次播放结束的时间点。单位:秒
- (void)basePlayerView:(BDLBasePlayerView *)basePlayerView onVodAutoContinuePlayback:(NSTimeInterval)playbackTime;
 
@end

/// seek 操作完成后回调
/// @param success:seek 操作是否成功。seek 操作指跳转至视频指定时间点。YES:操作成功 NO:操作失败
typedef void(^BDLBasePlayerViewSeekCompletionBlock)(BOOL success);

/// 独立播放器 view。播放器内部实现了对直播状态的监听,支持根据直播状态播放对应状态的点播或直播视频
@interface BDLBasePlayerView : BDLBaseView <BDLBasicService, BDLPullStreamUrlService>

/// 代理方法 
@property (nonatomic, weak) id<BDLBasePlayerViewDelegate> delegate;
 
/// 直播封面 imageView
@property (nonatomic, strong, readonly) UIImageView *coverImageView;
/// 水印 view
@property (nonatomic, strong, readonly) UIView *watermarkView;
/// 播放器 view
@property (nonatomic, strong, readonly, nullable) UIView *videoView;
/// 视频画面的填充模式,详见 BDLPlayerScalingMode
@property (nonatomic, assign) BDLPlayerScalingMode scalingMode;
/// 是否静音
@property (nonatomic, assign) BOOL muted;
/// 是否禁止播放
@property (nonatomic, assign) BOOL forbidPlay;
/// 是否开启系统画中画
@property (nonatomic, assign) BOOL enablePictureInPicture API_AVAILABLE(ios(14.0));
/// 是否为直播
@property (nonatomic, assign, readonly) BOOL isLive;
/// 是否为点播
@property (nonatomic, assign, readonly) BOOL isVod;
/// 是否正在播放
@property (nonatomic, assign, readonly) BOOL isPlaying;
/// 播放器状态,详见 BDLPlayerState
@property (nonatomic, assign, readonly) BDLPlayerState playerState;
/// 是否正在卡顿
@property (nonatomic, assign, readonly) BOOL isStalling;
/// 是否已渲染视频首帧
@property (nonatomic, assign, readonly) BOOL isFirstVideoFrameRendered;
/// 视频 size
@property (nonatomic, assign, readonly) CGSize videoSize;
/// 当前支持的清晰度
@property (nonatomic, copy, readonly, nullable) NSArray<NSNumber *> *supportedVideoResolutions;
/// 当前使用的清晰度
@property (nonatomic, assign) BDLVideoResolution currentVideoResolution;
/// 播放器配置,详见 BDLBasePlayerConfiguration
@property (nonatomic, strong, readonly) BDLBasePlayerConfiguration *config;
 
/// 设置点播开始播放的时间
- (void)setVodStartTime:(NSTimeInterval)startTime;
/// 播放
- (void)play;
/// 停止
- (void)stop;
/// 暂停
- (void)pause;
 
#pragma mark - VOD
 
/// 点播视频的总时长
@property (nonatomic, assign, readonly) NSTimeInterval duration;
/// 当前可播放的时长,即已缓存的时长
@property (nonatomic, assign, readonly) NSTimeInterval playableDuration;
/// 当前播放时间
@property (nonatomic, assign, readonly) NSTimeInterval currentPlaybackTime;
/// 是否正在 seek(跳转)
@property (nonatomic, assign, readonly) BOOL isSeeking;
/// 是否循环播放
@property (nonatomic, assign) BOOL looping;
/// 播放速度
@property (nonatomic, assign) CGFloat playbackSpeed;
 
/// 跳转至预告或回放视频的指定时间点(单位:秒)
/// @param playbackTime 跳转至的时间点。单位:秒
/// @param completion seek 操作完成后触发该回调
- (void)seek:(NSTimeInterval)playbackTime completion:(BDLBasePlayerViewSeekCompletionBlock _Nullable)completion;
 
/// 添加周期性事件,用于定期从播放器获取数据
/// @param interval 时间间隔。单位:秒
/// @param queue 执行操作的目标队列
/// @param block 需要做的周期性工作
- (void)addPeriodicObserverWithInterval:(NSTimeInterval)interval
                                  queue:(dispatch_queue_t)queue
                             usingBlock:(void (^)(void))block;
                             
/// 移除周期性事件
- (void)removePeriodicObserver;
 
/// 重置当前视频的断点续播记录
/// @return 是否重置成功
- (BOOL)resetCurrentContinuePlaybackTime;
/// 播放器是否可见。默认为 YES
/// NO:播放器不可见。即使开启了系统画中画,在 App 切换至后台后也不会显示系统画中画。同时会暂停正在播放的直播或点播视频,即使开启了自动播放,在直播状态发生变化时也不会自动播放视频
/// YES:播放器可见。播放器不可见时暂停播放的直播或点播视频会自动恢复播放。如果开启了系统画中画,在 App 切换至后台后会显示系统画中画
@property (nonatomic, assign) BOOL visible;
 
@end

/// 播放器状态
typedef NS_ENUM(NSInteger, BDLPlayerState) {
    BDLPlayerStateUnknown, ///< 状态未知
    BDLPlayerStateStopped, ///< 播放停止
    BDLPlayerStatePlaying, ///< 正在播放
    BDLPlayerStatePaused, ///< 暂停播放
    BDLPlayerStateError ///< 播放出错
};

/// 视频画面的填充模式
typedef NS_ENUM(NSInteger, BDLPlayerScalingMode) {
    BDLPlayerScalingModeNone,
    BDLPlayerScalingModeAspectFit,  ///< 保持视频原有宽高比例填充播放器,视频的宽高会填满播放器的宽高。如果视频宽高比与播放器宽高比不同,视频会缩放显示。
    BDLPlayerScalingModeAspectFill, ///< 保持视频原有宽高比例填充播放器,视频的宽高会填满播放器的宽高。如果视频宽高比与播放器宽高比不同,会有部分视频内容被裁剪掉。
    BDLPlayerScalingModeFill        ///< 视频内容完全填充播放器,但视频宽高比可能发生变化。
};

BDLPlayerView

@class BDLPlayerView;
 
/// 播放器 view 的代理方法
@protocol BDLPlayerViewDelegate <NSObject>
 
 /// 在控制 view 显示/消失时调用该方法
 /// @param isAppear 是否显示
- (void)playerView:(BDLPlayerView *)playerView controlViewIsAppear:(BOOL)isAppear;
/// 在播放完成时调用该方法
/// @param isLive 是否为直播
- (void)playerView:(BDLPlayerView *)playerView didFinishPlayingWithIsLive:(BOOL)isLive;
 
@optional
 /// 在观众点击全屏/退出全屏按钮时调用该方法
/// @param isSelected YES:点击了全屏按钮,即全屏状态 NO:点击了退出全屏按钮,即非全屏状态
- (void)playerView:(BDLPlayerView *)playerView fullScreenButtonDidTouch:(BOOL)isSelected;
/// 在视频尺寸发生改变时调用该方法
- (void)playerView:(BDLPlayerView *)playerView videoSizeDidChange:(CGSize)size;
/// 在直播封面改变时调用该方法
/// @param image 改变后的直播封面图
/// @param error 错误信息,有值则新的直播封面图获取失败,继续使用之前的直播封面图
- (void)playerView:(BDLPlayerView *)playerView coverImageDidChange:(nullable UIImage *)image error:(nullable NSError *)error;
/// 在观众单击播放器时调用该方法
- (void)playerViewDidSingleTap:(BDLPlayerView *)playerView;
/// 在观众双击播放器时调用该方法
- (void)playerViewDidDoubleTap:(BDLPlayerView *)playerView;
/// 在播放内容改变时调用该方法
/// @param isLive 是否为直播
/// @param willPlay 是否将要播放
- (void)playerViewPlayerItemDidChange:(BDLPlayerView *)playerView isLive:(BOOL)isLive willPlay:(BOOL)willPlay;
 
@end

/// 播放器 view
@interface BDLPlayerView : BDLBaseView <BDLBasicService, BDLLanguageService, BDLPopularityService, BDLCardExplainService>
 
/// 初始化
/// @param isPortrait 是否以竖屏模式初始化播放器
/// NO:以横屏模式初始化播放器。无论源流画面宽高比如何,播放器画面区域为整个播放器, 控制界面(播放按钮等互动按钮)在播放器的底部
/// YES:以竖屏模式初始化播放器。源流画面宽高比不同,播放器画面区域与控制界面的显示样式不同
// 源流画面宽度大于等于高度,即横屏视频:播放器画面区域宽度为播放器的宽度,高度为播放器宽度的 9/16,距离播放器顶部 120 px。控制界面在画面区域的底部。默认有全屏按钮
/// 源流画面宽度小于高度,即竖屏视频:播放器画面区域为整个播放器。在播放点播视频时,控制界面在播放器底部,但直播期间播放器无控制界面
- (instancetype)initWithPortrait:(BOOL)isPortrait;
/// 初始化
/// @param isPortrait 是否为竖屏
/// @param basePlayerView 已经开始播放的独立播放器
- (instancetype)initWithPortrait:(BOOL)isPortrait
                  basePlayerView:(nullable BDLBasePlayerView *)basePlayerView; 
                  
/// 弹窗显示的父 view。SDK 内部默认实现了倍速、清晰度等弹窗效果,弹窗会加到 popupSuperView 上面 
@property (nonatomic, weak) UIView *popupSuperView;
/// 代理方法
@property (nonatomic, weak) id<BDLPlayerViewDelegate> delegate;
/// 独立播放器 view。playerView 持有一个 basePlayerView 并添加了控制的逻辑
@property (nonatomic, strong, readonly, nullable) BDLBasePlayerView *basePlayerView;
/// 播放器遮罩 view,包含直播状态、水印、人气 view 等,详见 BDLPlayerMaskView
@property (nonatomic, strong) BDLPlayerMaskView *maskView;
/// 播放器控制 view,包含播放按钮、暂停按钮、进度条、刷新按钮、全屏按钮、时间文本等,详见 BDLPlayerControlView
@property (nonatomic, strong) BDLPlayerControlView *controlView;
/// 清晰度选择 view,详见 BDLPlayerResolutionView
@property (nonatomic, strong, nullable) BDLPlayerResolutionView *resolutionView;
/// 倍速选择 view,详见 BDLPlayerSpeedView
@property (nonatomic, strong, nullable) BDLPlayerSpeedView *speedView;
/// 加载 view,详见 BDLLoadingView
@property (nonatomic, strong, nullable) BDLLoadingView *loadingView;
/// 断网提示 view,详见 BDLNetworkNotReachableView
@property (nonatomic, strong, nullable) BDLNetworkNotReachableView *networkNotReachableView;
/// 流量访问提示 view,详见 BDLNetworkViaWWANView
@property (nonatomic, strong, nullable) BDLNetworkViaWWANView *networkViaWWANView;
/// 重播 view,详见 BDLPlayerReplayView
@property (nonatomic, strong, nullable) BDLPlayerReplayView *replayView;
/// 断点续播提示 view,详见 BDLContinuePlaybackToastView
@property (nonatomic, strong, nullable) BDLContinuePlaybackToastView *continuePlaybackToastView;
 
/// 播放器配置,详见 BDLPlayerConfiguration
@property (nonatomic, strong, readonly) BDLPlayerConfiguration *config;

/// 是否开启系统画中画
@property (nonatomic, assign, readonly) BOOL isPiPStarted;
/// 是否开启浮窗(InApp 画中画)
@property (nonatomic, assign, readonly) BOOL isFloating;
/// 是否为全屏
@property (nonatomic, assign, readonly) BOOL isFullScreen;
/// 播放器是否全屏
@property (nonatomic, assign) BOOL isPlayerFullSuper; 
/// 是否为竖屏视频
@property (nonatomic, assign) BOOL isPortraitVideo;
/// 自定义断点续播提示 view
@property (nonatomic, copy) __kindof UIView * (^customizeVodContinuePlaybackToastView)(BDLPlayerView *view, BDLContinuePlaybackToastView *toastView, NSTimeInterval currentPlaybackTime);

/// 自定义倍速选择界面
@property (nonatomic, copy) void (^customizeSpeedView)(BDLPlayerView *playerView, BDLPlayerSpeedView *speedView);
/// 显示 controlView
/// @param autoHide 是否自动隐藏
- (void)showControlViewIfNeededWithAutoHide:(BOOL)autoHide;
/// 隐藏 controlView
- (void)hideControlView;
/// 自动隐藏 controlView
- (void)autoHideControlView;
/// 当前是否可以浮窗播放
- (BOOL)canFloating;
/// 进入全屏。外部实现全屏逻辑后调用该方法,更改 controlView 全屏按钮的状态
- (void)enterFullScreen;
/// 离开全屏
- (void)leaveFullScreen;
 
/// 获取浮窗关闭的图片
- (UIImage *)getFloatingCloseImage;
/// 获取浮窗关闭图片的大小
- (CGSize)getFloatingCloseImageSize;
 
/// 获取当前正在显示的媒体文件(图片/视频)的大小
- (CGSize)getCurrentShowingMediaSize;

/// 退出全屏时更新播放器
- (void)updatePlayerWhenLeaveFullScreen; 

/// 添加 basePlayerView
- (void)addBasePlayerView:(BDLBasePlayerView *)basePlayerView;
/// removeFromSuperview,即从 BDLPlayerView 中移除 basePlayerView,使其不再显示在界面上,但属性 self.basePlayerView 不会为空,BDLPlayerView 会保留对 basePlayerView 的引用
- (BDLBasePlayerView *)removeBasePlayerViewFromSuperview;

/// 播放
- (void)play;
/// 暂停播放
- (void)pause;
/// 停止播放
- (void)stop;

@end

BDLPlayerControlView

/// 播放器控制 view 的代理方法 
@protocol BDLPlayerControlViewDelegate <NSObject>

/// 在观众点击播放按钮时调用该方法
/// @param isSelected YES:播放按钮选中状态,即正在播放视频 NO:播放按钮未选中状态,即暂停播放
- (void)controlView:(BDLPlayerControlView *)controlView playButtonDidTouch:(BOOL)isSelected;
/// 在观众开始拖动进度条时调用该方法
- (void)controlViewSliderBeganDrag;
/// 在观众停止拖动进度条时调用该方法
- (void)controlViewSliderEndDrag;
/// 在观众点击进度条时调用该方法
- (void)controlViewSliderViewDidTap;
/// 在播放进度改变时调用该方法
/// @param progress 播放进度
- (void)controlView:(BDLPlayerControlView *)controlView progressDidChange:(CGFloat)progress;

@optional
/// 在直播期间观众点击刷新按钮时调用该方法
- (void)controlViewRefreshButtonDidTouch:(BDLPlayerControlView *)controlView;
/// 在观众点击清晰度按钮时调用该方法
- (void)controlViewResolutionButtonDidTouch:(BDLPlayerControlView *)controlView;
/// 在观众点击倍速按钮时调用该方法
- (void)controlViewSpeedButtonDidTouch:(BDLPlayerControlView *)controlView;
/// 在观众点击全屏/退出全屏按钮时调用该方法
/// @param isSelected YES:点击了全屏按钮,即全屏状态 NO:点击了退出全屏按钮,即非全屏状态
- (void)controlView:(BDLPlayerControlView *)controlView fullScreenButtonDidTouch:(BOOL)isSelected;
/// 在视频清晰度改变时调用该方法
/// @param resolution 当前的清晰度
- (void)controlView:(BDLPlayerControlView *)controlView resolutionDidChange:(BDLVideoResolution)resolution;

@end

/// 播放器控制 view,包含播放按钮、暂停按钮、进度条、刷新按钮、全屏按钮、时间文本等
@interface BDLPlayerControlView : BDLBaseView <BDLBasicService, BDLLanguageService, BDLPullStreamUrlService>

/// 代理方法
@property (nonatomic, weak) id<BDLPlayerControlViewDelegate> delegate;
/// 功能元素(播放按钮、暂停按钮、进度条、刷新按钮、全屏按钮、时间文本等)的父控件
@property (nonatomic, strong) UIView *controlBarView;
/// 播放/暂停按钮
/// selected 为 YES 表示当前正在播放,显示暂停按钮
/// selected 为 NO 表示当前不在播放,显示播放按钮
@property (nonatomic, strong) UIButton *playButton;
/// 播放器中间的播放按钮,暂停时才会显示
@property (nonatomic, strong, readonly) UIButton *centerPlayButton;
/// 刷新按钮,直播时才会显示
@property (nonatomic, strong, readonly) UIButton *refreshButton;
/// 全屏按钮,横屏模式下以及竖屏模式的横屏视频才会显示
/// 可通过 config.common.fullScreenButtonNormalImage 和 config.common.fullScreenButtonSelectedImage 自定义图片
@property (nonatomic, strong, nullable) UIButton *fullScreenButton;
/// 返回按钮,横屏模式下以及竖屏模式的横屏视频才会显示
/// 可通过 config.common.exitFullScreenButtonNormalImage 自定义图片
@property (nonatomic, strong, readonly) UIButton *backButton;
/// 是否需要全屏按钮
@property (nonatomic, assign) BOOL needFullScreenButton;
/// 当前播放时间 label,点播时才会显示
/// 可通过 config.common.currentTimeColor 自定义颜色
@property (nonatomic, strong) UILabel *currentTimeLabel;
/// 总时长 label,点播时才会显示
/// 可通过 config.common.totalTimeColor 自定义颜色
@property (nonatomic, strong) UILabel *durationLabel;
/// 总时长,直播时为 0。单位:秒
@property (nonatomic, assign) NSTimeInterval duration;
/// 当前时长,直播时为 0。单位:秒
@property (nonatomic, assign) NSTimeInterval currentTime;
/// 进度条 view,点播时才会显示,详见 BDLPlayerSliderView
@property (nonatomic, strong) BDLPlayerSliderView *sliderView;
/// 是否正在拖动进度条
@property (nonatomic, readonly, getter=isSliding) BOOL sliding;
/// 倍速按钮,不支持自定义文字
@property (nonatomic, strong) UIButton *speedButton;
/// 当前播放速度
@property (nonatomic, assign) BDLPlayerSpeed speed;
/// 清晰度按钮
@property (nonatomic, strong, nullable) UIButton *resolutionButton;

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param config 当前配置
- (instancetype)initWithPortrait:(BOOL)isPortrait config:(BDLPlayerConfiguration *)config;

/// 播放
- (void)play;
/// 暂停
- (void)pause;

/// 根据播放状态同步播放按钮的状态
- (void)updatePlayButton:(BOOL)isPlaying;
/// 设置当前的播放进度
/// @param animated 是否需要动画
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated;
/// 设置缓存进度
/// @param animated 是否需要动画
- (void)setCacheProgress:(CGFloat)progress animated:(BOOL)animated;
/// 显示控制 view,SDK 内部会判断是否可以显示
/// @return YES: 显示 NO: 没显示
- (BOOL)showIfNeeded;
/// 隐藏控制 view
- (void)hide;
/// 当前是否正在播放
- (BOOL)isPlaying;
/// 开始浮窗(InApp 画中画)播放,SDK 内部会有一些逻辑来控制浮窗播放时部分控件的显示和隐藏
/// @return 是否开始成功
- (BOOL)startFloating;
/// 停止浮窗播放
- (void)stopFloating;
/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;
/// 更新清晰度
/// @param resolutions 所有支持的清晰度
/// @param resolution 当前选中的清晰度
- (void)updateResolutionButtonWithResolutions:(NSArray<NSNumber *> *)resolutions currentResolution:(BDLVideoResolution)resolution;
/// 修改清晰度,用于同步清晰度按钮的显示
/// @param success 是否成功
/// @param completeResolution 最终的清晰度
- (void)changeResolutionSuccess:(BOOL)success completeResolution:(BDLVideoResolution)completeResolution;

/// 进入/退出全屏
- (void)onFullScreen;

@end

BDLPlayerReplayView

/// 重播 view 的代理方法
@protocol BDLPlayerReplayViewDelegate <NSObject>
/// 在竖屏模式下观众点击重播界面时调用该方法
- (void)replayViewDidTouch:(BDLPlayerReplayView *)replayView;
/// 在横屏模式下观众点击重播按钮时调用该方法
/// @param button 重播按钮
- (void)playerReplayView:(BDLPlayerReplayView *)replayView replayButtonDidTouch:(UIButton *)button;

@end

/// 重播 view
@interface BDLPlayerReplayView : BDLBaseView <BDLLanguageService>

/// 代理方法
@property (nonatomic, weak) id<BDLPlayerReplayViewDelegate> delegate;

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param config 当前配置
- (instancetype)initWithPortrait:(BOOL)isPortrait config:(BDLPlayerConfiguration *)config;
/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;

@end

BDLFloatingPlayer

/// 浮窗(InApp 画中画)播放器的代理方法
@protocol BDLFloatingPlayerDelegate <NSObject>

@optional
/// 在即将显示播放器时调用该方法
- (void)floatingPlayerWillAppear:(BDLFloatingPlayer *)floatingPlayer;
/// 在播放器消失时调用该方法
- (void)floatingPlayerDidDisappear:(BDLFloatingPlayer *)floatingPlayer;
/// 在观众单击播放器时调用该方法
- (void)floatingPlayerDidSingleTap:(BDLFloatingPlayer *)floatingPlayer;
/// 在观众双击播放器时调用该方法
- (void)floatingPlayerDidDoubleTap:(BDLFloatingPlayer *)floatingPlayer;
/// 在播放器即将关闭时调用该方法
- (void)floatingPlayerWillClose:(BDLFloatingPlayer *)floatingPlayer;
/// 在点播断点续播时调用该方法
/// @param playbackTime 断点续播时间,即上次播放结束的时间点。单位:秒
- (void)floatingPlayer:(BDLFloatingPlayer *)floatingPlayer onVodAutoContinuePlayback:(NSTimeInterval)playbackTime;

/// 在点击关闭浮窗播放器时调用该方法
/// @return 是否执行默认点击逻辑,即关闭浮窗播放器
- (BOOL)floatingPlayerDidClickClose:(BDLFloatingPlayer *)floatingPlayer;

@end

/// 浮窗播放器
@interface BDLFloatingPlayer : NSObject

/// 代理方法
@property (nonatomic, weak) id<BDLFloatingPlayerDelegate> delegate;
/// 独立播放器 view
@property (nonatomic, strong, readonly) BDLBasePlayerView *basePlayerView;
/// 容器 view
@property (nonatomic, strong, readonly) UIView *containerView;

/// 初始化
/// @param isPortrait 是否以竖屏模式初始化浮窗播放器。
/// YES:从 BDLPlayerConfiguration.portrait.loadingImage 获取浮窗播放器加载中图片,从 BDLPlayerConfiguration.portrait.loadingImageSize 获取浮窗播放器加载中图片的大小 
/// NO:从 BDLPlayerConfiguration.landscape.loadingImage 获取浮窗播放器加载中图片,从 BDLPlayerConfiguration.landscape.loadingImageSize 获取浮窗播放器加载中图片的大小
- (instancetype)initWithPortrait:(BOOL)isPortrait;
/// 初始化
/// @param isPortrait 是否为竖屏
/// @param basePlayerView 已经开始播放的独立播放器
- (instancetype)initWithPortrait:(BOOL)isPortrait
                  basePlayerView:(BDLBasePlayerView *)basePlayerView;
/// 移除已经开始播放的独立播放器
- (BDLBasePlayerView *)removeBasePlayerView;
/// 设置播放器方向
- (void)setUIOrientation:(UIInterfaceOrientation)orientation;
/// 显示播放器
/// 播放器会以 16:9 的比例显示在右下角
/// 如果已经有视频 size,那么会根据视频 size 决定是 16:9 还是 9:16
/// @param haveCloseButton 是否显示浮窗右上方的关闭按钮。YES:显示关闭按钮 NO:不显示关闭按钮
- (BOOL)showWithCloseButton:(BOOL)haveCloseButton;
/// 以指定的 frame 显示播放器
/// @param haveCloseButton 是否需要关闭按钮
- (BOOL)showWithFrame:(CGRect)frame closeButton:(BOOL)haveCloseButton;
/// 隐藏播放器
- (void)hide;
/// 关闭播放器。效果同 hide,但是比 hide 多了 floatingPlayerWillClose 回调
- (void)close;
/// 播放器是否处于悬浮状态
- (BOOL)isFloating;

@end

BDLPlayerMaskView

/// 遮罩 view,包含直播状态(预告/结束)、水印、人气 view 等
@interface BDLPlayerMaskView : BDLBaseView <BDLBasicService, BDLLanguageService>

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param config 当前配置
- (instancetype)initWithPortrait:(BOOL)isPortrait config:(BDLPlayerConfiguration *)config;

/// 预告/直播已结束 toast 的 label
/// 不支持自定义 text、hidden
/// 可通过 config.common.toastFont 自定义字体
@property (nonatomic, strong) UILabel *promptLabel;
/// 预告/直播已结束 toast 的容器 view
/// 不支持自定义 hidden
/// 可通过 config.common.toastCornerRadius 自定义圆角
@property (nonatomic, strong) UIView *promptContainerView;
/// 水印的 imageView,横屏模式下才显示
/// 不支持自定义 image
@property (nonatomic, strong, nullable) UIImageView *watermarkImageView;
/// 预告/结束状态的 label
/// 不支持自定义 hidden、text
@property (nonatomic, strong, nullable) UILabel *tagLabel;
/// 人气 view,横屏模式下才显示,详见人气显示定制的 BDLPopularityView
/// 不支持自定义 hidden
@property (nonatomic, strong, nullable) BDLPopularityView *popularityView;

/// 开始浮窗(InApp 画中画)播放,SDK 内部会有一些逻辑来控制浮窗播放时部分控件的显示和隐藏
/// @return 是否开始成功
- (BOOL)startFloating;
/// 停止浮窗播放
- (void)stopFloating;
/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;

@end

BDLPlayerResolutionView

/// 清晰度选择 view 的代理方法
@protocol BDLPlayerResolutionViewDelegate <NSObject>
/// 在清晰度改变时调用该方法
/// @param resolution 选中的清晰度
- (void)resolutionView:(BDLPlayerResolutionView *)resolutionView resolutionDidChange:(BDLVideoResolution)resolution;

@end

/// 清晰度选择 view
@interface BDLPlayerResolutionView : BDLPopupBottomOrRightShowBaseView <BDLLanguageService>

/// 代理方法
@property (nonatomic, weak) id<BDLPlayerResolutionViewDelegate> delegate;

/// 当前是否全屏
@property (nonatomic, assign) BOOL fullScreen;

/// 更新清晰度
/// @param resolutions 所有支持的清晰度
/// @param currentResolution 当前选中的清晰度
- (void)updateWithResolutions:(NSArray<NSNumber *> *)resolutions currentResolution:(BDLVideoResolution)currentResolution;

/// 修改清晰度,用于同步清晰度按钮的显示
/// @param success 是否成功
/// @param completeResolution 最终的清晰度
- (void)changeResolutionSuccess:(BOOL)success completeResolution:(BDLVideoResolution)completeResolution;

/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;
@end

BDLPlayerSliderView

/// 播放器进度条 view 的代理方法
@protocol BDLPlayerSliderViewDelegate <NSObject>

/// 在观众开始拖动进度条时调用该方法
- (void)sliderViewBeganDrag;
/// 在观众停止拖动进度条时调用该方法
- (void)sliderViewEndDrag;
/// 在观众点击进度条 view 时调用该方法
- (void)sliderViewDidTap:(BDLPlayerSliderView *)sliderView;
/// 在进度条进度改变时调用该方法
/// @param progress 当前进度
- (void)sliderView:(BDLPlayerSliderView *)sliderView progressDidChange:(CGFloat)progress;

@end

/// 播放器进度条 view
@interface BDLPlayerSliderView : UIView

/// 当前位置的小圆点
/// 支持自定义除位置外的所有属性
@property (nonatomic, strong) UIView *thumbView;
/// 背景 view
/// 支持自定义除位置外的所有属性
@property (nonatomic, strong) UIView *backgroundView;
/// 当前进度的 view
/// 可通过 config.common.themeColor 自定义背景颜色
@property (nonatomic, strong) UIView *trackProgressView;
/// 缓存进度的 view
@property (nonatomic, strong) UIView *cacheProgressView;

/// 代理方法
@property (nonatomic, weak) id<BDLPlayerSliderViewDelegate> delegate;
/// 当前进度
@property (nonatomic, assign, readonly) CGFloat progress;
/// 缓存进度
@property (nonatomic, assign, readonly) CGFloat cacheProgress;
/// 是否正在拖动
@property (nonatomic, assign, readonly, getter=isSliding) BOOL sliding;

/// 初始化
/// @param config 配置信息
- (instancetype)initWithConfig:(BDLPlayerConfiguration *)config;

/// 设置当前的播放进度
/// @param animated 是否需要动画
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated;
/// 设置缓存进度
/// @param animated 是否需要动画
- (void)setCacheProgress:(CGFloat)progress animated:(BOOL)animated;

/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;

@end

BDLPlayerSpeedView

/// 播放速度
typedef NS_ENUM(NSUInteger, BDLPlayerSpeed) {
    BDLPlayerSpeed200X,  ///< 2 倍速
    BDLPlayerSpeed150X,  ///< 1.5 倍速
    BDLPlayerSpeed125X,  ///< 1.25 倍速
    BDLPlayerSpeed100X,  ///< 正常播放
    BDLPlayerSpeed075X,  ///< 0.75 倍速
    BDLPlayerSpeed050X,  ///< 0.5 倍速
};

@class BDLPlayerSpeedView;

/// 倍速选择 view 的代理方法
@protocol BDLPlayerSpeedViewDelegate <NSObject>
/// 在倍速改变时调用该方法
- (void)speedView:(BDLPlayerSpeedView *)speedView speedDidChange:(BDLPlayerSpeed)speed;

@end
/// 倍速选择 view
@interface BDLPlayerSpeedView : BDLPopupBottomOrRightShowBaseView <BDLLanguageService>

/// 自定义倍速按钮
/// @param buttons 倍速按钮数组
/// @param selectedIndex 当前选中的数组下标
@property (nonatomic, copy, nullable) void (^customizeSpeedButtons)(NSArray<UIButton *> * buttons, NSUInteger selectedIndex);

/// 代理方法
@property (nonatomic, weak) id<BDLPlayerSpeedViewDelegate> delegate;

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param config 当前配置
- (instancetype)initWithPortrait:(BOOL)isPortrait config:(BDLPlayerConfiguration *)config;

/// 当前是否为全屏
@property (nonatomic, assign) BOOL fullScreen;
/// 当前播放速度
@property (nonatomic, assign) BDLPlayerSpeed speed;

/// 根据枚举值切换倍速的值
+ (CGFloat)valueFromSpeed:(BDLPlayerSpeed)speed;
/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;

@end

BDLBasePlayerConfiguration

/// 独立播放器配置
@interface BDLBasePlayerConfiguration : NSObject
 
/// 设置是否自动播放直播
@property (nonatomic, assign) BOOL liveAutoPlay;
/// 设置是否自动播放预告
@property (nonatomic, assign) BOOL previewAutoPlay;
/// 设置是否自动播放回放
@property (nonatomic, assign) BOOL playbackAutoPlay;
/// 设置预告结束后是否自动重播
@property (nonatomic, assign) BOOL previewAutoReplay;
/// 设置回放结束后是否自动重播
@property (nonatomic, assign) BOOL playbackAutoReplay;
/// 设置是否开启点播视频的自动断点续播
@property (nonatomic, assign) BOOL vodAutoContinuePlayback;
 
@end

BDLPlayerBaseConfiguration

/// 播放器基类配置
@interface BDLPlayerBaseConfiguration : NSObject
 
/// 直播从后台切回前台是否自动播放
@property (nonatomic, assign) BOOL liveEnterForegroundAutoPlay;
/// 预告从后台切回前台是否自动播放
@property (nonatomic, assign) BOOL previewEnterForegroundAutoPlay;
/// 回放从后台切回前台是否自动播放
@property (nonatomic, assign) BOOL playbackEnterForegroundAutoPlay;
 
/// 重试按钮文字
@property (nonatomic, copy) NSString *retryButtonTitle;
/// 重试按钮圆角
@property (nonatomic, assign) CGFloat retryButtonCornerRadius;
/// 重试按钮背景颜色
@property (nonatomic, strong) UIColor *retryButtonBackgroundColor;
 
/// 重播提示文案
@property (nonatomic, copy) NSString *replayText;
/// 重播提示文案文字颜色
@property (nonatomic, strong) UIColor *replayTextColor;
/// 重播按钮图片
@property (nonatomic, strong) UIImage *replayButtonNormalImage;
/// 重播按钮图片大小
@property (nonatomic, assign) CGSize replayButtonNormalImageSize;
/// 重播按钮圆角
@property (nonatomic, assign) CGFloat replayButtonCornerRadius;
 
/// 加载中图片
@property (nonatomic, strong) UIImage *loadingImage;
/// 加载中图片大小
@property (nonatomic, assign) CGSize loadingImageSize;
 
@end

BDLPlayerCommonConfiguration

/// 播放器公用配置
@interface BDLPlayerCommonConfiguration : NSObject

/// 视频画面的填充模式,详见 BDLPlayerScalingMode
@property (nonatomic, assign) BDLPlayerScalingMode scalingMode;
/// 播放按钮图片
@property (nonatomic, strong) UIImage *playButtonNormalImage;
/// 播放按钮选中的图片,即暂停按钮图片
@property (nonatomic, strong) UIImage *playButtonSelectedImage;
/// 播放器中间的播放按钮图片
@property (nonatomic, strong) UIImage *centerPlayButtonNormalImage;
/// 刷新按钮图片
@property (nonatomic, strong) UIImage *refreshButtonNormalImage;
/// 刷新按钮是否居左(默认不居左)
@property (nonatomic, assign) BOOL refreshButtonLocation;
/// 全屏按钮图片
@property (nonatomic, strong) UIImage *fullScreenButtonNormalImage;
/// 全屏按钮选中的图片
@property (nonatomic, strong) UIImage *fullScreenButtonSelectedImage;
/// 是否支持进入全屏模式。默认为 YES
/// YES:支持,播放器内显示全屏按钮。全屏按钮可在竖屏直播间的直播或点播源流画面宽大于高时以及横屏直播间内显示
/// NO:不支持,播放器内不显示全屏按钮
@property (nonatomic, assign) BOOL enterFullScreenEnable;
/// 退出全屏按钮图片
@property (nonatomic, strong) UIImage *exitFullScreenButtonNormalImage;
/// 主题色,即已播放进度条的背景颜色
@property (nonatomic, strong) UIColor *themeColor;
/// 当前时间标签颜色
@property (nonatomic, strong) UIColor *currentTimeColor;
/// 总时间标签颜色
@property (nonatomic, strong) UIColor *totalTimeColor;
/// 预告/直播已结束 toast 字体
@property (nonatomic, assign) UIFont *toastFont;
/// 预告/直播已结束 toast 圆角
@property (nonatomic, assign) CGFloat toastCornerRadius;
/// 预告/直播已结束 toast 左右边距
@property (nonatomic, assign) CGFloat toastHorizontalEdge;
/// 预告/直播已结束 toast 上下边距
@property (nonatomic, assign) CGFloat toastVerticalEdge;
/// 预告/直播已结束 toast 位置
@property (nonatomic, assign) CGFloat toastCenterYOffset;
 
/// 提示频率
/// -1: 每次都提示
/// 0: 永不提示
/// >0: 提示次数, 默认为 1
@property (nonatomic, assign) NSInteger wwanPromptCount;
/// 流量访问提示文案
@property (nonatomic, copy) NSString *viaWWANText;
/// 断网提示文案
@property (nonatomic, copy) NSString *networkNotReachableText;
/// 提示文案文字颜色
@property (nonatomic, strong) UIColor *promptTextColor;
 
/// 是否开启音频抢占管理
/// YES:切换至后台期间,暂停播放未开启后台音频播放以及系统画中画的视频。重新切换至前台后,自动播放开启了自动播放的视频
/// NO:如果视频正在播放且开启了后台音频播放,切换至后台后会继续播放音频,如果视频暂停时被切换至后台,则仍然暂停播放。重新切换至前台后,播放状态与后台期间保持一致,后台播放音频则切换至前台后继续播放视频,后台暂停播放则切换至前台仍然暂停播放
@property (nonatomic, assign) BOOL enableAudioPreemption;
/// 是否开启后台音频播放
@property (nonatomic, assign) BOOL enableBackgroundAudio;
/// 直播状态退出是否开启系统画中画
@property (nonatomic, assign) BOOL enableLivePiP API_AVAILABLE(ios(14.0));
/// 点播状态退出是否开启系统画中画
@property (nonatomic, assign) BOOL enableVodPiP API_AVAILABLE(ios(14.0));
/// 直播状态退出是否开启浮窗(InApp 画中画) 
/// 该方法自 1.29.1 版本开始不再支持使用,您可以使用 BDLLivePullViewControllerConfig 中的 shouldShowInAppPipIfAvailable 方法替代之
@property (nonatomic, assign) BOOL enableInAppLivePiP;
/// 点播状态退出是否开启浮窗(InApp 画中画)
/// 该方法自 1.29.1 版本开始不再支持使用,您可以使用 BDLLivePullViewControllerConfig 中的 shouldShowInAppPipIfAvailable 方法替代之
@property (nonatomic, assign) BOOL enableInAppVodPiP;
/// 关闭浮窗图标
@property (nonatomic, strong) UIImage *floatingCloseImage;
/// 关闭浮窗图标大小
@property (nonatomic, assign) CGSize floatingCloseImageSize;
/// 浮窗边框宽度
@property (nonatomic, assign) CGFloat floatingViewBorderWidth;
/// 浮窗边框颜色
@property (nonatomic, strong) UIColor *floatingViewBorderColor;
/// 浮窗圆角
@property (nonatomic, assign) CGFloat floatingViewCornerRadius;
/// 切换清晰度后是否立即关闭清晰度选择界面
@property (nonatomic, assign) BOOL closeResolutionViewAtOnce;
/// 切换倍速后是否立即关闭倍速选择界面
@property (nonatomic, assign) BOOL closeSpeedViewAtOnce; 
 
@end

BDLPlayerPortraitConfiguration

/// 竖屏播放器配置
@interface BDLPlayerPortraitConfiguration : BDLPlayerBaseConfiguration

/// 重播按钮背景颜色 
@property (nonatomic, strong) UIColor *replayButtonBackgroundColor;
 
@end

BDLPlayerLandscapeConfiguration

/// 横屏播放器配置
@interface BDLPlayerLandscapeConfiguration : BDLPlayerBaseConfiguration

/// 播放器控件风格
@property (nonatomic, assign) BDLPlayerControlViewMode controlViewMode;
/// 重播界面背景颜色
@property (nonatomic, strong) UIColor *replayViewBackgroundColor;
/// 人气标签字体
@property (nonatomic, strong) UIFont *popularityFont;
/// 人气图标
@property (nonatomic, strong) UIImage *popularityImage;
 
@end

BDLPlayerConfiguration

/// 播放器配置
@interface BDLPlayerConfiguration : NSObject
 
/// 播放器公用配置,详见 BDLPlayerCommonConfiguration
@property (nonatomic, strong) BDLPlayerCommonConfiguration *common;
/// 独立播放器配置,详见 BDLBasePlayerConfiguration
@property (nonatomic, strong) BDLBasePlayerConfiguration *basePlayerConfig;
/// 竖屏播放器配置,详见 BDLPlayerPortraitConfiguration
@property (nonatomic, strong) BDLPlayerPortraitConfiguration *portrait;
/// 横屏播放器配置,详见 BDLPlayerLandscapeConfiguration
@property (nonatomic, strong) BDLPlayerLandscapeConfiguration *landscape;
 
@end

弹窗定制

BDLAlertController

/// 弹窗类型
typedef NS_ENUM(NSUInteger, BDLAlertControllerType) {
    /// 评论详情
    BDLAlertControllerTypeComment = 1,
    /// H5 页面,例如点击商品卡片或广告后浮层展示的页面
    BDLAlertControllerTypeURL = 2,
    /// 自定义 view
    BDLAlertControllerTypeCustom,
};

/// 弹窗 controller
@interface BDLAlertController : UIViewController

/// AlertController 当前持有的配置
@property (nonatomic, strong, readonly) BDLAlertControllerConfiguration *config;

/// 返回按钮
/// 仅当 BDLAlertControllerType 为 BDLAlertControllerTypeComment 时有效
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly, nullable) UIButton *backButton;
/// 文本显示
/// 仅当 BDLAlertControllerType 为 BDLAlertControllerTypeComment 时有效
/// 可自定义除 attributedText、font 外的所有属性
/// 如需自定义 font,可通过 BDLAlertControllerConfiguration.alertContentFont 设置
@property (nonatomic, strong, readonly, nullable) UITextView *textView;
/// 显示内容的 WKWebView
/// 仅当 BDLAlertControllerType 为 BDLAlertControllerTypeURL 时有效 
@property (nonatomic, strong, readonly, nullable) WKWebView *webView;

/// BDLAlertControllerTypeComment 类型的初始化方法
/// @param comment 需要显示的评论
/// @param isPortrait 是否为竖屏
- (instancetype)initWithComment:(BDLCommentModel *)comment
                     isPortrait:(BOOL)isPortrait;

/// BDLAlertControllerTypeURL 类型的初始化方法
/// @param redirectUrl 需要加载的 URL
- (instancetype)initWithRedirectUrl:(NSString *)redirectUrl;

/// BDLAlertControllerTypeCustom 类型的初始化方法
/// @param view 自定义 view,不受 BDLLiveEngine.sharedInstance.getLiveRoomConfiguration.alertControllerConfig 影响
/// @param expectHeight 自定义 view 的预期高度
- (instancetype)initWithContentView:(UIView *)view expectHeight:(CGFloat)expectHeight;

/// AlertController 的类型 
@property (nonatomic, assign, readonly) BDLAlertControllerType type;

/// 退出 AlertController 时,使用以下方法,而非系统的 dismiss(dismissViewControllerAnimated:completion:)方法
- (void)dismissAlertControllerAnimated:(BOOL)flag completion:(void (^ __nullable)(void))completion;

/// 请使用 dismissAlertControllerAnimated:completion: 方法,而非以下方法
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^ __nullable)(void))completion DEPRECATED_MSG_ATTRIBUTE("use dismissAlertControllerAnimated:completion: instead");

/// 评论中 URL 点击回调,仅当 BDLAlertControllerType 为 BDLAlertControllerTypeComment 时有效
@property (nonatomic, copy, nullable) void (^urlClickBlock)(NSURL *url);
/// 评论昵称点击回调,仅当 BDLAlertControllerType 为 BDLAlertControllerTypeComment 时有效
@property (nonatomic, copy, nullable) void (^commentNicknameClick)(BDLAlertController *controller, BDLCommentModel *comment);

@end

BDLAlertControllerConfiguration

/// 弹窗配置
@interface BDLAlertControllerConfiguration : BDLRTBaseConfiguration

/// 内容区域的高度
@property (nonatomic, assign) CGFloat viewHeight;
/// 颜色主题
/// 参数值设置为 custom 或 light 时,内容区域的颜色为白色,其他情况为黑色(#20202A)
@property (nonatomic, copy, nullable) NSString *colorTheme;
/// 竖屏背景颜色
@property (nonatomic, strong) UIColor *portraitContentBackgroundColor;
/// 竖屏文字颜色
@property (nonatomic, strong) UIColor *portraitTopFontColor;
/// 弹窗内容字体
@property (nonatomic, strong) UIFont *alertContentFont;
 
/// 置顶评论详情面板的标题是否居左(默认居中)
@property (nonatomic, assign) BOOL topTitleAlignmentLeft;
/// 点击评论中链接是否开启浮层
@property (nonatomic, assign) BOOL commentUrlFloatingEnable;

@end

更多选项弹窗定制

在竖屏直播间内点击右下方的更多(...)图标后,即可弹出更多选项弹窗。

BDLMoreOptionsController

/// BDLMoreOptionsController 实现了更多选项弹窗内多语言切换、清屏、分享、清晰度选择按钮的显示与隐藏逻辑
@interface BDLMoreOptionsController : NSObject <BDLLanguageService, BDLBasicService, BDLMoreOptionsProvider>

/// 多语言切换按钮点击回调
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock multiLanguageClickBlock;

/// 清屏按钮点击回调
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock clearScreenClickBlock;

/// 分享按钮点击回调
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock shareClickBlock;

/// 清晰度选择按钮点击回调
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock resolutionClickBlock;

/// 多语言变化回调
@property (nonatomic, copy, nullable) void(^ multiLanguageChangeBlock)(BDLMoreOptionsController *controller);

/// 多语言切换、清屏、分享或清晰度选择按钮显示状态变化回调
@property (nonatomic, copy, nullable) void(^ modelsChangeBlock)(BDLMoreOptionsController *controller);

@end

BDLMoreOptionsView

typedef void (^BDLMoreOptionsViewBlock)(void);

/// 更多选项弹窗 view
@interface BDLMoreOptionsView : BDLPopupBottomShowBaseView <BDLLanguageService, BDLMoreOptionsService>

/// 多语言切换按钮点击回调
/// 该属性自 1.32.0 版本开始不再支持使用,您可以使用 BDLMoreOptionsController 的 multiLanguageClickBlock 替代之
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock multiLanguageClickBlock;
/// 清屏按钮点击回调
/// 该属性自 1.32.0 版本开始不再支持使用,您可以使用 BDLMoreOptionsController 的 clearScreenClickBlock 替代之
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock clearScreenClickBlock;
/// 关闭更多选项弹窗的点击回调
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock closeClickBlock;
/// 分享按钮点击回调
/// 该属性自 1.32.0 版本开始不再支持使用,您可以使用 BDLMoreOptionsController 的 shareClickBlock 替代之 
@property (nonatomic, copy, nullable) BDLMoreOptionsViewBlock shareClickBlock;
/// 背景 view
/// 可自定义所有属性
/// 内部使用 Masonry 进行布局,如需修改 frame,推荐使用 mas_remake 进行修改
/// 该属性自 1.32.0 版本开始不再支持使用,您可以使用 BDLPopupBaseView 的 contentView 替代之
@property (nonatomic, strong, readonly) UIView *bottomBackgroundView;
/// 选项 view
/// 可自定义除 frame 外的所有属性
@property (nonatomic, strong, readonly) UICollectionView *optionsView;
/// 底部取消按钮和选项间的分割线
/// 可自定义所有属性
/// 内部使用 Masonry 进行布局,如需修改 frame,推荐使用 mas_remake 进行修改
@property (nonatomic, strong, readonly) UIView *splitView;
/// 底部取消按钮
/// 可自定义所有属性
/// 内部使用 Masonry 进行布局,如需修改 frame,推荐使用 mas_remake 进行修改
@property (nonatomic, strong, readonly) UIButton *cancelButton;
/// 更多选项弹窗配置,详见 BDLMoreOptionsViewConfiguration
/// 该属性自 1.32.0 版本开始不再支持使用,您可以使用 BDLLiveRoomConfiguration 中的 moreOptionsViewConfig 属性替代之
@property (nonatomic, strong, readonly) BDLMoreOptionsViewConfiguration *config;

@end

BDLMoreOptionsViewConfiguration

/// 更多选项弹窗配置
@interface BDLMoreOptionsViewConfiguration : BDLRTBaseConfiguration

/// 多语言切换按钮的图片
@property (nonatomic, strong) UIImage *multiLanguageImage;
/// 清屏按钮的图片
@property (nonatomic, strong) UIImage *clearScreenImage;
/// 分享按钮的图片
@property (nonatomic, strong) UIImage *shareImage;
/// 清晰度选择按钮的图片
@property (nonatomic, strong) UIImage *resolutionImage;
@end

抽奖定制

BDLFloatingAwardView

/// 抽奖浮窗类型
typedef NS_ENUM(NSUInteger, BDLFloatingAwardViewType) {
    BDLFloatingAwardViewTypeOngoing, ///< 正在进行的抽奖
    BDLFloatingAwardViewTypeOpened, ///< 已开奖的抽奖
};

/// 抽奖浮窗 view
@interface BDLFloatingAwardView : BDLBaseView <BDLInteractiveToolService, BDLLanguageService>

/// 初始化方法
/// @param type 类型(抽奖正在进行中或已开奖)
- (instancetype)initWithType:(BDLFloatingAwardViewType)type;
/// 初始化方法传递进来的 type
@property (nonatomic, assign, readonly) BDLFloatingAwardViewType type;
/// 当前 view 对应的抽奖数据。SDK 内部会根据 type 获取最新的抽奖数据
@property (nonatomic, strong, readonly) BDLInteractiveAwardModel *model;
/// 自定义 imageView
@property (nonatomic, copy, nullable) void (^customImageViewBlock)(BDLFloatingAwardView *view);
/// 抽奖浮窗点击回调
@property (nonatomic, copy, nullable) void (^viewTappedBlock)(BDLFloatingAwardView *view);
/// 关闭按钮点击回调
@property (nonatomic, copy, nullable) void (^closeButtonClickedBlock)(BDLFloatingAwardView *view);
/// 关闭按钮
@property (nonatomic, strong, readonly) UIButton *closeButton;
/// imageView
@property (nonatomic, strong, readonly) UIImageView *imageView;
/// 倒计时 label,仅当 BDLFloatingAwardViewType 为 BDLFloatingAwardViewTypeOngoing 且是自动开奖的抽奖时才会显示
/// 可自定义除 text 外的所有属性
@property (nonatomic, strong, readonly, nullable) UILabel *countdownLabel;
/// “点击抽奖”/“已开奖”文案的 label
/// 可自定义除 text 外的所有属性
@property (nonatomic, strong, readonly) UILabel *statusLabel;
/// statusLabel 的背景 view
@property (nonatomic, strong, readonly) UIView *statusView;

@end

注意

BDLFloatingAwardView 自 1.28.0 版本开始不再支持使用。1.28.0 版本及以后,SDK 使用 BDLFloatingInteractiveToolView 实现抽奖浮窗相关的功能。

BDLAwardContactView

/// 完善中奖信息弹窗 view
/// 以下文本显示的控件均不支持自定义文字
/// 如需修改 label.text,您可自定义类,重写 refreshMultiLanguage 方法,调用 super 后实现自己的修改
@interface BDLAwardContactView : BDLPopupCenterShowBaseView <BDLLanguageService>

/// 初始化方法
/// @param award 当前的抽奖
/// @param awardUser 中奖观众的 model
- (instancetype)initWithAward:(BDLInteractiveAwardModel *)award awardUser:(BDLAwardUserModel *)awardUser;

/// 初始化方法传递进来的 award
@property (nonatomic, strong, readonly) BDLInteractiveAwardModel *award;
/// 初始化方法传递进来的 awardUser
@property (nonatomic, strong, readonly) BDLAwardUserModel *awardUser;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType languageType;
/// 顶部背景的 imageView,支持修改图片
@property (nonatomic, strong, readonly) UIImageView *topBackgroundImageView;
/// 标题 label
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// 手机号 label
@property (nonatomic, strong, readonly) UILabel *phoneHintLabel;
/// 手机号输入框
@property (nonatomic, strong, readonly) UITextField *phoneTextField;
/// 手机号输入错误提示 label
@property (nonatomic, strong, readonly) UILabel *phoneErrorHintLabel;
/// 地址 label
@property (nonatomic, strong, readonly) UILabel *addressHintLabel;
/// 地址输入框
@property (nonatomic, strong, readonly) UITextField *addressTextField;
/// 地址输入错误提示 label
@property (nonatomic, strong, readonly) UILabel *addressErrorHintLabel;
/// 确定按钮
/// 不支持自定义背景颜色
@property (nonatomic, strong, readonly) UIButton *confirmButton;
/// “请尽快填写中奖信息,避免错失奖品\n奖品解释权和提供方归主办方所有”文案的 label
@property (nonatomic, strong, readonly) UILabel *hintLabel;
/// 关闭按钮
@property (nonatomic, strong, readonly) UIButton *closeButton;
/// 确定按钮点击回调
@property (nonatomic, copy) void (^confirmButtonClickBlock)(BDLAwardContactView *view, UIButton *confirmButton);
/// 关闭按钮点击回调
@property (nonatomic, copy) void (^closeButtonClickBlock)(BDLAwardContactView *view, UIButton *closeButton);

@end

BDLAwardCountdownView

/// 抽奖倒计时 view
@interface BDLAwardCountdownView : UIView
/// 数字 view 的数组
@property (nonatomic, copy) NSArray<BDLAwardNumberView *> *numberViews;
/// 冒号 label 的数组
@property (nonatomic, copy) NSArray<UILabel *> *colons;
/// 更新界面
/// @param countdown 倒计时剩余时间,单位为秒
- (void)updateViewWithCountdown:(NSInteger)countdown;

@end

BDLAwardConditionView

/// 抽奖详情中参与条件 view
@interface BDLAwardConditionView : BDLBaseView <BDLLanguageService>

/// “参与条件”文案的 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// “点击一键参与自动完成”文案的 label
/// 不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *subTitleLabel;
/// 具体参与条件的 label
/// 不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *conditionLabel;
/// 参与条件勾选状态的 imageView,支持自定义图片
@property (nonatomic, strong, readonly) UIImageView *checkMarkImageView;

@end

BDLAwardDetailsView

/// 抽奖详情 view
@interface BDLAwardDetailsView : BDLPopupBottomShowBaseView <BDLLanguageService, BDLInteractiveToolService>

/// 初始化方法
/// @param model 抽奖信息
- (instancetype)initWithModel:(BDLInteractiveAwardModel *)model;
/// 关闭按钮点击回调
@property (nonatomic, copy, nullable) void (^closeButtonClickedBlock)(BDLAwardDetailsView *view);
/// 参与按钮点击回调
@property (nonatomic, copy, nullable) void (^participateButtonClickedBlock)(BDLAwardDetailsView *view);
/// 初始化方法传递进来的 model
@property (nonatomic, strong, readonly) BDLInteractiveAwardModel *model;
/// 关闭按钮,支持自定义所有属性
@property (nonatomic, strong, readonly) UIButton *closeButton;
/// 顶部的 imageView,支持自定义所有属性
@property (nonatomic, strong, readonly) UIImageView *headerImageView;
/// 即将开奖 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// 倒计时 view,详见 BDLAwardCountdownView
@property (nonatomic, strong, readonly) BDLAwardCountdownView *countdownView;
/// 奖品信息 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *awardLabel;
/// 奖品数量 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *awardCountLabel;
/// 参与条件 view,详见 BDLAwardConditionView
@property (nonatomic, strong, readonly, nullable) BDLAwardConditionView *conditionView;
/// 参与按钮
@property (nonatomic, strong, readonly) UIButton *participateButton;

@end

BDLAwardNoticeView

/// 抽奖通知 view
@interface BDLAwardNoticeView : UIView <BDLLanguageService>
/// 当前所有支持的语言类型
@property (nonatomic, copy, readonly) NSArray *langTypes;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType langType;
/// 背景图,可自定义任意属性
@property (nonatomic, strong, readonly) UIImageView *bgImageView;
/// “直播间发起了一场抽奖”文案 label
/// 不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// 参与按钮
/// 不支持自定义 Normal 状态的 text
@property (nonatomic, strong, readonly) UIButton *participateButton;
/// 当前通知对应的抽奖信息
@property (nonatomic, strong) BDLInteractiveAwardModel *award;
/// 参与按钮点击回调
@property (nonatomic, copy) void(^onParticipateClickBlock)(BDLAwardNoticeView *view);

@end

BDLAwardNumberView

/// 抽奖倒计时数字的 view
@interface BDLAwardNumberView : UIView
/// 数字 label。不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;

@end

BDLAwardResultView

/// 抽奖结果 view
@interface BDLAwardResultView : BDLPopupCenterShowBaseView <BDLLanguageService>

/// 初始化方法
/// @param awardModel 抽奖信息
/// @param userModel 当前观众的中奖情况
- (instancetype)initWithAwardModel:(BDLInteractiveAwardModel *)awardModel userModel:(BDLAwardUserModel *)userModel;
/// 关闭按钮点击回调
@property (nonatomic, copy) void (^closeButtonClickedBlock)(BDLAwardResultView *view);
/// 完善中奖信息按钮点击回调
/// 对于未中奖观众,则是知道了按钮的点击回调。可以调用 [self shouldShowAwardContactEntrance] 判断是否为完善中奖信息按钮
@property (nonatomic, copy) void (^completeInfoButtonClickedBlock)(BDLAwardResultView *view);
/// 查看中奖结果按钮点击回调
@property (nonatomic, copy) void (^awardWinnersButtonClickedBlock)(BDLAwardResultView *view);
/// 初始化方法传递进来的 awardModel
@property (nonatomic, strong, readonly) BDLInteractiveAwardModel *awardModel;
/// 初始化方法传递进来的 userModel
@property (nonatomic, strong, readonly) BDLAwardUserModel *userModel;
/// imageView,不支持自定义 image
@property (nonatomic, strong, readonly) UIImageView *imageView;
/// “恭喜你,获得奖品”/“很遗憾,你没有中奖”文案的 label
/// 不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// 完善中奖信息/知道了按钮,不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *completeInfoButton;
/// 查看中奖结果按钮,不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *awardWinnersButton;
/// 奖品条款 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *termsLabel;
/// 关闭按钮,支持自定义
@property (nonatomic, strong, readonly) UIButton *closeButton;

/// 是否显示完善中奖信息入口
- (BOOL)shouldShowAwardContactEntrance;

@end

BDLAwardWinnersView

/// 中奖名单 view
@interface BDLAwardWinnersView : BDLPopupCenterShowBaseView <BDLLanguageService>
/// 初始化
/// @param awardId 当前抽奖的 ID
- (instancetype)initWithAwardId:(NSNumber *)awardId;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType languageType;
/// 顶部背景的 imageView,支持自定义
@property (nonatomic, strong, readonly) UIImageView *topBackgroundImageView;
/// 关闭按钮,支持自定义
@property (nonatomic, strong, readonly) UIButton *closeButton;
/// 中奖名单标题 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// “共 X 人中奖”文案的 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *countLabel;
/// 中奖名单的容器 tableView,支持自定义
@property (nonatomic, strong, readonly) UITableView *tableView;
/// 加载中的 view
@property (nonatomic, strong, readonly) BDLLoadingView *loadingView;
/// “无人参与该抽奖活动”文案的 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *emptyHintLabel; 
/// “中奖用户尽快在图文直播-抽奖入口处填写中奖信息,避免错失奖品~”文案的 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *bottomHintLabel;

@end

BDLAwardConfiguration

/// 抽奖配置
@interface BDLAwardConfiguration : BDLRTBaseConfiguration

/// 是否需要完善中奖信息
@property (nonatomic, assign) BOOL needAwardContact;
 
@end

连麦定制

BDLAudienceLinkExitWarningView

/// 退出观众连麦时的提示 view
@interface BDLAudienceLinkExitWarningView : BDLPopupBottomShowBaseView <BDLLanguageService>
/// “确认退出观众连麦吗?” 提示 label
/// 不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// “当前正在连麦中,关闭直播连麦将\n退出当前连麦” 提示 label
/// 不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *subTitleLabel;
/// subTitleLabel 和确认按钮之间的分割线
@property (nonatomic, strong, readonly) UIView *sepLine;
/// 确认按钮
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *confirmButton;
/// 确认按钮和取消按钮之间的灰色区域
@property (nonatomic, strong, readonly) UIView *greyView;
/// 取消按钮
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *cancelButton;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType langType;
/// 确认按钮点击回调
@property (nonatomic, copy, nullable) void(^onConfirmClickCallback)(BDLAudienceLinkExitWarningView *view, UIButton *button);
/// 取消按钮点击回调
@property (nonatomic, copy, nullable) void(^onCancelClickCallback)(BDLAudienceLinkExitWarningView *view, UIButton *button);

@end

BDLAudienceLinkMenuView

/// 按钮类型
typedef NS_ENUM(NSInteger, BDLAudienceLinkMenuViewButtonTag) {
    BDLAudienceLinkMenuViewButtonTagSwitchCamera,  ///< 翻转摄像头
    BDLAudienceLinkMenuViewButtonTagAudioSwitch,   ///< 静音/取消静音
    BDLAudienceLinkMenuViewButtonTagVideoSwitch,   ///< 打开摄像头/关闭摄像头
    BDLAudienceLinkMenuViewButtonTagEndLink,       ///< 断开连麦
};

/// 连麦菜单选项 view
@interface BDLAudienceLinkMenuView : BDLPopupBottomShowBaseView <BDLLanguageService>

/// 包含选项的容器 view,可通过 containerView.arrangedSubviews 获取到选项按钮(UIButton)
/// 可通过 tag 区分不同的按钮、通过 button.select 设置按钮的选中与未选中状态。其中静音按钮的选中状态为取消静音按钮,摄像头按钮的选中状态为打开摄像头按钮、未选中状态为关闭摄像头按钮,翻转摄像头和断开连麦按钮无选中状态的变化。
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIStackView *containerView;
/// 选项按钮和取消按钮之间的分割线
@property (nonatomic, strong, readonly) UIView *sepLine;
/// 取消按钮
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *cancelButton;
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType langType;
/// 翻转摄像头按钮点击回调
@property (nonatomic, copy, nullable) void(^onSwitchCameraClickCallback)(BDLAudienceLinkMenuView *view, UIButton *button);
/// 静音/取消静音按钮点击回调
@property (nonatomic, copy, nullable) void(^onAudioClickCallback)(BDLAudienceLinkMenuView *view, UIButton *button);
/// 打开/关闭摄像头按钮点击回调
@property (nonatomic, copy, nullable) void(^onVideoClickCallback)(BDLAudienceLinkMenuView *view, UIButton *button);
/// 断开连麦按钮点击回调
@property (nonatomic, copy, nullable) void(^onExitClickCallback)(BDLAudienceLinkMenuView *view, UIButton *button);
/// 取消按钮点击回调
@property (nonatomic, copy, nullable) void(^onCancelClickCallback)(BDLAudienceLinkMenuView *view, UIButton *button);

@end

其他定制

BDLPopupInputView

/// 昵称输入框 view
@interface BDLPopupInputView : BDLBaseView
/// 关闭按钮,支持自定义
@property (nonatomic, strong, readonly) UIButton *closeButton;

/// 输入框
/// 可自定义除 attributedPlaceholder、backgroundColor、textColor、font 外的所有属性
@property (nonatomic, strong, readonly) UITextField *inputTextField;
/// 确认按钮点击回调
/// @param text 输入的昵称
@property (nonatomic, copy, nullable) void (^confirmBlock)(NSString *__nullable text);
/// 关闭按钮点击回调
@property (nonatomic, copy, nullable) void (^closeBlock)(void);

@end

BDLPopupInputViewConfiguration

/// 昵称输入框配置
@interface BDLPopupInputViewConfiguration : BDLRTBaseConfiguration
/// 输入框占位文字
@property (nonatomic, copy) NSString *inputPlaceholder;
/// 标题文字
@property (nonatomic, copy) NSString *titleText;
/// 确认按钮文字
@property (nonatomic, copy) NSString *confirmTitle;
/// 标题字体
@property (nonatomic, strong) UIFont *titleFont;
/// 输入框字体
@property (nonatomic, strong) UIFont *textFieldFont;
/// 确认按钮文字字体
@property (nonatomic, strong) UIFont *confirmFont;
/// 确认按钮背景颜色
@property (nonatomic, strong) UIColor *confirmBackgroundColor;
/// 输入框占位文字字体
@property (nonatomic, strong) UIFont *placeholderFont;
 
@end

BDLContinuePlaybackToastView

/// 断点续播提示 view,仅当观看页语言为简体中文时才会显示该提示
@interface BDLContinuePlaybackToastView : UIView
/// 断点续播提示 label,不支持自定义 text
@property (nonatomic, strong) UILabel *label;
/// 初始化
/// @param time 断点续播时间,即上次播放结束的时间点
- (instancetype)initWithPlaybackTime:(NSTimeInterval)time;

@end

BDLCountdownView

@class BDLCountdownView;
/// 直播间倒计时 view 的代理方法
@protocol BDLCountdownViewDelegate <NSObject>
/// 在倒计时结束时调用该方法
- (void)countdownViewDidFinish:(BDLCountdownView *)countdownView;
/// 在倒计时被取消时调用该方法
- (void)countdownViewDidCancel:(BDLCountdownView *)countdownView;

@end

/// 直播间倒计时 view,包含直播预约
@interface BDLCountdownView : BDLBaseView <BDLBasicService, BDLLanguageService>
/// 初始化
/// @param isPortrait 是否为竖屏
- (instancetype)initWithPortrait:(BOOL)isPortrait;
/// 代理方法
@property (nonatomic, weak) id<BDLCountdownViewDelegate> delegate;
/// “距离直播开始还有”文案的 label,不支持自定义位置和 text
@property (nonatomic, strong, readonly) UILabel *hintLabel;
/// 当前剩余时间的 label,不支持自定义 text
@property (nonatomic, strong, readonly) UILabel *countdownLabel;
/// 预约按钮,在企业直播控制台开启直播预约功能后才会显示
/// 不支持设置 Normal 和 Disabled 状态的 text
@property (nonatomic, strong, readonly) UIButton *reservationButton;

/// 预约成功的 toast 文案
@property (nonatomic, copy) NSString *addEventSuccessToast;
/// 预约失败的 toast 文案
@property (nonatomic, copy) NSString *addEventFailToast;

/// 停止倒计时
- (void)cancel;

@end

BDLLoadingView

/// 加载 view
@interface BDLLoadingView : UIView

/// 加载图片的 imageView
@property (nonatomic, strong, readonly) UIImageView *imageView;
/// 开始动画
- (void)showAnimation;
/// 结束动画
- (void)hideAnimation;

@end

BDLNetworkNotReachableView

@class BDLNetworkNotReachableView;
/// 断网提示 view 的代理方法
@protocol BDLNetworkNotReachableViewDelegate <NSObject>
/// 在观众点击重试按钮时调用该方法
- (void)networkNotReachableView:(BDLNetworkNotReachableView *)notReachableview retryButtonDidTouch:(UIButton *)button;

@end

/// 断网提示 view
@interface BDLNetworkNotReachableView : BDLBaseView <BDLLanguageService>

/// 代理方法
@property (nonatomic, weak) id<BDLNetworkNotReachableViewDelegate> delegate;
/// 提示 label
/// 可通过 config.common.networkNotReachableText 和 config.common.promptTextColor 自定义提示的文字和文字颜色
@property (nonatomic, strong) UILabel *promptLabel;
/// 重试按钮
/// 可通过 config.landscape 或 config.portrait 的 retryButtonBackgroundColor、retryButtonTitle、retryButtonCornerRadius 自定义横竖屏模式下的背景颜色、文字、圆角
@property (nonatomic, strong) UIButton *retryButton;

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param config 当前配置
- (instancetype)initWithPortrait:(BOOL)isPortrait config:(BDLPlayerConfiguration *)config;
/// 根据 config 更新 view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;

@end

BDLNetworkViaWWANView

/// 流量访问提示 view 的代理方法
@protocol BDLNetworkViaWWANViewDelegate <NSObject>
/// 在观众点击流量访问提示 view 时调用该方法
- (void)networkViaWWANViewDidTouch:(BDLNetworkViaWWANView *)wwanView;

@end

/// 流量访问提示 view
@interface BDLNetworkViaWWANView : BDLBaseView <BDLLanguageService>

/// 代理方法
@property (nonatomic, weak) id<BDLNetworkViaWWANViewDelegate> delegate;
/// 提示 label
/// 可通过 config.common.viaWWANText、config.common.promptTextColor 自定义提示的文字和文字颜色
@property (nonatomic, strong) UILabel *promptLabel;
/// 背景 view,支持自定义
@property (nonatomic, strong) UIView *contentView;

/// 初始化
/// @param isPortrait 是否为竖屏
/// @param config 当前配置
- (instancetype)initWithPortrait:(BOOL)isPortrait config:(BDLPlayerConfiguration *)config;
/// 根据 config 更新view
- (void)updateWithConfig:(BDLPlayerConfiguration *)config;

@end

BDLNoticeContainerView

/// 通知的容器 view
@interface BDLNoticeContainerView : BDLBaseView <BDLNoticeService, BDLInteractiveToolService>
/// 自定义抽奖通知 view
@property (nonatomic, copy) __kindof UIView * (^customizeAwardNoticeView)(BDLNoticeContainerView *view, BDLAwardNoticeView *noticeView, BDLInteractiveAwardModel *award);
/// 自定义自定义通知 view
@property (nonatomic, copy) __kindof UIView * (^customizeCustomNoticeView)(BDLNoticeContainerView *view, BDLCustomNoticeView *noticeView, BDLCustomNotice *notice);
/// 隐藏正在显示的通知 view
- (void)hideShowingNoticeViewWithFinish:(void (^ _Nullable )(void))finish;

@end

BDLCustomNoticeView

/// 自定义通知 view
@interface BDLCustomNoticeView : UIView
/// 初始化方法
/// @param notice 当前要显示的通知
- (instancetype)initWithNotice:(BDLCustomNotice *)notice;
/// 左侧的 imageView,支持自定义
@property (nonatomic, strong, readonly) UIImageView *imageView;
/// 文字 label,支持自定义
@property (nonatomic, strong, readonly) UILabel *label;
/// 初始化方法传递进来的 notice
@property (nonatomic, strong, readonly) BDLCustomNotice *customNotice;

@end

BDLJoinRoomNoticeView

/// 进场消息 view 的协议
@protocol BDLJoinRoomNoticeViewProtocol <NSObject>
/// 更新方法
/// @param user 进入直播间的观众
- (void)updateWithUser:(BDLCommentUserModel *)user;

@end
/// 进场消息 view
@interface BDLJoinRoomNoticeView : BDLBaseView <BDLJoinRoomNoticeViewProtocol, BDLLanguageService>
/// 背景 view
@property (nonatomic, strong, readonly) UIView *backgroundView;
/// 昵称 label,支持自定义
/// 可通过 BDLCommentViewConfiguration 的 nickNameFont、nickNameColor 自定义昵称的字体和文字颜色
@property (nonatomic, strong, readonly) UILabel *nameLabel;
/// “进入了直播间”提示 label,不支持自定义 text
/// 可通过 BDLCommentViewConfiguration 的 commentFont、commentColor 自定义字体和文字颜色
@property (nonatomic, strong, readonly) UILabel *hintLabel;
/// 昵称点击回调
@property (nonatomic, copy) void(^onUserNicknameClickBlock)(BDLJoinRoomNoticeView *view, BDLCommentUserModel *user);

@end

BDLShareView

/// 分享弹窗
@interface BDLShareView : BDLPopupBottomShowBaseView <BDLBasicService>

/// 初始化方法
/// @param shareInfo 分享信息
/// @param url 分享的 URL。如果 shareInfo.customAddress 为空,则分享该 URL
/// @param inviteTokenModel 分享者信息(如观众未登录直播间,则为空值)
- (instancetype)initWithShareInfo:(BDLGetShareInfoResult *)shareInfo url:(NSString *)url inviteTokenModel:(BDLGetInviteTokenResult *)inviteTokenModel;

/// 初始化方法传递进来的 url
@property (nonatomic, strong, readonly, nullable) NSString *url;
/// 初始化方法传递进来的 shareInfo
@property (nonatomic, strong, readonly) BDLGetShareInfoResult *shareInfo;
/// 初始化方法传递进来的 inviteTokenModel
@property (nonatomic, strong, readonly, nullable) BDLGetInviteTokenResult *inviteTokenModel;

/// 海报按钮
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *inviteButton;
/// 复制链接按钮
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *linkButton;
/// 二维码按钮
/// 不支持自定义 Normal 状态的文字
@property (nonatomic, strong, readonly) UIButton *qrCodeButton;

/// 海报按钮点击回调
@property (nonatomic, copy, nullable) void (^onInviteButtonClickBlock)(BDLShareView *view);
/// 复制链接按钮点击回调
@property (nonatomic, copy, nullable) void (^onCopyLinkButtonClickBlock)(BDLShareView *view);
/// 二维码按钮点击回调
@property (nonatomic, copy, nullable) void (^onQRCodeButtonClickBlock)(BDLShareView *view);

@end

BDLRiskWarningView

/// 风险提示 view
@interface BDLRiskWarningView : BDLPopupCenterShowBaseView
/// 当前的语言类型,详见 BDLLanguageType
@property (nonatomic, assign, readonly) BDLLanguageType languageType;
/// 当前所有支持的语言类型
@property (nonatomic, copy, readonly) NSArray *languageTypeArray;
/// 顶部的背景图 view,支持自定义
@property (nonatomic, strong, readonly) UIImageView *topBackgroundImageView;
/// 标题 label,不支持自定义 text。您可以通过企业直播控制台自定义标题
@property (nonatomic, strong, readonly) UILabel *titleLabel;
/// 内容 label,不支持自定义 text。您可以通过企业直播控制台自定义内容
@property (nonatomic, strong, readonly) UILabel *contentLabel;
/// 需滚动查看底部内容时,内容底部的半透明 view,不支持自定义 hidden
@property (nonatomic, strong, readonly) UIView *maskView;
/// 确认按钮,支持自定义除 title(按钮文字)外的所有属性
@property (nonatomic, strong, readonly) UIButton *confirmButton;
/// 确认按钮点击回调
@property (nonatomic, copy) void(^onConfirmButtonClickBlock)(BDLRiskWarningView *view);

@end

BDLPopupBaseView

/// 弹窗基类 view 的协议
@protocol BDLPopupBaseViewProtocol <NSObject>

/// 设置显示弹窗的动画时长
/// @param duration 动画时长。单位:秒。BDLPopupBaseView 的实现时长为 0.3 秒
- (void)setShowAnimationDuration:(NSTimeInterval)duration;

/// 设置隐藏弹窗的动画时长
/// @param hideDuration 动画时长。单位:秒。BDLPopupBaseView 的实现时长为 0.3 秒
- (void)setHideAnimationDuration:(NSTimeInterval)hideDuration;

/// 设置圆角。默认竖屏底部弹窗的左上角和右上角为圆角
- (void)setContentViewCorners:(UIRectCorner)corner;

/// 隐藏弹窗
- (void)hideWithCompletion:(nullable void(^)(BDLPopupBaseView *view))completion;

/// 隐藏弹窗
/// @param animation 隐藏弹窗时需要额外执行的自定义动画
/// @param completion 弹窗隐藏后触发该回调
- (void)hideWithAnimation:(nullable void (^)(void))animation completion:(nullable void (^)(BDLPopupBaseView *view))completion;
@end

/// 底部显示弹窗的协议
@protocol BDLPopupBottomShowViewProtocol <BDLPopupBaseViewProtocol>

/// 弹窗的内容 view 与弹窗底部的间距
- (void)setVerticalOffset:(CGFloat)offset;
/// 底部显示弹窗
- (void)bottomShowInView:(UIView *)superview completion:(nullable void(^)(BDLPopupBaseView *view))completion;

@end

/// 右侧显示弹窗的协议
@protocol BDLPopupRightShowViewProtocol <BDLPopupBaseViewProtocol>
/// 右侧显示弹窗
- (void)rightShowInView:(UIView *)superview completion:(nullable void(^)(BDLPopupBaseView *view))completion;

@end

/// 中间显示弹窗的协议
@protocol BDLPopupCenterShowViewProtocol <BDLPopupBaseViewProtocol>

/// 弹窗的内容 view 与 self.center.y 的间距
- (void)setVerticalOffset:(CGFloat)offset;
/// 中间显示弹窗
- (void)centerShowInView:(UIView *)superview completion:(nullable void(^)(BDLPopupBaseView *view))completion;

@end

/// 底部或者右侧显示弹窗的协议
@protocol BDLPopupBottomOrRightShowViewProtocol <BDLPopupBottomShowViewProtocol, BDLPopupRightShowViewProtocol>

@end

/// 弹窗基类 view
@interface BDLPopupBaseView : BDLBaseView <BDLPopupBaseViewProtocol>

/// 背景点击回调。如果为空,则点击背景无效
@property (nonatomic, copy, nullable) void (^onBackgroundTapCallback)(BDLPopupBaseView *view);
/// 弹窗内容 view。frame 由子类决定
@property (nonatomic, strong, readonly) UIView *contentView;

/// superview 中显示在最上面的 BDLPopupBaseView 实例,即最后显示的弹窗
- (BDLPopupBaseView *)topPopupViewInView:(UIView *)superview;
/// superView 中与 self 相邻的 BDLPopupBaseView 实例,即当前弹窗的前一个弹窗
- (BDLPopupBaseView *)neighborPopupViewInView:(UIView *)superview;

@end

/// 底部弹窗 view 的基类 view
@interface BDLPopupBottomShowBaseView : BDLPopupBaseView <BDLPopupBottomShowViewProtocol>

@end
/// 右侧弹窗 view 的基类 view
@interface BDLPopupRightShowBaseView : BDLPopupBaseView <BDLPopupRightShowViewProtocol>

@end
/// 中间弹窗 view 的基类 view
@interface BDLPopupCenterShowBaseView : BDLPopupBaseView <BDLPopupCenterShowViewProtocol>

@end

/// 底部或者右侧弹窗 view 的基类 view
@interface BDLPopupBottomOrRightShowBaseView : BDLPopupBaseView <BDLPopupBottomOrRightShowViewProtocol>

@end