# Classroom and Proctor SDK (/en/realtime-media/flexible-classroom/build/customize-the-ui-and-plugins/customize-classroom/ios)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

## Introduction to classrooms and UI components [#introduction-to-classrooms-and-ui-components-1]

    This section tells you about the components that manage data and the user interface in Flexible Classroom.

    ### Data exchange process [#data-exchange-process-1]

    In the Agora Classroom SDK, the code of the user interfaces is separated from the code of core business logic. The Classroom SDK contains two libraries, **AgoraEduUI** and **AgoraEduCore**. These two libraries connect with each other through Agora Edu Context. Supposing that we want to implement a button for turning on or off the camera, you can call the `openLocalDevice`method of `AgoraEduMediaContext` in `AgoraEduUI`, and listen to the event which indicates the device state change thrown by ` AgoraEduMediaHandler`.

    The data flow is as follows:

    ![Data exchange process in Agora Classroom SDK](https://web-cdn.agora.io/docs-files/1651746402754)

    ### The structure of classrooms and UI components [#the-structure-of-classrooms-and-ui-components-1]

    `AgoraEduUI` contains the code of UI components in Flexible Classroom. The source code of `AgoraEduUI` is in `/SDKs/AgoraEduUI` in the CloudClass-iOS repository. The project structure is as follows:

    | Folder        | Description                                                                                                                                                                                                                                     |
    | :------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `/Scenes`     | Arranges UI components for different classroom types of Flexible Classroom, such as One-to-one Classroom, Small Classroom, and Lecture Hall.                                                                                                    |
    | `/Components` | The UI components for modular features in Flexible Classroom, such as the user list and navigation bar.                                                                                                                                         |
    | `/Configs`    | The UI configurations of Flexible Classroom. The UI configurations, such as background color, font color, and border width, are automatically adapted according to` AgoraUIMode`. Developers can define their own `AgoraUIMode` in this folder. |
    | `/Views`      | The basic UI components used in Flexible Classroom, such as the video rendering window and the dialog window.                                                                                                                                   |
    | `/Models`     | The corresponding data model and parsing method defined for parsing widget data in` AgoraEduUI`.                                                                                                                                                |

    ### Type description [#type-description]

    * `UIScene`

      * A `UIScene` represents a classroom type. The type of `UIManager` is  `UIViewController`.
      * A `UIScene` manages multiple `UIComponent` and is responsible for the communication between `UIComponent`.
      * Each `UIScene` has a `contextPool` for using the abilities provided by `AgoraEduContext`.

    * `UIComponent`
      * A `UIComponent` represents a UI component. The type of `UIController` is `UIViewController`.

      * The view of `UIComponent` is a subview of `UIScene.contentView`, which is the placeholder for this function.

      * `UIComponent` is in the `/Components` folder of the `AgoraEduUI` library, and is divided into the following two types:
        * `FlatComponents`: UI component of tile type.
        * `SuspendComponents`: UI component of dialog type.

    ### UI structure [#ui-structure]

    ![iOS Flexible Classroom UI structure](https://web-cdn.agora.io/docs-files/1651750314208)

    Taking Small Classroom on the teacher side as an example, the layout of UI components is as follows:

    ![Small Classroom teacher UI component layout on iOS](https://web-cdn.agora.io/docs-files/1651758759212)

    ## Customizing the classroom UI [#customizing-the-classroom-ui]

    To customize the classroom UI, follow these steps:

    ### 1. Get the source code for Flexible Classroom [#1-get-the-source-code-for-flexible-classroom]

    To customize the classroom UI based on the default UI of Flexible Classroom, download the source code for Flexible Classroom from [CloudClass-iOS](https://github.com/AgoraIO-Community/CloudClass-iOS/tree/release/2.8.11) and [apaas-extapp-ios](https://github.com/AgoraIO-Community/apaas-extapp-ios).

    1. Clone the repositories:

       ```bash
       git clone https://github.com/AgoraIO-Community/CloudClass-iOS.git
       git clone https://github.com/AgoraIO-Community/apaas-extapp-ios.git
       ```

    2. Update to the supported version of Flexible Classroom:

       ```bash
         cd CloudClass-iOS
         git checkout release/2.8.11
         cd ../apaas-extapp-ios
         git checkout release/2.8.11
       ```

    3. (Optional) Upload your project to a GitHub repository:

       1. From inside each repository, run `git remote add <shortname> <url>`, pointing to your project.

       2. Create a branch based on the latest release branch of Flexible Classroom and push it to your project.

    4. Add the following code in your project's `Podfile` to make reference to `AgoraClassroomSDK_iOS.podspec`, `AgoraEduContext.podspec`, `AgoraEduUI.podspec`, `AgoraWidgets.podspec` and other dependencies.

       ```swift
       # third libs
       pod 'Protobuf', '3.17.0'
       pod 'CocoaLumberjack', '3.6.1'
       pod 'AliyunOSSiOS', '2.10.8'
       pod 'Armin', '1.1.0'
       pod 'SSZipArchive', '2.4.2'
       pod 'SwifterSwift', '5.2.0'
       pod 'Masonry', '1.1.0'
       pod 'SDWebImage', '5.12.0'

       # agora libs
       pod 'AgoraRtcEngine_iOS/RtcBasic', '3.6.2'
       pod 'AgoraMediaPlayer_iOS', '1.3.0'
       pod 'AgoraRtm_iOS', '1.4.8'
       pod 'Agora_Chat_iOS', '1.0.6'
       pod 'Whiteboard', '2.16.39'

       # open source libs
       pod 'AgoraClassroomSDK_iOS', :path => '../CloudClass-iOS/AgoraClassroomSDK_iOS.podspec'
       pod 'AgoraEduUI', :path => '../CloudClass-iOS/AgoraEduUI.podspec'
       pod 'AgoraWidgets', :path => '../apaas-extapp-ios/AgoraWidgets.podspec'

       # close source libs
       pod 'AgoraUIBaseViews', '2.8.0'
       pod 'AgoraEduCore', '2.8.0'
       pod 'AgoraWidget', '2.8.0'
       ```

    ### 2. Edit the existing UI components [#2-edit-the-existing-ui-components]

    #### Example one: Change the background color of the navigation bar [#example-one-change-the-background-color-of-the-navigation-bar]

    You can change the background color of the navigation bar in one of the following ways:

    * Method one: Edit the code in `RoomStateUIComponent`.

    * Method two: Edit the `backgroundColor` variable of `FcrUIComponentStateBar` in `UIConfigs`.

    The following code is an example of the method two:

    **Before**

    ```swift
    struct FcrUIComponentStateBar: FcrUIComponentProtocol {
        var visible: Bool = true
        var enable: Bool = true
        // The color of the navigation bar is systemForegroundColor。
        var backgroundColor: UIColor = FcrUIColorGroup.systemForegroundColor

        /**Scene Builder Set**/
        var networkState = FcrUIItemStateBarNetworkState()
        var roomName = FcrUIItemStateBarRoomName()
        var scheduleTime = FcrUIItemStateBarScheduleTime()
        /**iOS**/
        let sepLine = FcrUIItemSepLine()

        let borderWidth = FcrUIFrameGroup.borderWidth
        let borderColor = FcrUIColorGroup.systemDividerColor
    }
    ```

    ![iOS navigation bar before background color customization](https://web-cdn.agora.io/docs-files/1651751702539)

    **After**

    ```swift
    struct FcrUIComponentStateBar: FcrUIComponentProtocol {
        var visible: Bool = true
        var enable: Bool = true
        // The color of the navigation bar is systemTeal。
        var backgroundColor: UIColor = .systemTeal

        /**Scene Builder Set**/
        var networkState = FcrUIItemStateBarNetworkState()
        var roomName = FcrUIItemStateBarRoomName()
        var scheduleTime = FcrUIItemStateBarScheduleTime()
        /**iOS**/
        let sepLine = FcrUIItemSepLine()

        let borderWidth = FcrUIFrameGroup.borderWidth
        let borderColor = FcrUIColorGroup.systemDividerColor
    }
    ```

    ![iOS navigation bar after background color customization](https://web-cdn.agora.io/docs-files/1651751774540)

    #### Example two: Change the icons used in the user list componet [#example-two-change-the-icons-used-in-the-user-list-componet]

    The code of the user list component is in the following two files:

    * iOS/SDKs/AgoraEduUI/Classes/Components/SuspendComponents/FcrRosterUIController.swift
    * iOS/SDKs/AgoraEduUI/Classes/Views/UserList/AgoraUserListItemCell.swift

    As the following picture shows, the student list includes six columns: Student Name, Stage, Auth, Camera, Micr, and Rewards:

    ![iOS student list component columns](https://web-cdn.agora.io/docs-files/1651752243091)

    There are two states, namely **true** and **false** for stage and whiteboard authorization. The camera and microphone have four states: **not on stage + inoperable**, **on stage + device off**, **on stage + device on + streaming permission off**, **on stage + device on + streaming permission on**.

    The data of the user list component comes from:

    * The changes in the total number of students and number of students "on the stage" are reported by callbacks in `AgoraEduUserHandler`.
    * The changes in the microphone state and camera state are reported by callbacks in `AgoraEduStreamHandler`.
    * The whiteboard authorization state is reported by the widget with the ID of `netlessBoard`.

    Taking the camera state as an example, the data flow is as follows:

    1. When the stream state changes, the `onStreamUpdated` callback in `AgoraEduStreamHandler` is triggered, and then the data is updated through the `updateModel` method.
    2. After the data is updated, `tableView.reloadData()` is called to refresh each cell of the tableView.
    3. Finally, the icon is updated in the `updateState` method of `AgoraUserListItemCell`.

    If you want to update the camera icon, refer to the following steps:

    1. Put the new camera icons **new\_camera\_on** and **new\_camera\_off** in the `AgoraEduUI/AgoraEduUI/Assets/images.xcassets/NameRoll` folder:

       ![New camera icon assets in Xcode](https://web-cdn.agora.io/docs-files/1651755311560)

    2. Update the code in the `AgoraUserListItemCell.swift` file:

    **Before**

    ```swift
    // colors
    let onColor = UIColor(hex: 0x0073FF)
    let offColor = UIColor(hex: 0xF04C36)
    let disabledColor = UIColor(hex: 0xE2E2EE)

    // state
    case .camera:
        if !model.stageState.isOn {
            // unCohost
            let image = UIImage.agedu_named("ic_nameroll_camera_on")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = disabledColor
        } else if !model.cameraState.deviceOn {
            // cohost + device off
            let image = UIImage.agedu_named("ic_nameroll_camera_off")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = disabledColor
        } else if !model.cameraState.streamOn {
            // cohost + device on + no video stream privilege
            let image = UIImage.agedu_named("ic_nameroll_camera_off")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = offColor
        } else {
            // cohost + device on + video stream privilege
            let image = UIImage.agedu_named("ic_nameroll_camera_on")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = onColor
        }
        cameraButton.isUserInteractionEnabled = model.cameraState.isEnable
    ```

    **After**

    ```swift
    case .camera:
        if !model.stageState.isOn {
            // unCohost
            let image = UIImage.agedu_named("new_camera_on")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = disabledColor
        } else if !model.cameraState.deviceOn {
            // cohost + device off
            let image = UIImage.agedu_named("new_camera_off")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = disabledColor
        } else if !model.cameraState.streamOn {
            // cohost + device on + no video stream privilege
            let image = UIImage.agedu_named("new_camera_off")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = offColor
        } else {
            // cohost + device on + video stream privilege
            let image = UIImage.agedu_named("new_camera_on")
            if let i = image?.withRenderingMode(.alwaysTemplate) {
                cameraButton.setImageForAllStates(i)
            }
            cameraButton.tintColor = onColor
        }
        cameraButton.isUserInteractionEnabled = model.cameraState.isEnable
    ```

    ![iOS user list camera icon before customization](https://web-cdn.agora.io/docs-files/1651756155692)

    ![iOS user list camera icon after customization](https://web-cdn.agora.io/docs-files/1651756204269)

    ### 3. Add a UI component [#3-add-a-ui-component]

    The basic steps for adding a new UI component are as follows:

    1. Add a `UIComponent` class in the `iOS/SDKs/AgoraEduUI/Classes/Components` folder.
    2. Add an object of this `UIComponent` class in `UIScene` and add the view.

    
  
      
  
      
  
