# 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

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

### Data exchange process

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

`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

* `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

![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

To customize the classroom UI, follow these steps:

### 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

#### 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

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

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.

    
  
      
  
      
  
