在 Agora Classroom SDK 中,灵动课堂的 UI 层代码和核心业务逻辑相隔离,独立成 AgoraEduUI 和 AgoraEduCore 两个库,两者通过 Agora Edu Context 产生关联。具体逻辑如下:
教室的类结构示意图如下:
每种班型的 UI 在对应的 .xml
文件中定义,包含多个独立的 UI 组件 (Component)。UI 组件的结构示意图如下:
开发者可自由组合 UI 组件搭建自定义版型,也可以自定义 UI 组件或修改灵动课堂的 UI 组件。
本节介绍自定义课堂 UI 的具体步骤。
如需修改灵动课堂的默认 UI,你需要通过下载 GitHub 源码的方式集成灵动课堂,步骤如下:
运行以下命令克隆仓库到本地:
git clone https://github.com/AgoraIO-Community/CloudClass-Android.git
运行以下命令切换分支至指定版本,将 {VERSION} 替换为要切换的版本号:
git checkout release/apaas/{VERSION}
例如要切换到 2.1.0 版本分支,执行以下命令:
git checkout release/apaas/2.1.0
Agora 建议你切换到最新发版分支。参考下图在 GitHub 仓库中查看最新发版分支:
后续 UI 相关的改动主要在以下两个目录中进行:
/AgoraClassSDK
:实现教室页面。/AgoraEduUIKit
:教室使用到的所有 UI 组件。参考以下步骤引入 UI 组件库:
参考集成灵动课堂文档将灵动课堂以 maven 的方式引入到你自己的项目中。
修改 AgoraEduUIKit
和 AgoraClassSDK
模块的引用方式。你需要在 build.gradle
文件中进行如下修改:
dependencies {
// ...
implementation "io.github.agoraio-community:hyphenate:版本号"
implementation "io.github.agoraio-community:AgoraEduCore:版本号"
// implementation "io.github.agoraio-community:AgoraEduUIKit:版本号"
// implementation "io.github.agoraio-community:AgoraClassSDK:版本号"
implementation project(path: ':AgoraClassSDK')
}
AgoraClassSDK
里引用了 AgoraEduUIKit
模块。所有 UI 组件都位于 com.agora.edu.component
目录下,找到对应的组件就可以修改 UI。
下文以小班课为例,介绍如何修改顶部导航栏的高度、标题以及背景色。具体步骤如下:
在 AgoraClassSDK模块
的 io.agora.classroom.ui
下面找到小班课的 AgoraClassSmallActivity
。
在 AgoraClassSmallActivity
对应的 activity_agora_class_small.xml
中找到 AgoraEduHeadComponent
组件。Activity
与 .xml
是通过 viewbinding
绑定的。
打开 AgoraEduHeadComponent
对应的 agora_edu_head_component.xml
。在这个文件中,你可以直接修改导航栏的高度、标题以及背景色。
所有 UI 组件都必须继承 AbsAgoraEduComponent
,且调用 initView(agoraUIProvider: IAgoraUIProvider)
方法初始化 UI 组件。
UI 组件可通过 IAgoraUIProvider
接口获取 EduCore 层的数据。
interface IAgoraUIProvider {
/**
* 获取 EduCore 数据
*/
fun getAgoraEduCore(): AgoraEduCore?
/**
* UI 可以自定义数据
*/
fun getUIDataProvider(): UIDataProvider?
}
下文介绍如何为 1 对 1 班型新增一个 AgoraEduMyComponent
组件。具体步骤如下:
定义 AgoraEduMyComponent
:
class AgoraEduMyComponent : AbsAgoraEduComponent {
constructor(context: Context) : super(context)
constructor(context: Context, attr: AttributeSet) : super(context, attr)
constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr)
// TODO: 替换成你自己定义的 xml
private var binding: xxxxBinding = xxxBinding.inflate(LayoutInflater.from(context), this, true)
override fun initView(agoraUIProvider: IAgoraUIProvider) {
super.initView(agoraUIProvider)
// TODO: 在这里处理 View
// TODO: agoraUIProvider 提供教室数据能力和 View 需要的数据,你可自行定义
}
}
在 .xml
中使用定义好的 AgoraEduMyComponent
:
<xxxx.xxx.xxxx.AgoraEduMyComponent
android:id="@+id/agora_class_head"
android:layout_width="match_parent"
android:layout_height="@dimen/agora_head_h_small"
android:gravity="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
在 AgoraClass1V1Activity
中初始化组件:
class AgoraClass1V1Activity : AgoraEduClassActivity() {
private val TAG = "AgoraClass1V1Activity"
lateinit var binding: ActivityAgoraClass1v1Binding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAgoraClass1v1Binding.inflate(layoutInflater)
setContentView(binding.root)
// 创建教室对象
createEduCore(object : EduContextCallback<Unit> {
override fun onSuccess(target: Unit?) {
// 教室资源加载完成后
joinClassRoom()
}
override fun onFailure(error: EduContextError?) {
error?.let {
ToastManager.showShort(it.msg)
}
finish()
}
})
}
private fun joinClassRoom() {
runOnUiThread {
eduCore()?.eduContextPool()?.let { context ->
// 初始化 view
binding.agoraEduMyComponent.initView(this)
}
join()
}
}
}