
Method/Property | Description |
topRightItems | Configure the set of buttons in the top-right corner of the live room. Freely add custom buttons or adjust the layout of built-in buttons. |
bottomItems | Configure the set of buttons at the bottom of the live room. Freely add custom buttons or adjust the layout of built-in buttons. |
replace(node:with:) | Replace the default component at a specified position (such as the top info area or bottom operation bar) with a fully custom view. |
overlayView | Widget layer for adding global business UI that floats above the video screen. |
perform(action:) | Trigger built-in logic directly from custom views, such as displaying the default audience list or co-host management panel. |
import UIKitimport AtomicXlet anchorView: AnchorViewfunc setupUI() {// Step 1: Create the beauty filter button and set button orderlet beautyButton = UIButton(type: .system)beautyButton.setTitle("beauty", for: .normal)// Order: co-host, PK, custom beauty button, moreanchorView.bottomItems = [.coHost, .battle, .custom(beautyButton), .more]// Step 2: Replace the LiveInfo view stylelet customLiveInfoView = CustomLiveInfoView()anchorView.replace(node: .liveInfo, with: customLiveInfoView)// Step 3: Add the "Popularity Ranking" floating widgetlet rankWidget = RankWidgetView()// Add widget to the overlay layeranchorView.overlayView.addSubview(rankWidget)// Position below the top-left cornerrankWidget.snp.makeConstraints { make inmake.top.equalToSuperview().offset(120)make.leading.equalToSuperview().offset(12)make.width.equalTo(70)make.height.equalTo(30)}}
.custom(UIView), or flexibly add/remove built-in features and adjust button order using the bottomItems property.
AnchorBottomItem enums and assign it to the component property.import UIKitimport AtomicXlet anchorView: AnchorView// Example: Keep only the co-host feature in the bottom toolbar and add a product list trigger buttonfunc adjustBottomBar() {// Step 1: Prepare custom button viewlet goodsButton = UIButton(type: .custom)goodsButton.setImage(UIImage(named: "shop_cart"), for: .normal)// Step 2: Update the bottom button arrayanchorView.bottomItems = [.coHost,.custom(goodsButton)]}
topRightItems property to add or simplify control buttons in the top-right corner.
topRightItems property.import UIKitimport AtomicXlet anchorView: AnchorView// Example: Keep audience count and close room buttons in the top-right corner, and add a "Report" buttonfunc adjustTopRightBar() {// Step 1: Prepare custom button viewlet reportButton = UIButton(type: .custom)reportButton.setImage(UIImage(named: "report_btn"), for: .normal)// Step 2: Update the top button array in display orderanchorView.topRightItems = [.audienceCount, .custom(reportButton), .close]}
replace interface to fully swap out the view in a specified area.AnchorNode enum. See the "Page Structure Diagram" above for reference:AnchorNode | Description |
liveInfo | Top-left area displaying host and room information. |
topRightButtons | Top-right area for system control buttons. |
networkInfo | Network status indicator area. |
bottomRightBar | Bottom-right area for business operation bar. |
barrageInput | Bottom-left area for triggering the live comments input box. |
replace method fully replaces the specified node. If you replace both topRightButtons and bottomRightBar, their corresponding Items properties become invalid. For simple button adjustments, use the Items properties described earlier. Use replace only when you need to redesign the layout of an area.replace interface inserts your custom view into the specified slot. The framework controls the position; you don't need to set it. The view's size is determined by itself. Declare the size using one of the following methods:class MyInfoView: UIView {init() {super.init(frame: .zero)let label = UILabel()label.text = "Live now"addSubview(label)label.snp.makeConstraints { make inmake.edges.equalToSuperview().inset(12) // Child view expands parent view}}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}}
class MyInfoView: UIView {override var intrinsicContentSize: CGSize {CGSize(width: 200, height: 44)}}
replace interface on the AnchorView component, passing the node enum to replace and the custom view.let anchorView: AnchorView// Example: Replace the default area with a custom live info viewfunc replaceLiveInfoNode() {// Step 1: Initialize a custom view with proper layout ruleslet customInfoView = MyInfoView()customInfoView.backgroundColor = .darkGray// Step 2: Call replace to update the specific nodeanchorView.replace(node: .liveInfo, with: customInfoView)}
perform method to trigger TUILiveKit's built-in logic.addTarget or gesture recognizers to add tap events.perform with the AnchorAction enum, or execute other business logic.import UIKitimport AtomicXclass YourAnchorViewController {var anchorView: AnchorView?// Example: Bind a tap event to a custom live info view and reuse the SDK's built-in host info panelfunc setupCustomLiveInfoNode() {// Step 1: Initialize custom view and bind gesture eventlet customLiveInfoView = MyInfoView() // Custom live info viewcustomLiveInfoView.backgroundColor = .darkGray// Enable user interaction and add tap gesturecustomLiveInfoView.isUserInteractionEnabled = truelet tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleLiveInfoClick))customLiveInfoView.addGestureRecognizer(tapGesture)// Replace the live info node with the custom viewanchorView?.replace(node: .liveInfo, with: customLiveInfoView)}// Step 2: Trigger built-in logic or business code@objc func handleLiveInfoClick() {// UI node view is custom, but tap logic reuses the built-in host info popupanchorView?.perform(.showLiveInfo)// Or pop up your own host info dialog}}
perform don't meet your business needs, you can fully take over this logic and build custom panels using data from the Core SDK.AtomicXCore data interface to access room, user, and status data. Build custom views and bind interactions as needed. After creating your custom controller, use the AtomicPopover component to present it, so your panel benefits from the same gesture handling and animations as the SDK's built-in panels.UIView and use the AtomicXCore interface inside it to fetch or listen to business data for UI updates.contentView to the AtomicPopover container and present it.import UIKitimport AtomicXimport AtomicXCore // Use core data interface for business development// Step 1: Build custom audience list viewclass CustomAudienceListView: UIView {override init(frame: CGRect) {super.init(frame: frame)self.backgroundColor = .whitesetupUI()bindLiveData()}required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}private func setupUI() {// Add custom UI controls, such as audience avatars, user levels, etc.}private func bindLiveData() {// Use AtomicXCore to get current room status or user data// Refresh custom UI after obtaining core data}}// Example: Slide up a custom panel from the bottom, occupying half the screen heightfunc presentBusinessPanel(from parentViewController: UIViewController) {// Step 2: Configure popup container parameterslet config = AtomicPopover.AtomicPopoverConfig(position: .bottom,height: .ratio(0.5),animation: .slideFromBottom)// Step 3: Present custom viewlet audienceListView = CustomAudienceListView()let popover = AtomicPopover(contentView: audienceListView, configuration: config)parentViewController.present(popover, animated: true)}
AtomicXCore interface:Feature Description | Reference Documentation |
Audience co-host management panel: co-host application/invite/accept/reject, co-host member permission control (microphone/camera), status synchronization. | |
Host cross-room co-host panel: manage host co-hosting interactions, initiate/accept/reject co-hosting. | |
Audience list: count audience number, listen for audience join/leave events. | |
Audio effects panel: voice changer (child voice/male voice), reverb (KTV, etc.), monitor adjustment, real-time effect switching. |
overlayView layer, as they sit above the video and are independent of the base layout.AtomicPopover: bind a tap event to the widget, and pop up a custom business dialog when clicked.overlayView, and in the tap callback, call your custom popup logic.import UIKitimport TUILiveKitclass LiveRoomController: UIViewController {var anchorView: AnchorView?// Example: Display a red packet widget floating at the top-left corner, and pop up the custom business panel when clickedfunc addRedPacketWidget() {// Step 1: Create widget view and enable interactionlet redPacketWidget = UIImageView(image: UIImage(named: "red_packet_icon"))redPacketWidget.frame = CGRect(x: 15, y: 120, width: 60, height: 60)redPacketWidget.isUserInteractionEnabled = true// Step 2: Bind tap eventlet tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleRedPacketClick))redPacketWidget.addGestureRecognizer(tapGesture)// Step 3: Add to overlay layeranchorView?.overlayView.addSubview(redPacketWidget)}@objc func handleRedPacketClick() {// Call the presentBusinessPanel method to pop up your custom business view// presentBusinessPanel(from: self)}}
.custom() or replace doesn't respond to clicks, check the following:bottomRightBar), ensure that child controls form a complete constraint chain to expand the parent view, or override the main view's intrinsicContentSize. If the parent view's actual size is 0, even visible buttons won't receive click events—they fall outside the parent view's bounds.isUserInteractionEnabled property. For UIImageView or generic UIView containers, this defaults to false. Set it to true manually.UITapGestureRecognizer or used addTarget.bottomItems and topRightItems properties of AnchorView support reactive updates. Assemble a new button array and assign it to the property—the SDK automatically refreshes the view. No need to manually call reloadData or similar methods.intrinsicContentSize. See "Custom View Layout Rules" above for details.피드백