iOS UI Kit — Customization

Customize the iOS UI Kit via EnxSetting.shared — a shared singleton that controls join options, UI appearance, enabled features, screen sharing, and live streaming. Configure settings before presenting EnxVideoViewClass so they take effect when the session loads.

Join Configuration

These settings control how participants enter the room — what the join button says, which camera is active by default, whether a preview screen appears, and whether audio or video starts muted.

Custom Join Button Label

Override the default "Join" label on the entry button with any string:

EnxSetting.shared.setJoinText("Go Live")

Default Camera

Choose which camera is active when the session starts. Useful for apps where rear-camera use cases (e.g., field inspection, demonstrations) are primary:

EnxSetting.shared.setCameraPosition(true)   // Front camera (default)
EnxSetting.shared.setCameraPosition(false)  // Rear camera

Camera Preview Before Joining

Show a pre-join preview screen so participants can check their video and audio before entering the room. Disable it for faster direct-join flows:

EnxSetting.shared.isPreScreening(true)   // Show preview screen
EnxSetting.shared.isPreScreening(false)  // Skip directly into room

Audio-Only Call

When enabled, all video capture and rendering is suppressed and only audio is transmitted. All video-related UI elements are hidden automatically:

EnxSetting.shared.isAudioOnlyCall(true)   // Audio only
EnxSetting.shared.isAudioOnlyCall(false)  // Audio + Video (default)

Join with Video Muted

Enter the room with the camera off. The participant can enable their camera after joining:

EnxSetting.shared.joinAsVideoMute(true)   // Enter with camera off
EnxSetting.shared.joinAsVideoMute(false)  // Enter with camera on (default)

Join with Audio Muted

Enter the room with the microphone muted. Useful for large webinars where participants should be silent by default:

EnxSetting.shared.joinAsAudioMute(true)   // Enter muted
EnxSetting.shared.joinAsAudioMute(false)  // Enter with mic on (default)

Auto-Start RTMP Streaming on Join

Automatically begin RTMP live streaming the moment the moderator connects. Provide both the RTMP ingest URL and the CDN playback URL:

EnxSetting.shared.startLiveStreaming(true)
EnxSetting.shared.liveStreaming([
    "rtmpDetails": ["rtmpUrl": "YOUR_RTMP_URL"],
    "urlDetails":  ["url":     "YOUR_CDN_URL"]
])
Audio View Mode — 1-to-1 Audio Calls

When a session is used for a 1-to-1 voice call — where neither participant publishes video — the default video grid is replaced by a purpose-built calling screen. It shows the remote participant's name and initials avatar over a gradient background, with overlay buttons for microphone toggle and exit.

Two properties on EnxSetting.shared control this mode. Both must be set before the session connects — they have no effect once the session is active.

Enable the Audio View Overlay

Set isAudioViewMode to true to activate the audio call UI. This replaces the standard video grid with the calling screen whenever no video is being published:

EnxSetting.shared.isAudioViewMode = true

Customise the Audio View Appearance

Assign an EnxAudioViewConfig instance to audioViewConfig to define the gradient background colours, the remote participant's name text colour, and the initials avatar colours:

EnxSetting.shared.audioViewConfig = EnxAudioViewConfig(
    gradientLayer1: UIColor(red: 0.04, green: 0.22, blue: 0.20, alpha: 1),   // top gradient colour
    gradientLayer2: UIColor(red: 0.01, green: 0.08, blue: 0.07, alpha: 1),   // bottom gradient colour
    nameTextColor: .white,                                                     // remote participant name
    sortNameTextColor: .white,                                                 // initials text colour
    sortNameBGColor: UIColor(red: 0.07, green: 0.55, blue: 0.44, alpha: 1)   // initials avatar background
)
ParameterTypeDescription
gradientLayer1UIColorTop colour of the background gradient.
gradientLayer2UIColorBottom colour of the background gradient.
nameTextColorUIColorColour of the remote participant's display name.
sortNameTextColorUIColorColour of the initials text inside the avatar circle.
sortNameBGColorUIColorBackground colour of the avatar/initials circle.
Must be set before the session starts

Both isAudioViewMode and audioViewConfig must be configured before EnxVideoViewClass connects to the room. Changes applied after the session starts have no effect.

UI Customization

Bottom Bar Background Color

Change the background color of the control bar at the bottom of the video view to match your app's brand:

EnxSetting.shared.updateBottomOptionView(withColor: .blue.withAlphaComponent(1.0))
Bottom bar button limit

You can define a maximum of 7 buttons in the Bottom Bar. Custom buttons use your own action targets. Buttons assigned pre-defined tags are handled automatically by the kit and do not require additional wiring.

Participant List Actions

Control which actions appear when a moderator long-presses a participant in the list. Pass an array of ParticipantListOptions raw values:

EnxSetting.shared.configureParticipantList(
    to: [
        ParticipantListOptions.audio.rawValue,      // Hard mute audio
        ParticipantListOptions.video.rawValue,      // Hard mute video
        ParticipantListOptions.chat.rawValue,       // Open private chat
        ParticipantListOptions.disconnect.rawValue  // Force disconnect
    ]
)
Feature Configuration

Use these APIs to control exactly which controls appear in the kit's UI. You can enable features by tag (quick) or by supplying fully configured model objects with custom icons.

Enable Controls by Tag

Pass an array of EnxRequiredEventsOption raw values to show only the controls your app needs:

EnxSetting.shared.configureRequiredEventList(
    withList: [
        EnxRequiredEventsOption.audio.rawValue,
        EnxRequiredEventsOption.video.rawValue,
        EnxRequiredEventsOption.cameraSwitch.rawValue
    ]
)

Enable Controls with Custom Icons

For full brand control, supply EnxRequiredEventsOptionModel objects that pair each control with your own normal and selected-state images:

let requiredAudio = EnxRequiredEventsOptionModel(
    name: "Audio",
    isSelected: false,
    optionTag: .audio,
    isSwith: false,
    eventImageNormal:   UIImage(named: "audio-on"),
    eventImageSelected: UIImage(named: "audio-off")
)

let requiredVideo = EnxRequiredEventsOptionModel(
    name: "Video",
    isSelected: false,
    optionTag: .video,
    isSwith: false,
    eventImageNormal:   UIImage(named: "video-on"),
    eventImageSelected: UIImage(named: "video-off")
)

let requiredCamera = EnxRequiredEventsOptionModel(
    name: "Camera",
    isSelected: false,
    optionTag: .cameraSwitch,
    isSwith: false,
    eventImageNormal:   UIImage(named: "camera-switch"),
    eventImageSelected: UIImage(named: "camera-switch")
)

EnxSetting.shared.configureRequiredEventsOptionList(
    withList: [requiredAudio, requiredVideo, requiredCamera]
)
Screen Sharing

iOS screen sharing uses a ReplayKit broadcast extension — a separate app extension target in your Xcode project that captures the screen and feeds frames to the kit. The extension communicates with the main app via an App Group.

Initialize the Screen Share Client

Create an EnxShareClass instance inside your broadcast extension's SampleHandler. Pass the screen share token, your App Group name, a client identifier, and a delegate for lifecycle callbacks:

EnxShareClass(
    screenShare: "YOUR_SCREEN_SHARE_TOKEN",
    withAppGroupName: "group.com.company.AppName",
    withUserKey: "CLIENT_ID",
    delegate: self
)

Process Frames for Sharing

Inside your broadcast extension's processSampleBuffer method, forward each pixel buffer to the kit:

enxShare.processFrame(buffer: outPixelBuffer!, withTimeStamp: time)

Set Screen Share Layout

Control how the shared screen is presented to remote participants. The "presenter" layout pins the shared screen as the dominant tile:

EnxSetting.shared.setOption(forScreenShare: ["layout": "presenter"])

Set App Group and User Key

Register the App Group name and client identifier so the main app and broadcast extension can communicate:

EnxSetting.shared.setAppGroupsName(
    groupname: "group.com.company.AppName",
    withUserKey: "CLIENT_ID"
)

Stop Screen Sharing

enxShare.stopStreenShare()
RTMP Live Streaming

Moderators can start and stop RTMP streaming during an active session. The stream is broadcast to any RTMP-compatible ingest endpoint (e.g., YouTube Live, Facebook Live, a custom media server).

Start Streaming

To start with explicit stream details at runtime, pass an information dictionary:

EnxSetting.shared.startStreaming(information: [
    "rtmpDetails": ["rtmpUrl": "YOUR_RTMP_URL"],
    "urlDetails":  ["url":     "YOUR_CDN_URL"]
])

To start using the stream details that were configured at join time (via EnxSetting.shared.liveStreaming()), pass nil:

EnxSetting.shared.startStreaming(information: nil)

Stop Streaming

EnxSetting.shared.stopStreaming()

Show / Hide Live Indicator

Toggle the on-screen "Live" badge that appears while RTMP streaming is active:

EnxSetting.shared.isShow(GoLiveIndicator: true)   // Show badge
EnxSetting.shared.isShow(GoLiveIndicator: false)  // Hide badge
User Data and Room Information

Send Custom Data

Send arbitrary structured data to all participants — used for polls, Q&A responses, or any custom in-session signalling:

EnxSetting.shared.sendUserData(enxSendUserData)

Receive Custom Data

Implement this delegate method to handle incoming custom data from other participants:

func didUserDataReceived(_ userData: [String: Any]) {
    // Handle incoming poll responses, Q&A answers, or custom events
    print("Received user data: \(userData)")
}

Close the Chat Panel

EnxSetting.shared.closeChatPage()

Observe Panel Open / Close Events

The kit notifies your delegate whenever a slide-over panel opens or closes. Use this to adjust your own UI — for example, hiding floating controls when a panel is visible:

func didPageSlide(_ pageName: EnxPageSlideEventName, isShow: Bool) {
    // pageName: EnxChat | EnxPolling | EnxQnA | EnxScreenShare
    // isShow: true = panel opened, false = panel closed
}

Room and User Information

Query current session state at any time using these accessors on EnxSetting:

EnxSetting.getParticipantList()         // All connected participants
EnxSetting.shared.getRoomMode()         // "group" or "lecture"
EnxSetting.shared.getCurrentRole()     // "moderator" or "participant"
EnxSetting.shared.getClientID()        // Self client ID
EnxSetting.shared.getRoom()            // Room instance (EnxRoom)
EnxSetting.shared.getiSKnockRoom()     // true if knock/lobby is enabled
EnxSetting.shared.getisUserAwaited()   // true if a user is waiting in lobby
EnxSetting.shared.getisUserInFloorReq() // true if user has requested floor