@@ -25,6 +25,12 @@ | |||
</formatting-settings> | |||
</DBN-SQL> | |||
<JetCodeStyleSettings> | |||
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="true" /> | |||
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="true" /> | |||
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="true" /> | |||
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="0" /> | |||
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" /> | |||
<option name="IF_RPAREN_ON_NEW_LINE" value="false" /> | |||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> | |||
</JetCodeStyleSettings> | |||
<DBN-PSQL> | |||
@@ -168,6 +174,13 @@ | |||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> | |||
<option name="RIGHT_MARGIN" value="120" /> | |||
<option name="KEEP_LINE_BREAKS" value="false" /> | |||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" /> | |||
<option name="ALIGN_MULTILINE_METHOD_BRACKETS" value="true" /> | |||
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="false" /> | |||
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="false" /> | |||
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="false" /> | |||
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="false" /> | |||
<option name="EXTENDS_LIST_WRAP" value="0" /> | |||
</codeStyleSettings> | |||
</code_scheme> | |||
</component> |
@@ -7,6 +7,7 @@ | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/drawable/svg/drawable/ic_discern.xml" value="0.3223958333333333" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/drawable/svg/drawable/ic_nav_learn_center.xml" value="0.3223958333333333" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/drawable/svg/drawable/ic_nav_my.xml" value="0.3223958333333333" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/dialog_bottom_bg.xml" value="0.5140625" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/et_search_bg.xml" value="0.175" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/ic_delete.xml" value="0.30520833333333336" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/ic_discern.xml" value="0.30520833333333336" /> | |||
@@ -22,18 +23,35 @@ | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/nav_service.xml" value="0.30520833333333336" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/nav_statistics.xml" value="0.1" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/progress_center.xml" value="0.287962962962963" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_12_white.xml" value="0.5140625" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_toplr_24_white.xml" value="0.5061538461538462" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/spoken_autoplay_btn_text_color_.xml" value="0.5140625" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/theme_splash_bg.xml" value="0.30520833333333336" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout-v23/include_main_learn_center_course_type_title.xml" value="0.4963768115942029" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_course_main.xml" value="0.33" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_base.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_word2.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_main.xml" value="0.5" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_splash.xml" value="0.4921875" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_auto_play_select.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_course_more.xml" value="0.33" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_item_select_repeat.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_lesson_learn.xml" value="0.4144927536231884" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_lesson.xml" value="0.33" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_main.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_pack.xml" value="0.34427083333333336" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_review.xml" value="0.12802768166089964" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_total_test.xml" value="0.33" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_first.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_learn_center.xml" value="0.25" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_my.xml" value="0.28229166666666666" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_over_number.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/include_main_learn_center_course_progress.xml" value="0.503125" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/include_main_learn_center_course_type_title.xml" value="0.67" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/include_recyclerview_smart_refresh_layout.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/include_title_bar.xml" value="0.25052083333333336" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_course_lesson.xml" value="0.4785615491009682" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_empty.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_course_progress.xml" value="0.25" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_coursepack.xml" value="0.43500866551126516" /> | |||
@@ -42,6 +60,7 @@ | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/textview.xml" value="0.49773550724637683" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/textview_only.xml" value="0.49773550724637683" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/statedrawable/drawable/ic_nav_learn_center.xml" value="0.44166666666666665" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_arrow_right.xml" value="0.29814814814814816" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_discern.xml" value="0.5061538461538462" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_icon___.xml" value="0.287962962962963" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_nav_learn_center.xml" value="0.44166666666666665" /> | |||
@@ -55,6 +74,7 @@ | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/drawable/ic_back.xml" value="0.4148148148148148" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/drawable/ic_search.xml" value="0.19814814814814816" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/drawable/loading_bg.xml" value="0.5061538461538462" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/layout/item_empty.xml" value="0.34427083333333336" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/layout/lib_dialog_loading.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/layout/lib_layout_custom_title.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/lib/common/src/main/res/layout/loadding_fragment.xml" value="0.4817708333333333" /> |
@@ -45,4 +45,5 @@ google 给与的唯一标识符最佳做法: | |||
3、尽一切可能针对防欺诈支付和电话以外的所有其他用例使用实例 ID 或私密存储的 GUID。对于绝大多数非广告用例,使用实例 ID 或 GUID 应已足够。 | |||
4、使用适合您的用例的 API 以尽量降低隐私权风险 | |||
如何实现防快速点击 aspectJ | |||
如何实现防快速点击 aspectJ | |||
@@ -43,3 +43,11 @@ Kotlin的单例模式: https://developer.aliyun.com/article/642618 | |||
饿汉式(直接获取实例)、懒汉式(一次判空获取实例)、双重校验锁 | |||
object 声明: 为饿汉式单例,即直接实例 | |||
数字精度格式: https://www.jianshu.com/p/5286a44ed9b1 | |||
Material Design Components 组件使用 https://www.jianshu.com/p/bc71b4179cb2 | |||
// Android Gradle 插件 4.0,下述配置不再是必需的,并且会导致构建失败。外部原生 build 现在会自动打包这些库,因此使用 jniLibs 明确打包库会导致重复。 | |||
// sourceSets { | |||
// main { | |||
// jniLibs.srcDirs = ['libs'] | |||
// } | |||
// } |
@@ -68,6 +68,7 @@ android { | |||
} | |||
dependencies { | |||
implementation fileTree(include: ['*.jar',"*.aar"], dir: 'libs') | |||
implementation 'androidx.legacy:legacy-support-v4:1.0.0' | |||
implementation project(path: ':lib:common') | |||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' | |||
@@ -75,6 +76,9 @@ dependencies { | |||
implementation 'androidx.appcompat:appcompat:1.2.0' | |||
implementation 'com.google.android.material:material:1.3.0' | |||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' | |||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5' | |||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5' | |||
rootProject.ext.dependencies_required.each{ k, v -> implementation v} | |||
testImplementation rootProject.ext.dependencies_testImplementation.junit | |||
rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v} |
@@ -13,7 +13,28 @@ | |||
android:theme="@style/Theme.XklLocal" | |||
tools:ignore="LockedOrientationActivity"> | |||
<activity | |||
android:name=".module.m_center_learn.CourseMainActivity" | |||
android:name=".module.learn.LearnCTaskActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.learn.LearnCReadingActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.learn.LearnCVideoActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.learn.LearnExamSpellActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.learn.LearnExamWordActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.learn.LearnSpellActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.learn.LearnWordActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.m_center_learn.CoursePackMainActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.splash.SplashActivity" |
@@ -0,0 +1,45 @@ | |||
package com.xkl.cdl.adapter | |||
import android.view.ViewGroup | |||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||
import androidx.viewbinding.ViewBinding | |||
import com.suliang.common.base.adapter.BaseAdapter | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.databinding.DialogItemSelectRepeatBinding | |||
/** | |||
* author suliang | |||
* create 2020/6/29 13:44 | |||
* Describe: 自动播放弹窗列表选择适配器 | |||
*/ | |||
class AdapterAutoPlaySelectRepeat : BaseAdapter<Void?>() { | |||
override fun coverEmptyViewHolder(parent: ViewGroup): BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_empty)) | |||
} | |||
override fun onBindEmptyViewHolder(holder: BaseAdapterViewHolder) {} | |||
override fun getItemCount(): Int { | |||
return 5 | |||
} | |||
override fun coverViewHolder(parent: ViewGroup, viewType: Int): BaseAdapterViewHolder { | |||
val binding = inflateBinding(parent, R.layout.dialog_item_select_repeat) | |||
return BaseAdapterViewHolder(binding) | |||
} | |||
override fun onBindVH(holder: BaseAdapterViewHolder, position: Int) { | |||
val binding = holder.binding as DialogItemSelectRepeatBinding | |||
when (position) { | |||
0 -> binding.tvOption.setText(R.string.auto_play_repeat_1) | |||
1 -> binding.tvOption.setText(R.string.auto_play_repeat_2) | |||
2 -> binding.tvOption.setText(R.string.auto_play_repeat_3) | |||
3 -> binding.tvOption.setText(R.string.auto_play_repeat_4) | |||
4 -> binding.tvOption.setText(R.string.auto_play_repeat_5) | |||
} | |||
binding.root.click { | |||
onItemClick.invoke(it,position,null) | |||
} | |||
} | |||
} |
@@ -1,15 +1,14 @@ | |||
package com.xkl.cdl.adapter | |||
import android.opengl.Visibility | |||
import android.view.View | |||
import android.view.ViewGroup | |||
import com.suliang.common.base.adapter.BaseAdapterVM | |||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||
import com.suliang.common.databinding.ItemEmptyBinding | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.Constants | |||
import com.xkl.cdl.data.course.CoursePack | |||
import com.xkl.cdl.databinding.ItemEmptyBinding | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.CoursePack | |||
import com.xkl.cdl.databinding.MainItemCoursepackBinding | |||
import com.xkl.cdl.module.m_center_learn.CoursePackFragmentViewModel | |||
@@ -21,11 +20,6 @@ import com.xkl.cdl.module.m_center_learn.CoursePackFragmentViewModel | |||
class AdapterCoursePackWithLearCenter(vm: CoursePackFragmentViewModel) : | |||
BaseAdapterVM<CoursePack, CoursePackFragmentViewModel>(vm) { | |||
override fun coverEmptyViewHolder(parent: ViewGroup): BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_empty)) | |||
} | |||
override fun onBindEmptyViewHolder(holder: BaseAdapterViewHolder) { | |||
(holder.binding as ItemEmptyBinding).apply { | |||
val nullOrEmpty = vm.learnCenterFragmentViewModel.mCoursePackSearchValueMap[vm.projectId].isNullOrEmpty() | |||
@@ -46,8 +40,8 @@ class AdapterCoursePackWithLearCenter(vm: CoursePackFragmentViewModel) : | |||
imageViewTypeVoice.visibility = View.GONE | |||
coursePack = getItem(position).also { cp -> | |||
when (vm.projectId) { | |||
Constants.SUBJECT_ENGLISH -> initEnglish(this, cp, position) | |||
Constants.SUBJECT_CHINESE -> initChinese(this, cp, position) | |||
AppConstants.SUBJECT_ENGLISH -> initEnglish(this, cp, position) | |||
AppConstants.SUBJECT_CHINESE -> initChinese(this, cp, position) | |||
} | |||
root.click { | |||
onItemClick.invoke(it, position, cp) | |||
@@ -65,15 +59,15 @@ class AdapterCoursePackWithLearCenter(vm: CoursePackFragmentViewModel) : | |||
//图标 | |||
coursePack.childrenCourses.forEach { | |||
when(it.courseType){ | |||
Constants.COURSE_TYPE_ENGLISH_DISCERN -> imageViewTypeDiscern.visibility = View.VISIBLE | |||
Constants.COURSE_TYPE_ENGLISH_SPELL -> imageViewTypeSpell.visibility = View.VISIBLE | |||
Constants.COURSE_TYPE_ENGLISH_VOICE -> { | |||
AppConstants.COURSE_TYPE_ENGLISH_DISCERN -> imageViewTypeDiscern.visibility = View.VISIBLE | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL -> imageViewTypeSpell.visibility = View.VISIBLE | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | |||
imageViewTypeVoice.run { | |||
visibility = View.VISIBLE | |||
setImageResource(R.drawable.ic_voice) | |||
} | |||
} | |||
Constants.COURSE_TYPE_ENGLISH_SPOKEN -> { | |||
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> { | |||
imageViewTypeVoice.run{ | |||
visibility = View.VISIBLE | |||
setImageResource(R.drawable.ic_spoken) |
@@ -0,0 +1,135 @@ | |||
package com.xkl.cdl.adapter | |||
import android.content.res.ColorStateList | |||
import android.view.View | |||
import android.view.ViewGroup | |||
import androidx.core.content.ContextCompat | |||
import com.suliang.common.base.adapter.BaseAdapterVM | |||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import com.xkl.cdl.databinding.ItemCourseLessonBinding | |||
import com.xkl.cdl.module.m_center_learn.coursechildren.CourseMainFragmentViewModel | |||
/** | |||
* author suliang | |||
* create 2022/3/29 16:43 | |||
* Describe: 课程课时列表适配器 | |||
*/ | |||
class AdapterLesson(vm: CourseMainFragmentViewModel) : BaseAdapterVM<Lesson, CourseMainFragmentViewModel>(vm) { | |||
/** 选中item的位置 */ | |||
var selectPos = -1 | |||
override fun coverViewHolder(parent: ViewGroup, viewType: Int): BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_course_lesson)) | |||
} | |||
override fun onBindVH(holder: BaseAdapterViewHolder, position: Int) { | |||
val lesson = getItem(position) | |||
(holder.binding as ItemCourseLessonBinding).run { | |||
data = lesson | |||
//章节名称是否显示 | |||
if (position == 0 || lesson.chapterId != getItem(position - 1).chapterId) { //不为第一个个且与上一个章节id相同 | |||
tvChapterName.visibility = View.VISIBLE | |||
} else { | |||
tvChapterName.visibility = View.GONE | |||
} | |||
//执行 | |||
executePendingBindings() | |||
initColor(position, lesson) | |||
when(lesson.lessonType){ | |||
AppConstants.LESSON_TYPE_COMPOSITION_VIDEO -> { // 作文视频 | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_EXAM -> { //作文章节测试 | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_READING -> { //作文课堂练习 | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_TASK -> { //作文课外练习 | |||
} | |||
AppConstants.LESSON_TYPE_DIALOGUE -> { //口语对话 | |||
} | |||
else -> { } // 其他课时类型为布局的正常显示 | |||
} | |||
//事件: 将章节名称的点击事件取消了 | |||
layoutContent.click { | |||
//选中项非当前项,则需要改变选中颜色,直接通知更新,调用对应位置的notfy | |||
if (selectPos != position) { | |||
notifyItemChanged(selectPos) | |||
selectPos = position | |||
notifyItemChanged(selectPos) | |||
} | |||
notifyItemChanged(position) | |||
notifyItemChanged(position, null) | |||
onItemClick.invoke(it, position, lesson) | |||
} | |||
} | |||
} | |||
/** | |||
* 处理颜色 选中色 未选中色(学习完成/学习未完成) | |||
* @receiver ItemCourseLessonBinding | |||
* @param position Int | |||
* @param lesson Lesson | |||
*/ | |||
private fun ItemCourseLessonBinding.initColor(position: Int, lesson: Lesson) { | |||
val normalColorNotLearnOver = ContextCompat.getColor(context, R.color.gray_2) //学习未完成未选中时的颜色 | |||
val normalColorLearnOver = ContextCompat.getColor(context, R.color.gray_1) //学习已完成未选中时的颜色 | |||
val mainTextColor = ContextCompat.getColor(context, R.color.main_text_color) //选中颜色 | |||
val translationColor = ContextCompat.getColor(context, R.color.translation) //透明颜色 | |||
//item的背景和状态设置 | |||
if (selectPos == position) { //选中,背景设置 | |||
layoutContent.setBackgroundColor(ContextCompat.getColor(context, R.color.gray_3)) //选中背景 | |||
tvLessonName.run { | |||
setTextColor(mainTextColor) //课时名称颜色 | |||
paint.isFakeBoldText = true//加粗 | |||
} | |||
tvLessonNumber.setTextColor(normalColorNotLearnOver) //数量颜色 | |||
//箭头 | |||
ivArrowRight.apply { | |||
setBackgroundColor(ContextCompat.getColor(context, R.color.theme_color)) | |||
imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.white)) | |||
strokeColor = ColorStateList.valueOf(translationColor) | |||
} | |||
} else { //未选中:根据学习情况判断 | |||
layoutContent.setBackgroundColor(translationColor) //未选中背景透明 | |||
if (lesson.learnIsOver) { | |||
tvLessonName.run { | |||
setTextColor(normalColorLearnOver) //课时名称颜色 | |||
paint.isFakeBoldText = false //加粗 | |||
} | |||
tvLessonNumber.setTextColor(normalColorLearnOver) //数量颜色 | |||
ivArrowRight.run { | |||
setBackgroundColor(translationColor) | |||
imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.theme_color)) | |||
strokeColor = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.theme_color)) | |||
} | |||
} else { | |||
tvLessonName.run { | |||
setTextColor(normalColorNotLearnOver) //课时名称颜色 | |||
paint.isFakeBoldText = false //加粗 | |||
} | |||
tvLessonNumber.setTextColor(normalColorNotLearnOver) //数量颜色 | |||
ivArrowRight.run { | |||
setBackgroundColor(translationColor) | |||
imageTintList = ColorStateList.valueOf(normalColorNotLearnOver) | |||
strokeColor = ColorStateList.valueOf(normalColorNotLearnOver) | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -5,61 +5,114 @@ package com.xkl.cdl.data | |||
* create 2022/3/18 9:34 | |||
* Describe: | |||
*/ | |||
object Constants { | |||
object AppConstants { | |||
/** 项目: 英语 */ | |||
const val SUBJECT_ENGLISH = 3 | |||
/** 项目: 语文*/ | |||
const val SUBJECT_CHINESE = 1 | |||
/**课程包类型: categoryId -> 英语单词课程 */ | |||
const val COURSEPACK_TYPE_ENGLISH_WORD = 1 | |||
/**课程包类型: categoryId -> 英语音标课程 */ | |||
const val COURSEPACK_TYPE_ENGLISH_SOUNDMARK = 4 | |||
/**课程包类型: categoryId -> 英语口语 */ | |||
const val COURSEPACK_TYPE_ENGLISH_SPOKEN = 13 | |||
/**课程包类型: categoryId -> 语文作文 */ | |||
const val COURSEPACK_TYPE_CHINESE_COMPOSITION = 2 | |||
/**课程包类型: categoryId -> 语文识字 */ | |||
const val COURSEPACK_TYPE_CHINESE_LITERACY = 3 | |||
/**课程包类型: categoryId -> 语文拼音 */ | |||
const val COURSEPACK_TYPE_CHINESE_PINYIN = 1 | |||
/**课程类型: typeId 英语认读*/ | |||
const val COURSE_TYPE_ENGLISH_DISCERN = 1 | |||
/**课程类型: typeId 英语辨音*/ | |||
const val COURSE_TYPE_ENGLISH_VOICE = 2 | |||
/**课程类型: typeId 英语拼写*/ | |||
const val COURSE_TYPE_ENGLISH_SPELL = 3 | |||
/**课程类型: typeId 英语音标*/ | |||
const val COURSE_TYPE_ENGLISH_SOUNDMARK = 6 | |||
/**课程类型: typeId 英语口语*/ | |||
const val COURSE_TYPE_ENGLISH_SPOKEN = 8 | |||
/**课程类型: typeId 语文作文*/ | |||
const val COURSE_TYPE_CHINESE_COMPOSITION = 4 | |||
/**课程类型: typeId 语文识字*/ | |||
const val COURSE_TYPE_CHINESE_LITERACY = 5 | |||
/**课程类型: typeId 语文拼音*/ | |||
const val COURSE_TYPE_CHINESE_PINYIN = 7 | |||
/**课时类型: 词汇, 口语词汇*/ | |||
const val LESSON_TYPE_WORD = 1 | |||
const val LESSON_TYPE_WORD = 6 | |||
/**课时类型: 口语句型*/ | |||
const val LESSON_TYPE_SENTENCE = 2 | |||
const val LESSON_TYPE_SENTENCE = 7 | |||
/**课时类型: 口语对话*/ | |||
const val LESSON_TYPE_DIALOGUE = 3 | |||
const val LESSON_TYPE_DIALOGUE = 8 | |||
/**课时类型: 作文视频*/ | |||
const val COMPOSITION_TYPE_VIDEO = 4 //视频 | |||
const val LESSON_TYPE_COMPOSITION_VIDEO = 1 //视频 | |||
/**课时类型: 作文知识点学习*/ | |||
const val COMPOSITION_TYPE_KNOWLEDGE = 5 //知识点学习 | |||
const val LESSON_TYPE_COMPOSITION_KNOWLEDGE = 2 //知识点学习 | |||
/**课时类型: 作文知识点测试*/ | |||
const val COMPOSITION_TYPE_EXAM = 6 //知识点测试 | |||
const val LESSON_TYPE_COMPOSITION_EXAM = 3 //知识点测试 | |||
/**课时类型: 作文课堂练习*/ | |||
const val COMPOSITION_TYPE_READING = 7 //课堂练习 | |||
const val LESSON_TYPE_COMPOSITION_READING = 4 //课堂练习 | |||
/**课时类型: 作文课外练习*/ | |||
const val COMPOSITION_TYPE_TASK = 8 //课外练习 | |||
const val LESSON_TYPE_COMPOSITION_TASK = 5 //课外练习 | |||
// 分组(1:普通测试(词汇测试,不做redis统计关联) 2:章节学前测试 3:章节学后测试 4:学前总测试 5:学后总测试 6:备忘录测试(不做redis统计关联);7:作文知识点测试,8:服务中心的课程测试) | |||
/**普通测试(词汇测试,不做redis统计关联)*/ | |||
const val TEST_TYPE_NORMAL = 1 | |||
/**学前测试*/ | |||
const val TEST_TYPE_BEFORE = 2 | |||
/**学后测试*/ | |||
const val TEST_TYPE_AFTER = 3 | |||
/**学前总测试*/ | |||
const val TEST_TYPE_BEFORE_TOTAL = 4 | |||
/**学后总测试*/ | |||
const val TEST_TYPE_AFTER_TOTAL = 5 | |||
/**备忘录测试*/ | |||
const val TEST_TYPE_MEMO = 6 | |||
/**作文知识点测试*/ | |||
const val TEST_TYPE_COMPOSITION = 7 | |||
/**服务中心的课程测试*/ | |||
const val TEST_TYPE_SERVICE_CENTER = 8 | |||
/** 未做测试,没有做等用-1表示的内容 */ | |||
const val NOT_DOING = -1.0 | |||
/** 测试通过:>80 < 90 继续加油 <80 悲伤 */ | |||
const val TEST_SCORE_LEVEL_1 = 80 | |||
/** 测试通过 >= 太棒了 */ | |||
const val TEST_SCORE_LEVEL_2 = 90 | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.xkl.cdl.data | |||
import com.suliang.common.AppConfig | |||
/** | |||
* author suliang | |||
* create 2022/3/28 9:52 | |||
* Describe: 用于数据传递 | |||
*/ | |||
class DataTransferHolder private constructor(){ | |||
companion object{ | |||
val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { | |||
DataTransferHolder() | |||
} | |||
} | |||
private val dataMap = hashMapOf<String,Any>() | |||
fun <T : Any> putData(t : T){ | |||
dataMap.put(AppConfig.INTENT_1,t) | |||
} | |||
@Suppress("UNCHECKED_CAST") | |||
fun <T> getData() : T{ | |||
return dataMap.get(AppConfig.INTENT_1) as T | |||
} | |||
fun clear(){ | |||
dataMap.clear() | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
package com.xkl.cdl.data.bean | |||
import com.xkl.cdl.R | |||
/** | |||
* 数据基类 | |||
* @property subjectId Long 项目id | |||
* @property coursePackId Long 课程包id | |||
* @property courseId Long 课程id | |||
* @property coursePackType Int 课程包类型 | |||
* @property courseType Int 课程类型 | |||
* @property chapterId Long 章节id | |||
* @property lessonId Long 课时id | |||
* @property wordId Long 内容id | |||
* @property first Boolean 是否第一次出现 | |||
* @property reviewNum Int 大七次次数 | |||
* @property reviewTime Long 复习时间 | |||
* @property createTime Long 创建时间 | |||
* @property repeatNum Int 小七次次数 | |||
* @property showColor Int 显示颜色 | |||
* @property lessonType Int 课时类型 | |||
* @constructor | |||
*/ | |||
open class BaseWord(val subjectId: Int, | |||
val coursePackId: Long, | |||
val courseId: Long, | |||
val coursePackType: Int, | |||
val courseType: Int, | |||
val chapterId: Long, | |||
val lessonId: Long, | |||
val wordId: Long, | |||
val first: Boolean, | |||
val lessonType: Int) { | |||
/** 大复习次数 */ | |||
var reviewNum: Int = 0 | |||
/**复习时间*/ | |||
var reviewTime: Long = 0 | |||
/** 创建时间 */ | |||
var createTime: Long = 0 | |||
/**重复的次数*/ | |||
var repeatNum: Int = 0 | |||
/**显示颜色*/ | |||
var showColor: Int = 0 | |||
get() { | |||
return when (repeatNum) { | |||
0 -> R.color.num0 | |||
1 -> R.color.num1 | |||
2 -> R.color.num2 | |||
3 -> R.color.num3 | |||
4 -> R.color.num4 | |||
5 -> R.color.num5 | |||
6 -> R.color.num6 | |||
7 -> R.color.num7 | |||
else -> R.color.num0 | |||
} | |||
} | |||
private set | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.data.bean | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
/** | |||
* author suliang | |||
* create 2022/4/2 14:55 | |||
* Describe: 课时学习时的传参 | |||
*/ | |||
class IntentLearnData(val lesson: Lesson) { | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.xkl.cdl.data.bean | |||
/** | |||
* author suliang | |||
* create 2022/3/31 17:52 | |||
* Describe: 用于学习的数据 | |||
*/ | |||
class LearnWord(subjectId: Int, | |||
coursePackId: Long, | |||
courseId: Long, | |||
coursePackType: Int, | |||
courseType: Int, | |||
chapterId: Long, | |||
lessonId: Long, | |||
wordId: Long, | |||
first: Boolean, | |||
lessonType: Int) : BaseWord(subjectId, | |||
coursePackId, | |||
courseId, | |||
coursePackType, | |||
courseType, | |||
chapterId, | |||
lessonId, | |||
wordId, | |||
first, | |||
lessonType) { | |||
var word: String? = null //词汇 | |||
var phonetic_uk: String? = null // 英式音标 | |||
var phonetic_us: String? = null // 美式音标 | |||
var phonetic_cn: String? = null // 中文拼音 | |||
var photo: String? = null // 图片 | |||
var audio: String? = null // 音频 | |||
var basic_explanation: String? = null //基本释义 | |||
var all_explanation: String? = null //扩展释义 | |||
var phrase: String? = null //词组 | |||
var example: String? = null //例句 | |||
var reference: String? = null //参考 | |||
var literacyIspolyphone = false //识字课程,是否是多音字标识 | |||
var pattern: String? = null //口语: 语法 | |||
} |
@@ -1,19 +0,0 @@ | |||
package com.xkl.cdl.data.bean | |||
/** | |||
* author suliang | |||
* create 2022/3/21 17:10 | |||
* Describe: | |||
*/ | |||
data class Lesson( | |||
val subjectId: Long, | |||
val coursePackId:Long, | |||
val courseId:Long, | |||
val chapterId:Long, | |||
val chapterName: String, | |||
val lessonId:Long, | |||
val lessonName:String | |||
) { | |||
/** 课时类型 */ | |||
var lessonType : Int = 0 | |||
} |
@@ -1,6 +1,4 @@ | |||
package com.xkl.cdl.data.course | |||
import com.xkl.cdl.data.bean.Lesson | |||
package com.xkl.cdl.data.bean.course | |||
/** | |||
* author suliang | |||
@@ -26,7 +24,9 @@ data class Course( | |||
val totalWords: Int, | |||
val dbPathName: String | |||
) { | |||
var allLesson: ArrayList<Lesson>? = null | |||
var courseLearnProgress : Double = 0.0 //课程学习进度 | |||
var courseReviewNumber : Int = 0 //课程复习数 | |||
} |
@@ -0,0 +1,38 @@ | |||
package com.xkl.cdl.data.bean.course | |||
import android.R.bool | |||
/** | |||
* author suliang | |||
* create 2022/3/29 9:52 | |||
* Describe: 课程学习的详情 | |||
*/ | |||
class CourseDetail { | |||
var courseLearnProgress: Double = 0.0 //课程学习进度 | |||
var st_before: Double = -1.0 //学前总成绩 : -1代表没有进行学前总测试 | |||
var st_after: Double = -1.0 //学后总成绩 : -1代表没有进行学后总测试 | |||
var before: HashMap<String, Double> = hashMapOf() //章节学前测试成绩,key=>{chapter_id}_{lesson_id} value=>成绩 | |||
var after: HashMap<String, Double> = hashMapOf() //章节学后测试成绩,key=>{chapter_id}_{lesson_id} value=>成绩 | |||
var right = hashMapOf<String, Int>() //正确条目数,key=>{chapter_id}_{lesson_id} value=>条目数量 | |||
var wrong: HashMap<String, Int> = hashMapOf() //错误条目数,key=>{chapter_id}_{lesson_id} value=>条目数量 | |||
var lesson_learn_point: HashMap<String, Long> = hashMapOf() //章节学习点 key=>{chapter_id}_{lesson_id} value=>{entity_id) | |||
var exam_w_r_list: HashMap<String, bool> = hashMapOf() //课程/课时学前测试正确错误列表 key=> {chapter_id}_{lesson_id}_{entity_id} value=>正确 true;错误 false | |||
var course_learn_point: String = "" //课程学习进度点 {chapter_id}_{lesson_id}_{entity_id} | |||
var rl: Int = 0 //课程重学次数;有值表示是重新学,默认不是重新学习,对应数值表示第几次重学 用于辨音,拼写判断是否解锁, | |||
var chapter_rl: HashMap<String, Long> = hashMapOf() //章节重学次数,key =>{chapter_id}_{lesson_id} value=> relearn times | |||
var ct: Long = 0 //课程已学词汇量 | |||
var e = 0.0 //学习效率 | |||
var valid: HashMap<Long, Long> = hashMapOf() //有效学习时长,单位毫秒 key=>分时标记,value=>时长 | |||
var review: HashMap<Long, Long> = hashMapOf() //有效复习时长,单位毫秒 key=>分时标记,value=>时长 | |||
var total: HashMap<Long, Long> = hashMapOf() //总时长,单位毫秒 key=>分时标记,value=>时长 | |||
var current_week_total_durations: Long = 0 | |||
var last_e: Double = 0.0 //上周期学习效率 | |||
var temporary_words: HashMap<String, String> = hashMapOf() //课程错误本,重学会删除 key=>{chapter_id}_{lesson_id}_{entity_id} value=> first learn time | |||
var vp: HashMap<Long, String> = hashMapOf() //视频播放点,记录最新的就行 时间点 key=>video_id value=>{时间点} | |||
var exercise_schedule: HashMap<Long, Double> = hashMapOf() //课程练习进度(仅作文有效) | |||
} |
@@ -1,4 +1,4 @@ | |||
package com.xkl.cdl.data.course | |||
package com.xkl.cdl.data.bean.course | |||
import androidx.databinding.BaseObservable | |||
import androidx.databinding.Bindable | |||
@@ -25,6 +25,8 @@ data class CoursePack( | |||
val subjectId: Int, | |||
val coursePackType: Int, | |||
) : BaseObservable() { | |||
//在CourseManger中的subjectWithCoursePackMap对应subject下的list中所在的位置 | |||
var inCoursePackPosition : Int = 0 | |||
var childrenCourses = mutableListOf<Course>() | |||
@@ -0,0 +1,69 @@ | |||
package com.xkl.cdl.data.bean.course | |||
import androidx.databinding.BaseObservable | |||
import androidx.databinding.Bindable | |||
import com.suliang.common.BR | |||
import com.xkl.cdl.data.AppConstants | |||
/** | |||
* author suliang | |||
* create 2022/3/21 17:10 | |||
* Describe: 课时,通过lessonType判断课时类型 | |||
*/ | |||
data class Lesson( | |||
val subjectId: Int, | |||
val coursePackId:Long, | |||
val courseId:Long, | |||
var courseType: Int, | |||
val chapterId:Long, | |||
val chapterName: String, | |||
val lessonId:Long, | |||
val lessonName:String | |||
):BaseObservable() { | |||
/** 课时类型 : 默认为单词类型 */ | |||
var lessonType : Int = 0 | |||
/** 课时在列表中的位置 */ | |||
var lessonPositionInList : Int = 0 | |||
/** 该课时的总数据 或者作文关联的数据,如视频关联的内容*/ | |||
var wordIds = mutableListOf<Long>() | |||
/** 学习进度位置,为医学下标的位置,在作文课堂练习时,学习取当前条,其他取下一条*/ | |||
var learnedIndex: Int = 0 | |||
/**课时学前测试成绩 */ | |||
var beforeTestScore = -1.0 | |||
/** 课时学后测试 */ | |||
var afterTestScore = -1.0 | |||
/**是否学习完成: 为学习内容是否完成,不包含学前,学后测试*/ | |||
var learnIsOver = false | |||
/**是否是最后一个课时 */ | |||
var lastLesson : Boolean = false | |||
//总数量 | |||
@get:Bindable | |||
var totalNumber:Int = 0 | |||
set(value) { | |||
field = value | |||
notifyPropertyChanged(BR.totalNumber) | |||
} | |||
//正确数 | |||
@get:Bindable | |||
var correctNumber:Int = 0 | |||
set(value) { | |||
field = value | |||
notifyPropertyChanged(BR.correctNumber) | |||
} | |||
//错误数 | |||
@get:Bindable | |||
var errorNumber:Int = 0 | |||
set(value) { | |||
field = value | |||
notifyPropertyChanged(BR.errorNumber) | |||
} | |||
//作文视频使用 | |||
/** 视频播放时长 */ | |||
var videoPlayTime : Int = 0 | |||
/** 视频总时长 */ | |||
var videoTotalTime : Int = 0 | |||
} |
@@ -1,17 +1,13 @@ | |||
package com.xkl.cdl.data.binding | |||
import android.graphics.BitmapFactory | |||
import android.graphics.drawable.Drawable | |||
import android.widget.ImageView | |||
import android.widget.TextView | |||
import androidx.core.graphics.drawable.DrawableCompat | |||
import androidx.databinding.BindingAdapter | |||
import com.suliang.common.util.DrawableUti | |||
import com.suliang.common.util.image.ImageLoader | |||
import com.suliang.common.util.image.ImageLoaderOption | |||
import com.xkl.cdl.R | |||
import kotlinx.coroutines.NonCancellable.start | |||
import org.w3c.dom.Text | |||
import java.math.BigDecimal | |||
import java.math.RoundingMode | |||
import java.text.DecimalFormat | |||
@@ -36,7 +32,7 @@ object BindingAdapter { | |||
// view.setImageBitmap(BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.size)) | |||
} | |||
@BindingAdapter(value = ["imgByteArray","blur"]) | |||
@BindingAdapter(value = ["imgBytes","blur"]) | |||
@JvmStatic | |||
fun imageByteArray(view:ImageView,imgByteArray:ByteArray,blur:Boolean){ | |||
ImageLoader.loadImage(ImageLoaderOption().apply { |
@@ -1,9 +1,11 @@ | |||
package com.xkl.cdl.data.manager | |||
import com.suliang.common.util.file.FileUtil | |||
import com.xkl.cdl.data.course.Course | |||
import com.xkl.cdl.data.course.CoursePack | |||
import com.xkl.cdl.data.bean.course.CoursePack | |||
import java.io.File | |||
import java.math.BigDecimal | |||
import java.math.RoundingMode | |||
import java.text.DecimalFormat | |||
/** | |||
* author suliang | |||
@@ -73,20 +75,38 @@ object CourseManager { | |||
* 检查课程包下课程的db数据文件是否存在,不存在,则复制过去 | |||
*/ | |||
fun checkCourseDb() { | |||
subjectWithCoursePackMap.forEach{entry -> | |||
entry.value.forEach{ coursePack -> | |||
subjectWithCoursePackMap.forEach { entry -> | |||
entry.value.forEach { coursePack -> | |||
coursePack.childrenCourses.forEach { | |||
val file = File( | |||
FileUtil.getSaveDirPath("db"), | |||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${it.dbPathName}" | |||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db" | |||
) | |||
//不存在,复制,存在则不操作 | |||
if (!file.exists()){ | |||
FileUtil.copyAsset(it.dbPathName,file) | |||
if (!file.exists()) { | |||
FileUtil.copyAsset(it.dbPathName, file) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* 用于显示的进度 | |||
* @param progress Double 课程的进度 | |||
* @return String | |||
*/ | |||
@JvmStatic | |||
fun useToShowProgress(progress: Double): String { | |||
return when { | |||
progress == 0.0 -> "0" | |||
progress < 0.1 -> "0.1" | |||
progress < 100 -> DecimalFormat("#.#").apply { | |||
//直接舍弃 | |||
roundingMode = RoundingMode.DOWN | |||
}.format(BigDecimal(progress)) | |||
else -> "100" | |||
} | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
package com.xkl.cdl.data.manager | |||
import com.suliang.common.util.file.FileUtil | |||
import com.xkl.cdl.data.manager.db.DbControlBase | |||
import java.io.File | |||
/** | |||
* author suliang | |||
* create 2022/4/1 11:23 | |||
* Describe: 地址管理 | |||
*/ | |||
class FilePathManager { | |||
companion object{ | |||
/** | |||
* 获取课程包目录数据所在的地址 | |||
* @return File | |||
*/ | |||
@JvmStatic | |||
fun getCoursePackDbPath(): File{ | |||
return File(FileUtil.getSaveDirPath("db"), "course-pack.db") | |||
} | |||
/** 获取课程数据地址 */ | |||
@JvmStatic | |||
fun getCourseDbPath(base:DbControlBase): File{ | |||
return File(FileUtil.getSaveDirPath("db"), "${base.subjectId}/${base.coursePackId}/${base.courseId}/course.db") | |||
} | |||
/** 获取课程数据地址 */ | |||
@JvmStatic | |||
fun getCourseDbPath(subjectId:Int,coursePackId:Long,courseId:Long): File{ | |||
return File(FileUtil.getSaveDirPath("db"), "subjectId/coursePackId/courseId/course.db") | |||
} | |||
} | |||
} |
@@ -1,10 +0,0 @@ | |||
package com.xkl.cdl.data.manager.db | |||
/** | |||
* author suliang | |||
* create 2022/3/21 16:10 | |||
* Describe: 作文数据库 | |||
*/ | |||
object CompositionDbManager : IDB { | |||
} |
@@ -1,7 +1,14 @@ | |||
package com.xkl.cdl.data.manager.db | |||
import com.xkl.cdl.data.Constants | |||
import com.xkl.cdl.data.bean.Lesson | |||
import android.annotation.SuppressLint | |||
import android.widget.Toast | |||
import com.suliang.common.util.AppGlobals | |||
import com.suliang.common.util.thread.AppExecutors | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.CourseDetail | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import com.xkl.cdl.data.manager.FilePathManager | |||
import net.sqlcipher.database.SQLiteDatabase | |||
/** | |||
* author suliang | |||
@@ -9,19 +16,151 @@ import com.xkl.cdl.data.bean.Lesson | |||
* Describe: 课程数据库管理类,主要用于读取数据 | |||
*/ | |||
object DBCourseManager { | |||
private var currentBase = DbControlBase() | |||
private const val NORMAL = "XKL_COURSE_DATA_KEY" | |||
private const val SPOKEN = "XKL_SPOKEN_COURSE_DATA_KEY" | |||
private const val COMPOSITION = "XKL_LOCAL_COMPOSITION_DATA_KEY" | |||
private const val LITERACY = "XKL_LOCAL_CHINESE_COURSE_KEY" | |||
private var mDataBase: SQLiteDatabase? = null | |||
fun getDb(subjectId:Int,coursePackId:Long,courseId:Long):IDB{ | |||
return if (subjectId == Constants.SUBJECT_ENGLISH){ | |||
EnglishDbManager | |||
}else{ | |||
CompositionDbManager | |||
private fun open(base: DbControlBase) { | |||
synchronized(DBCourseManager) { | |||
if (mDataBase != null && currentBase != base) { | |||
mDataBase?.close() | |||
mDataBase = null | |||
} | |||
if (mDataBase == null) { | |||
currentBase = base | |||
val p = when (base.courseType) { | |||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION | |||
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> SPOKEN | |||
AppConstants.COURSE_TYPE_CHINESE_LITERACY -> LITERACY | |||
else -> NORMAL | |||
} | |||
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path, | |||
p, | |||
null, | |||
SQLiteDatabase.OPEN_READONLY) | |||
} | |||
if (mDataBase == null) { | |||
AppExecutors.mainThread.run { | |||
Toast.makeText(AppGlobals.application, "课程数据获取失败,请重启应用或联系业务员", Toast.LENGTH_LONG) | |||
} | |||
} | |||
} | |||
} | |||
/**获取该课程的所有课时 | |||
* @param base DbControlBase | |||
* @param detail CourseDetail 课程信息 | |||
* @return List<Lesson> | |||
*/ | |||
@SuppressLint("Range") | |||
fun queryAllLesson(base: DbControlBase, detail: CourseDetail): List<Lesson> { | |||
val mutableList = mutableListOf<Lesson>() | |||
open(base) | |||
//聚合所有课时,先所有chapter_sort和word_sort排序,然后根据leesonId分组并聚合leeson_id到 | |||
val rawQurySql = when (base.courseType) { | |||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | |||
"SELECT * FROM chapter ORDER by chapter_sort asc" | |||
} | |||
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> { //口语查询暂时与 单词一致 | |||
"SELECT *,group_concat(word_id,',') as wordIds FROM (select * from chapter ORDER By chapter_sort asc, word_sort asc) GROUP by lesson_id" | |||
} | |||
else -> { | |||
"SELECT *,group_concat(word_id,',') as wordIds FROM (select * from chapter ORDER By chapter_sort asc, word_sort asc) GROUP by lesson_id" // ORDER By chapter_sort asc, word_sort asc " | |||
} | |||
} | |||
var positionIndex = 0 | |||
mDataBase?.rawQuery(rawQurySql, null)?.let { | |||
while (it.moveToNext()) { | |||
val chapterId: Long = it.getLong(it.getColumnIndex("chapter_id")) | |||
val chapterName: String = it.getString(it.getColumnIndex("chapter_title")) | |||
val lessonId = it.getLong(it.getColumnIndex("lesson_id")) | |||
val lessonName = when (base.courseType) { | |||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> it.getString(it.getColumnIndex("lesson_title")) | |||
else -> it.getString(it.getColumnIndex("lesson")) | |||
} | |||
val wordIds = when (base.courseType) { | |||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> it.getString(it.getColumnIndex("relation_id")) | |||
.split(",") | |||
else -> it.getString(it.getColumnIndex("wordIds")).split(",") | |||
}.map { value -> value.toLong() }.toMutableList() | |||
val lessonType: Int = when (base.courseType) { | |||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> it.getInt(it.getColumnIndex("type")) | |||
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> it.getInt(it.getColumnIndex("lesson_type")) | |||
else -> AppConstants.LESSON_TYPE_WORD | |||
} | |||
val key = "${chapterId}_${lessonId}" | |||
val learnIndex = wordIds.indexOf(detail.lesson_learn_point.getOrElse(key, { -1 })) //学习位置,当前位置为已学 | |||
// 注:针对口语对话课时,如果没有学习完,是不会设置进度点的。 | |||
val learnIsOver = wordIds.size - 1 == learnIndex | |||
val lesson = Lesson(base.subjectId, | |||
base.coursePackId, | |||
base.courseId, | |||
base.courseType, | |||
chapterId, | |||
chapterName, | |||
lessonId, | |||
lessonName).apply { | |||
lessonPositionInList = positionIndex | |||
this.wordIds = wordIds //内容 | |||
totalNumber = this.wordIds.size //总数 | |||
correctNumber = detail.right.getOrElse(key, { 0 }) //正确数 | |||
errorNumber = detail.wrong.getOrElse(key, { 0 }) //错误数 | |||
beforeTestScore = detail.before.getOrElse(key, { -1.0 }) //课时学前测试成绩 | |||
afterTestScore = detail.after.getOrElse(key, { -1.0 }) //课时学后测试成绩 | |||
this.learnedIndex = learnIndex //学习位置,当前位置为已学 | |||
this.learnIsOver = learnIsOver | |||
this.lessonType = lessonType | |||
} | |||
mutableList.add(lesson) | |||
positionIndex += 1 | |||
} | |||
it.close() | |||
} | |||
mutableList.last().lastLesson = true | |||
return mutableList.toList() | |||
} | |||
/** 获取总测试的数据 */ | |||
fun queryTotalTest(coursePackId: Long, courseId: Long) { | |||
} | |||
/** 获取课时测试数据 */ | |||
fun queryLessonTest(coursePackId: Long, courseId: Long, chapterId: Long, lessonId: Long, courseType: Long) { | |||
} | |||
/** 获取指定课时(指定数据源wordIds)的随机个数测试数据 */ | |||
fun queryLessonTestRandomSize(coursePackId: Long, | |||
courseId: Long, | |||
chapterId: Long, | |||
lessonId: Long, | |||
courseType: Long, | |||
limitSize: Int, | |||
wordIds: ArrayList<Long>? = null) { | |||
} | |||
/** 获取课时学习内容 */ | |||
fun queryLessonLearnData(coursePackId: Long, | |||
courseId: Long, | |||
chapterId: Long, | |||
lessonId: Long, | |||
wordIds: ArrayList<Long>) { | |||
} | |||
/** 获取课程今日需要复习的数据 */ | |||
fun queryCourseReviewDatas(coursePackId: Long, courseId: Long, wordIds: ArrayList<Long>) { | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.data.manager.db | |||
/** | |||
* author suliang | |||
* create 2022/4/1 11:06 | |||
* Describe: 用于查询数据库需要的基本信息 | |||
*/ | |||
data class DbControlBase( | |||
val subjectId: Int = 0, | |||
val coursePackId: Long = 0, | |||
val courseId: Long = 0, | |||
var courseType: Int = 0) |
@@ -1,13 +1,13 @@ | |||
package com.xkl.cdl.data.manager.db | |||
import com.suliang.common.util.file.FileUtil | |||
import com.xkl.cdl.data.Constants | |||
import com.xkl.cdl.data.course.Course | |||
import com.xkl.cdl.data.course.CoursePack | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.Course | |||
import com.xkl.cdl.data.bean.course.CoursePack | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.data.manager.FilePathManager | |||
import net.sqlcipher.database.SQLiteDatabase | |||
import net.sqlcipher.database.SQLiteDatabase.OPEN_READONLY | |||
import java.io.File | |||
/** | |||
* author suliang | |||
@@ -20,8 +20,12 @@ class DbCoursePackManager { | |||
private val database: SQLiteDatabase | |||
init { | |||
val coursePackDbPath = FileUtil.getSaveDirPath("db") + File.separator + "course-pack.db" | |||
database = SQLiteDatabase.openDatabase(coursePackDbPath, "XUEKAOLE_COURSE_LIST_KEY", null, OPEN_READONLY) | |||
//数据文件是否存在 | |||
val coursePackFile = FilePathManager.getCoursePackDbPath() | |||
if (!coursePackFile.exists()) { | |||
val copyAssetResult = FileUtil.copyAsset("course-pack.db", coursePackFile) | |||
} | |||
database = SQLiteDatabase.openDatabase(coursePackFile.path, "XUEKAOLE_COURSE_LIST_KEY", null, OPEN_READONLY) | |||
} | |||
/*** | |||
@@ -66,16 +70,18 @@ class DbCoursePackManager { | |||
cursor.close() | |||
} | |||
} | |||
if (subjectId == Constants.SUBJECT_ENGLISH) { | |||
if (subjectId == AppConstants.SUBJECT_ENGLISH) { | |||
coursePack.inCoursePackPosition = englishCoursePack.size | |||
englishCoursePack.add(coursePack) | |||
} else { | |||
coursePack.inCoursePackPosition = englishCoursePack.size | |||
chineseCoursePack.add(coursePack) | |||
} | |||
} | |||
it.close() | |||
} | |||
CourseManager.subjectWithCoursePackMap[Constants.SUBJECT_ENGLISH] = englishCoursePack.toList() | |||
CourseManager.subjectWithCoursePackMap[Constants.SUBJECT_CHINESE] = chineseCoursePack.toList() | |||
CourseManager.subjectWithCoursePackMap[AppConstants.SUBJECT_ENGLISH] = englishCoursePack.toList() | |||
CourseManager.subjectWithCoursePackMap[AppConstants.SUBJECT_CHINESE] = chineseCoursePack.toList() | |||
database.close() | |||
return true | |||
} |
@@ -1,11 +0,0 @@ | |||
package com.xkl.cdl.data.manager.db | |||
/** | |||
* author suliang | |||
* create 2022/3/21 16:09 | |||
* Describe: 英语数据库 | |||
*/ | |||
object EnglishDbManager : IDB { | |||
} |
@@ -1,32 +0,0 @@ | |||
package com.xkl.cdl.data.manager.db | |||
/** | |||
* author suliang | |||
* create 2022/3/21 16:34 | |||
* Describe: 英语数据库接口 | |||
*/ | |||
interface IDB { | |||
// fun open(subjectId:Long,coursePackId:Long,courseId:Long) | |||
// | |||
// /**获取该课程的所有课时*/ | |||
// fun queryAllLesson() | |||
// | |||
// /** 获取总测试的数据 */ | |||
// fun queryTotalTest(coursePackId: Long,courseId: Long) | |||
// /** 获取课时测试数据 */ | |||
// fun queryLessonTest(coursePackId: Long,courseId: Long,chapterId:Long,lessonId:Long,courseType:Long) | |||
// /** 获取指定课时(指定数据源wordIds)的随机个数测试数据 */ | |||
// fun queryLessonTestRandomSize(coursePackId: Long,courseId: Long,chapterId: Long,lessonId: Long,courseType: Long,limitSize:Int,wordIds:ArrayList<Long>? = null) | |||
// | |||
// /** 获取课时学习内容 */ | |||
// fun queryLessonLearnData(coursePackId: Long,courseId: Long,chapterId: Long,lessonId: Long,wordIds:ArrayList<Long>) | |||
// | |||
// /** 获取课程今日需要复习的数据 */ | |||
// fun queryCourseReviewDatas(coursePackId: Long,courseId: Long,wordIds: ArrayList<Long>) | |||
} |
@@ -0,0 +1,37 @@ | |||
package com.xkl.cdl.data.repository | |||
import android.graphics.Bitmap | |||
import android.util.LruCache | |||
import java.security.Key | |||
/** | |||
* author suliang | |||
* create 2022/4/1 9:53 | |||
* Describe: 音频缓存获取规则 | |||
*/ | |||
object AudioCache { | |||
var lruCache : LruCache<String, ByteArray> | |||
init { | |||
lruCache = object : LruCache<String,ByteArray>((Runtime.getRuntime().maxMemory()/16).toInt()){ | |||
//告知每个对象的存储大小 | |||
override fun sizeOf(key: String?, value: ByteArray?): Int { | |||
if (value == null){ | |||
return 0 | |||
} | |||
return value.size | |||
} | |||
} | |||
} | |||
/** | |||
* 获取对应音频 | |||
* @param key String | |||
* @return ByteArray? | |||
*/ | |||
fun get(key:String) : ByteArray? { | |||
return null | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
package com.xkl.cdl.data.repository | |||
import com.xkl.cdl.data.bean.course.CourseDetail | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import com.xkl.cdl.data.manager.db.DBCourseManager | |||
import com.xkl.cdl.data.manager.db.DbControlBase | |||
import io.reactivex.rxjava3.core.Observable | |||
/** | |||
* author suliang | |||
* create 2022/3/29 10:24 | |||
* Describe: 数据提供 | |||
*/ | |||
object DataRepository { | |||
/** 获取课程的收藏本 */ | |||
fun getCourseCollect() : Observable<HashMap<String,Long>>{ | |||
return Observable.create{ | |||
it.onNext(hashMapOf()) | |||
it.onComplete() | |||
} | |||
} | |||
/** 获取复习的内容 */ | |||
fun getReviewData() : Observable<Array<String>> { | |||
return Observable.create{ | |||
mutableListOf<String>() | |||
it.onNext(Array<String>(1){"1"}) | |||
it.onComplete() | |||
} | |||
} | |||
/** 获取课程的详情 */ | |||
fun getCourseStatistics(): Observable<CourseDetail>{ | |||
return Observable.create{ | |||
val courseDetail = CourseDetail() | |||
it.onNext(courseDetail) | |||
it.onComplete() | |||
} | |||
} | |||
/** 获取课程课时 */ | |||
fun getCourseAllLesson(base: DbControlBase,courseDetail: CourseDetail):Observable<List<Lesson>>{ | |||
return Observable.create{ | |||
it.onNext(DBCourseManager.queryAllLesson(base,courseDetail)) | |||
it.onComplete() | |||
} | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
package com.xkl.cdl.dialog | |||
import android.view.View | |||
import com.suliang.common.base.BaseDialogFragment | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.util.LogUtil | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.databinding.DialogLessonLearnBinding | |||
/** | |||
* author suliang | |||
* create 2022/4/2 15:47 | |||
* Describe: 学习的通用弹窗 | |||
*/ | |||
class LearnDialog : BaseDialogFragment<DialogLessonLearnBinding>() { | |||
private lateinit var dialogListener : DialogFragmentListener | |||
override fun initFragment() { | |||
initClick() | |||
// initLessonBeforeTest() | |||
initLessonBeforeTestOver() | |||
} | |||
fun initClick(){ | |||
dialogListener = if (parentFragment != null){ | |||
parentFragment as DialogFragmentListener | |||
}else{ | |||
activity as DialogFragmentListener | |||
} | |||
} | |||
fun initLessonBeforeTest(){ | |||
binding.tvTitle.text = "课时学前测试" | |||
binding.tvLessonName.text = "章节课时名称" | |||
binding.tvCountTime.text = "测试题目时间" | |||
binding.tvRight.text = "开始测试" | |||
binding.tvLeft.visibility = View.VISIBLE | |||
binding.tvLeft.text = "随便设置" | |||
binding.tvRight.click { | |||
LogUtil.e("Dialog -- > show()") | |||
dialogListener.rightClick() | |||
} | |||
binding.tvLeft.click { | |||
LogUtil.e("Dialog -- > hide()") | |||
dialogListener.leftClick() | |||
} | |||
} | |||
fun initLessonBeforeTestOver(){ | |||
binding.tvScore.run { | |||
visibility = View.VISIBLE | |||
text = "100分" | |||
} | |||
binding.tvTip.visibility = View.VISIBLE | |||
binding.tvTitle.text = "恭喜你,完成了课时学前测试" | |||
binding.tvLessonName.visibility = View.GONE | |||
binding.tvCountTime.visibility = View.GONE | |||
binding.tvTip1.visibility = View.VISIBLE | |||
binding.tvTip1.setText(resources.getString(R.string.test_before_test_over_tip)) | |||
binding.incStatisticsNumber.root.visibility = View.VISIBLE | |||
binding.tvLeft.visibility = View.GONE | |||
binding.tvRight.setText(resources.getString(R.string.start_learn)) | |||
binding.tvRight.click { | |||
// TODO: 2022/4/2 开始学习 | |||
} | |||
} | |||
fun initLessonAfterTestOver(){ | |||
//未通过 | |||
//已通过 | |||
//已通过的再通过 | |||
} | |||
public interface DialogFragmentListener{ | |||
fun rightClick() | |||
fun leftClick() | |||
} | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.viewbinding.ViewBinding | |||
import com.suliang.common.base.activity.BaseActivityVM | |||
abstract class LearnBaseActivity<vb:ViewBinding,vm: LearnBaseViewModel> : BaseActivityVM<vb,vm>() { | |||
override fun onRestart() { | |||
super.onRestart() | |||
} | |||
override fun onResume() { | |||
super.onResume() | |||
} | |||
override fun onPause() { | |||
super.onPause() | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
/** | |||
* author suliang | |||
* create 2022/4/2 14:06 | |||
* Describe: 学习基类: 实现统一流程接口和计时实现 | |||
*/ | |||
abstract class LearnBaseViewModel : BaseViewModel() { | |||
} |
@@ -1,15 +1,12 @@ | |||
package com.xkl.cdl.module.m_center_learn | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
/** | |||
* 课程中心 | |||
*/ | |||
class CourseMainActivity : AppCompatActivity() { | |||
class LearnCReadingActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_course_main) | |||
setContentView(R.layout.activity_learn_creading) | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
class LearnCTaskActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_learn_ctask) | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
class LearnCVideoActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_learn_cvideo) | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
class LearnExamSpellActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_exam_learn_spell) | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
class LearnExamWordActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_learn_exam_word) | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
class LearnSpellActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_learn_spell) | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.xkl.cdl.module.learn | |||
import androidx.appcompat.app.AppCompatActivity | |||
import android.os.Bundle | |||
import com.xkl.cdl.R | |||
class LearnWordActivity : AppCompatActivity() { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
setContentView(R.layout.activity_learn_word) | |||
} | |||
} |
@@ -1,13 +0,0 @@ | |||
package com.xkl.cdl.module.m_center_learn | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.xkl.cdl.data.course.Course | |||
/** | |||
* author suliang | |||
* create 2022/3/24 17:42 | |||
* Describe: 课程主页 | |||
*/ | |||
class CourseMainActivityViewModel(val course: Course) : BaseViewModel() { | |||
} |
@@ -7,11 +7,10 @@ import androidx.lifecycle.ViewModel | |||
import androidx.lifecycle.ViewModelProvider | |||
import androidx.recyclerview.widget.DividerItemDecoration | |||
import androidx.recyclerview.widget.LinearLayoutManager | |||
import com.suliang.common.Config | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.base.fragment.BaseFragmentVM | |||
import com.suliang.common.util.LogUtil | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.course.CoursePack | |||
import com.xkl.cdl.databinding.FragmentCoursePackBinding | |||
import com.xkl.cdl.module.main.MainActivityViewModel | |||
@@ -25,13 +24,13 @@ class CoursePackFragment : BaseFragmentVM<FragmentCoursePackBinding,CoursePackFr | |||
@JvmStatic | |||
fun newInstance(projectId: Int) = CoursePackFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(Config.INTENT_1,projectId) | |||
putInt(AppConfig.INTENT_1,projectId) | |||
} | |||
} | |||
} | |||
override fun initViewModel(): CoursePackFragmentViewModel { | |||
val projectId = requireArguments().getInt(Config.INTENT_1) | |||
val projectId = requireArguments().getInt(AppConfig.INTENT_1) | |||
return ViewModelProvider(this,ViewModelFactory(projectId)).get(CoursePackFragmentViewModel::class.java).apply { | |||
this.mainActivityViewModel = ViewModelProvider(requireActivity()).get(MainActivityViewModel::class.java) | |||
this.learnCenterFragmentViewModel = ViewModelProvider(requireParentFragment()).get(LearnCenterFragmentViewModel::class.java) | |||
@@ -50,8 +49,9 @@ class CoursePackFragment : BaseFragmentVM<FragmentCoursePackBinding,CoursePackFr | |||
binding.contentLayout.recyclerView.apply { | |||
layoutManager = LinearLayoutManager(requireContext(),LinearLayoutManager.VERTICAL,false) | |||
adapter = vm.adpater.apply { | |||
onItemClick = { v,position,courePack -> | |||
//点击时事件,跳转 | |||
onItemClick = { v,position,coursePack -> | |||
CoursePackMainActivity.newInstance(requireContext(),coursePack.subjectId,coursePack.inCoursePackPosition) | |||
} | |||
} | |||
//分割线 |
@@ -3,7 +3,7 @@ package com.xkl.cdl.module.m_center_learn | |||
import androidx.lifecycle.MutableLiveData | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.xkl.cdl.adapter.AdapterCoursePackWithLearCenter | |||
import com.xkl.cdl.data.course.CoursePack | |||
import com.xkl.cdl.data.bean.course.CoursePack | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.module.main.MainActivityViewModel | |||
@@ -0,0 +1,283 @@ | |||
package com.xkl.cdl.module.m_center_learn | |||
import android.content.Context | |||
import android.content.Intent | |||
import android.graphics.Color | |||
import android.os.Bundle | |||
import android.view.View | |||
import androidx.core.content.ContextCompat | |||
import androidx.core.content.res.ResourcesCompat | |||
import androidx.databinding.DataBindingUtil | |||
import androidx.fragment.app.Fragment | |||
import androidx.lifecycle.ViewModel | |||
import androidx.lifecycle.ViewModelProvider | |||
import androidx.viewpager2.widget.ViewPager2 | |||
import com.google.android.material.bottomsheet.BottomSheetDialog | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.base.activity.BaseActivityVM | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.util.LogUtil | |||
import com.suliang.common.util.os.ScreenUtil | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.adapter.AdapterAutoPlaySelectRepeat | |||
import com.xkl.cdl.adapter.ViewPagerAdapter | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.binding.BindingAdapter | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.databinding.ActivityCourseMainBinding | |||
import com.xkl.cdl.databinding.DialogBottomAutoPlaySelectBinding | |||
import com.xkl.cdl.databinding.DialogBottomCourseMoreBinding | |||
import com.xkl.cdl.module.m_center_learn.coursechildren.CourseMainFragment | |||
import com.zackratos.ultimatebarx.ultimatebarx.statusBarOnly | |||
/** | |||
* 课程中心 | |||
*/ | |||
class CoursePackMainActivity : BaseActivityVM<ActivityCourseMainBinding, CoursePackMainActivityViewModel>() { | |||
companion object { | |||
@JvmStatic | |||
fun newInstance(context: Context, subjectId: Int, coursePackInPosition: Int) { | |||
context.startActivity(Intent(context, CoursePackMainActivity::class.java).apply { | |||
putExtra(AppConfig.INTENT_1, subjectId) | |||
putExtra(AppConfig.INTENT_2, coursePackInPosition) | |||
}) | |||
} | |||
} | |||
//子课程对应的Fragment | |||
private var childFragments = mutableListOf<Fragment>() | |||
//更多按钮的弹窗显示 | |||
private var moreDialog: BottomSheetDialog? = null | |||
//自动播放次数的弹窗选择 | |||
private var autoPlaySeletDialog: BottomSheetDialog? = null | |||
override fun initViewModel(): CoursePackMainActivityViewModel { | |||
val subjectId = intent.getIntExtra(AppConfig.INTENT_1, 0) | |||
val coursePackInListPosition = intent.getIntExtra(AppConfig.INTENT_2, 0) | |||
return ViewModelProvider( | |||
this, ViewModelFactory(subjectId, coursePackInListPosition) | |||
)[CoursePackMainActivityViewModel::class.java] | |||
} | |||
override fun initStatusBar() { | |||
statusBarOnly { | |||
fitWindow = false //布局是否侵入状态栏 | |||
color = Color.TRANSPARENT //透明 | |||
light = true | |||
} | |||
} | |||
override fun initActivity(savedInstanceState: Bundle?) { | |||
LogUtil.e("CoursePackMainActivity coursePackMainActivityVM hashCode -> ${vm.hashCode()}") | |||
//设置布局数据 | |||
binding.coursePack = vm.coursePack | |||
//状态栏高度设置 | |||
binding.statusBarView.layoutParams.height = ScreenUtil.getStatusBarHeight() | |||
//设置简介的箭头大小 | |||
ResourcesCompat.getDrawable(resources, R.drawable.ic_arrow_right, null)?.apply { | |||
setBounds(0, 0, 36, 36) | |||
binding.textViewIntroduction.setCompoundDrawables(null, null, this, null) | |||
} | |||
//返回事件 | |||
binding.includeTitleBar.titleBar.run { | |||
onBackClick = {_ -> finish() } | |||
} | |||
//初始化tab和viewPager | |||
initTabAndViewPager() | |||
} | |||
private fun initTabAndViewPager() { | |||
//英语课程包且为英语单词课程包才显示tab | |||
if (vm.coursePack.subjectId == AppConstants.SUBJECT_ENGLISH && vm.coursePack.coursePackType == AppConstants.COURSEPACK_TYPE_ENGLISH_WORD) { | |||
binding.includeCourseTypeTab.root.visibility = View.VISIBLE | |||
vm.coursePack.childrenCourses.forEachIndexed { index, course -> | |||
when (course.courseType) { | |||
AppConstants.COURSE_TYPE_ENGLISH_DISCERN -> { | |||
binding.includeCourseTypeTab.tabDiscern.visibility = View.VISIBLE | |||
childFragments.add(CourseMainFragment.newInstance(index)) | |||
} | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL -> { | |||
binding.includeCourseTypeTab.ivArrow1.visibility = View.VISIBLE | |||
binding.includeCourseTypeTab.tabSpell.visibility = View.VISIBLE | |||
childFragments.add(CourseMainFragment.newInstance(index)) | |||
} | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | |||
binding.includeCourseTypeTab.ivArrow2.visibility = View.VISIBLE | |||
binding.includeCourseTypeTab.tabVoice.visibility = View.VISIBLE | |||
childFragments.add(CourseMainFragment.newInstance(index)) | |||
} | |||
} | |||
} | |||
} else { //其他课程tab为空 | |||
binding.includeCourseTypeTab.root.visibility = View.GONE | |||
childFragments.add(CourseMainFragment.newInstance(0)) | |||
} | |||
//ViewPager初始 | |||
binding.viewPager2.apply { | |||
adapter = ViewPagerAdapter(this@CoursePackMainActivity, childFragments) | |||
//注册页面改变监听 | |||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { | |||
override fun onPageSelected(position: Int) { | |||
super.onPageSelected(position) | |||
//改变tab的选中颜色 | |||
if (binding.includeCourseTypeTab.root.visibility == View.VISIBLE) { //可见,才做操作 | |||
binding.includeCourseTypeTab.apply { | |||
tabDiscern.run { | |||
setTextColor( | |||
ContextCompat.getColor( | |||
this@CoursePackMainActivity, | |||
if (position == 0) R.color.theme_color else R.color.gray_2 | |||
) | |||
) | |||
BindingAdapter.loadVectorDrawable( | |||
this, ContextCompat.getColor( | |||
this@CoursePackMainActivity, | |||
if (position == 0) R.color.theme_color else R.color.gray_2 | |||
) | |||
) | |||
} | |||
tabSpell.run { | |||
setTextColor( | |||
ContextCompat.getColor( | |||
this@CoursePackMainActivity, | |||
if (position == 1) R.color.theme_color else R.color.gray_2 | |||
) | |||
) | |||
BindingAdapter.loadVectorDrawable( | |||
this, ContextCompat.getColor( | |||
this@CoursePackMainActivity, | |||
if (position == 1) R.color.theme_color else R.color.gray_2 | |||
) | |||
) | |||
} | |||
tabVoice.run { | |||
setTextColor( | |||
ContextCompat.getColor( | |||
this@CoursePackMainActivity, | |||
if (position == 2) R.color.theme_color else R.color.gray_2 | |||
) | |||
) | |||
BindingAdapter.loadVectorDrawable( | |||
this, ContextCompat.getColor( | |||
this@CoursePackMainActivity, | |||
if (position == 2) R.color.theme_color else R.color.gray_2 | |||
) | |||
) | |||
} | |||
} | |||
} | |||
//改变page后设置进度 | |||
vm.currentCourseProgress.value = vm.coursePack.childrenCourses[position].courseLearnProgress | |||
} | |||
}) | |||
} | |||
//tab点击 | |||
binding.includeCourseTypeTab.apply { | |||
tabDiscern.click { binding.viewPager2.currentItem = 0 } | |||
tabSpell.click { binding.viewPager2.currentItem = 1 } | |||
tabVoice.click { binding.viewPager2.currentItem = 2 } | |||
} | |||
//监听进度,设置进度 | |||
vm.currentCourseProgress.observe(this) { | |||
binding.includeCourseProgress.apply { | |||
//进度格式化 | |||
progressbar.progress = it.toInt() | |||
tvProgress.text = if (binding.includeCourseTypeTab.root.visibility == View.VISIBLE) { | |||
val format = when (binding.viewPager2.currentItem) { | |||
0 -> "认读进度:%s" | |||
1 -> "拼写进度:%s" | |||
2 -> "辨音进度:%s" | |||
else -> "进度:%s" | |||
} | |||
String.format(format, CourseManager.useToShowProgress(it)) | |||
} else { | |||
String.format("进度:%s", CourseManager.useToShowProgress(it)) | |||
} | |||
} | |||
} | |||
//更多按钮点击 | |||
binding.includeCourseProgress.ivMore.click { | |||
showMoreDialog() | |||
} | |||
} | |||
override fun loadData() { | |||
} | |||
/** 点击显示更多的弹窗 */ | |||
private fun showMoreDialog() { | |||
if (moreDialog == null) { | |||
moreDialog = BottomSheetDialog(this, R.style.dialog_style).apply { | |||
val moreBinding = DataBindingUtil.inflate<DialogBottomCourseMoreBinding>( | |||
layoutInflater, R.layout.dialog_bottom_course_more, null, false | |||
) | |||
setContentView(moreBinding.root) | |||
//体验账号、拼些、口语课程、作文课程不显示自动播放 | |||
when (vm.coursePack.childrenCourses[binding.viewPager2.currentItem].courseType) { | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL, AppConstants.COURSE_TYPE_ENGLISH_SPOKEN, AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> moreBinding.tvAutoPlay.visibility = | |||
View.GONE | |||
else -> moreBinding.tvAutoPlay.visibility = View.VISIBLE | |||
} | |||
moreBinding.ivCancel.click { | |||
dismiss() | |||
} | |||
moreBinding.tvAutoPlay.click { | |||
dismiss() | |||
showAutoPlaySelectDialog() | |||
} | |||
moreBinding.tvClearLearnRecord.click { | |||
dismiss() | |||
// TODO: 2022/3/29 弹窗显示清除学习记录 | |||
} | |||
} | |||
} | |||
moreDialog?.show() | |||
} | |||
/** 自动播放次数选择: 仅单词会有该选项 */ | |||
private fun showAutoPlaySelectDialog() { | |||
if (autoPlaySeletDialog == null) { | |||
autoPlaySeletDialog = BottomSheetDialog(this, R.style.dialog_style).apply { | |||
val autoPlayBinding = DataBindingUtil.inflate<DialogBottomAutoPlaySelectBinding>( | |||
layoutInflater, R.layout.dialog_bottom_auto_play_select, null, false | |||
) | |||
setContentView(autoPlayBinding.root) | |||
autoPlayBinding.ivCancel.click { v -> dismiss() } | |||
autoPlayBinding.rvRepeat.run { | |||
adapter = AdapterAutoPlaySelectRepeat().apply { | |||
onItemClick = { _, position, _ -> | |||
dismiss() | |||
startAutoPlay(position + 1) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
autoPlaySeletDialog?.show() | |||
} | |||
/** | |||
* 开始自动播放 | |||
* @param time Int | |||
*/ | |||
private fun startAutoPlay(time: Int) { | |||
} | |||
/** ViewModel Factory工厂 */ | |||
inner class ViewModelFactory(private val subjectId: Int, private val coursePackInPosition: Int) : | |||
ViewModelProvider.Factory { | |||
override fun <T : ViewModel?> create(modelClass: Class<T>): T { | |||
return CoursePackMainActivityViewModel(subjectId, coursePackInPosition) as T | |||
} | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
package com.xkl.cdl.module.m_center_learn | |||
import androidx.lifecycle.MutableLiveData | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.xkl.cdl.data.manager.CourseManager | |||
/** | |||
* author suliang | |||
* create 2022/3/24 17:42 | |||
* Describe: 课程主页 | |||
*/ | |||
class CoursePackMainActivityViewModel(subjectId: Int , coursePackInPosition : Int) : BaseViewModel() { | |||
//操作的课程包 | |||
val coursePack = CourseManager.subjectWithCoursePackMap[subjectId]!![coursePackInPosition] | |||
//设置显示当前课程的进度值和显示内容 | |||
val currentCourseProgress = MutableLiveData<Double>() | |||
} |
@@ -4,7 +4,7 @@ import androidx.fragment.app.Fragment | |||
import androidx.lifecycle.MutableLiveData | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.Constants | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.module.main.MainActivityViewModel | |||
/** | |||
@@ -30,8 +30,8 @@ class LearnCenterFragmentViewModel : BaseViewModel() { | |||
/** 实例化项目课程包Fragment和显示Title */ | |||
fun initLearnCenterFragment(){ | |||
if (mProjectFragments.isEmpty()){ | |||
mProjectFragments.add(CoursePackFragment.newInstance(Constants.SUBJECT_ENGLISH)) | |||
mProjectFragments.add(CoursePackFragment.newInstance(Constants.SUBJECT_CHINESE)) | |||
mProjectFragments.add(CoursePackFragment.newInstance(AppConstants.SUBJECT_ENGLISH)) | |||
mProjectFragments.add(CoursePackFragment.newInstance(AppConstants.SUBJECT_CHINESE)) | |||
} | |||
if (mProjectTitles.isEmpty()){ | |||
mProjectTitles.add(R.string.project_english) |
@@ -0,0 +1,86 @@ | |||
package com.xkl.cdl.module.m_center_learn.coursechildren | |||
import android.view.View | |||
import androidx.lifecycle.ViewModelProvider | |||
import androidx.recyclerview.widget.LinearLayoutManager | |||
import com.suliang.common.base.fragment.BaseFragmentVM | |||
import com.xkl.cdl.adapter.AdapterLesson | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import com.xkl.cdl.databinding.FragmentCourseLessonBinding | |||
/** | |||
* 课程章节目录 | |||
*/ | |||
class CourseLessonFragment : BaseFragmentVM<FragmentCourseLessonBinding, CourseMainFragmentViewModel>() { | |||
companion object { | |||
@JvmStatic | |||
fun newInstance() = CourseLessonFragment() | |||
} | |||
override fun initViewModel(): CourseMainFragmentViewModel { | |||
return ViewModelProvider(requireParentFragment())[CourseMainFragmentViewModel::class.java] | |||
} | |||
override fun initFragment() { | |||
//口语显示顶部的自动播放与跟读模式 | |||
if (vm.course.courseType == AppConstants.COURSE_TYPE_ENGLISH_SPOKEN){ | |||
binding.spokenTopLayout.visibility = View.VISIBLE | |||
} | |||
binding.recyclerView.apply { | |||
layoutManager = LinearLayoutManager(requireContext(),LinearLayoutManager.VERTICAL,false) | |||
adapter = AdapterLesson(vm).apply { | |||
onItemClick = onLessonClick | |||
} | |||
} | |||
//设置数据 | |||
(binding.recyclerView.adapter as AdapterLesson).setData(vm.allLesson.toMutableList()) | |||
} | |||
override fun loadData() { | |||
} | |||
/** 课时点击实现 */ | |||
private val onLessonClick : (v:View,position: Int, leeson: Lesson) -> Unit = { view, position, entity -> | |||
// TODO: 2022/3/31 根据情况具体跳转实现 学前、学习、学后 | |||
when(entity.lessonType){ | |||
AppConstants.LESSON_TYPE_WORD -> { | |||
if (entity.beforeTestScore == AppConstants.NOT_DOING){ | |||
}else if (!entity.learnIsOver){ | |||
}else if (entity.afterTestScore != AppConstants.NOT_DOING){ | |||
}else{ | |||
} | |||
} | |||
AppConstants.LESSON_TYPE_SENTENCE -> { | |||
} | |||
AppConstants.LESSON_TYPE_DIALOGUE -> { | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_VIDEO -> { | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_KNOWLEDGE -> { | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_EXAM -> { | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_READING -> { | |||
} | |||
AppConstants.LESSON_TYPE_COMPOSITION_TASK -> { | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
package com.xkl.cdl.module.m_center_learn.coursechildren | |||
import android.os.Bundle | |||
import androidx.lifecycle.ViewModel | |||
import androidx.lifecycle.ViewModelProvider | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.base.fragment.BaseFragmentVM | |||
import com.suliang.common.extension.replaceFragment | |||
import com.suliang.common.util.LogUtil | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.manager.db.DbControlBase | |||
import com.xkl.cdl.databinding.FragmentCourseMainBinding | |||
import com.xkl.cdl.module.m_center_learn.CoursePackMainActivityViewModel | |||
/** | |||
* 学习中心@[LearnCenterFragment] @[CoursePackFragment]下课程包主页@[CoursePackMainActivity]下的 | |||
* 主课程Fragment[CourseMainFragment] | |||
* 用于加载该课程的多种状态: 复习、章节目录、总测试 | |||
*/ | |||
class CourseMainFragment : BaseFragmentVM<FragmentCourseMainBinding, CourseMainFragmentViewModel>() { | |||
companion object { | |||
@JvmStatic | |||
fun newInstance(courseIndex:Int) = CourseMainFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(AppConfig.INTENT_1,courseIndex) | |||
} | |||
} | |||
} | |||
override fun initViewModel(): CourseMainFragmentViewModel { | |||
return ViewModelProvider(this,ViewModelFactory(requireArguments().getInt(AppConfig.INTENT_1)))[CourseMainFragmentViewModel::class.java].apply { | |||
coursePackMainActivityVM = ViewModelProvider(requireActivity())[CoursePackMainActivityViewModel::class.java] | |||
LogUtil.e("CourseMainFragment coursePackMainActivityVM hashCode -> ${coursePackMainActivityVM.hashCode()}") | |||
} | |||
} | |||
override fun initFragment() { | |||
//设置课程 和 需要操作的类型 | |||
vm.course = vm.coursePackMainActivityVM.coursePack.childrenCourses[vm.courseIndex].apply { | |||
vm.dbControlBase = DbControlBase(subjectId,coursePackId,courseId,courseType) | |||
} | |||
} | |||
override fun loadData() { | |||
LogUtil.e("CourseMainFragment 加载数据 --》 ${vm.courseIndex}") | |||
vm.loadMain().observe(this){ | |||
changeChildrenFragment() | |||
} | |||
} | |||
/** | |||
* 改变加载的子Fragment | |||
*/ | |||
private fun changeChildrenFragment(){ | |||
// //加载复习 | |||
// replaceFragment(R.id.layout_root, CourseReviewFragment.newInstance()) | |||
// //学前总测 | |||
// replaceFragment(R.id.layout_root, CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_BEFORE_TOTAL)) | |||
//学后总测 | |||
// replaceFragment(R.id.layout_root, CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_AFTER_TOTAL)) | |||
//学习目录 | |||
replaceFragment(R.id.layout_root, CourseLessonFragment.newInstance()) | |||
} | |||
inner class ViewModelFactory(private val courseIndex: Int) : ViewModelProvider.Factory{ | |||
override fun <T : ViewModel?> create(modelClass: Class<T>): T { | |||
return CourseMainFragmentViewModel(courseIndex) as T | |||
} | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
package com.xkl.cdl.module.m_center_learn.coursechildren | |||
import android.provider.ContactsContract | |||
import androidx.lifecycle.MutableLiveData | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.suliang.common.extension.diskIo2DiskIo | |||
import com.xkl.cdl.data.bean.course.Course | |||
import com.xkl.cdl.data.bean.course.CourseDetail | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import com.xkl.cdl.data.manager.db.DbControlBase | |||
import com.xkl.cdl.data.repository.DataRepository | |||
import com.xkl.cdl.module.m_center_learn.CoursePackMainActivityViewModel | |||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers | |||
import io.reactivex.rxjava3.core.Observable | |||
import io.reactivex.rxjava3.core.Observer | |||
import io.reactivex.rxjava3.disposables.Disposable | |||
import java.util.* | |||
import kotlin.collections.ArrayList | |||
import kotlin.collections.HashMap | |||
/** | |||
* author suliang | |||
* create 2022/3/28 15:26 | |||
* Describe: | |||
* @property courseIndex 该课程在课程包的课程集合中的位置 | |||
*/ | |||
class CourseMainFragmentViewModel(val courseIndex: Int) : BaseViewModel() { | |||
//课程包主页的ViewModel | |||
lateinit var coursePackMainActivityVM: CoursePackMainActivityViewModel | |||
lateinit var dbControlBase: DbControlBase | |||
//当前操作课程 | |||
lateinit var course: Course | |||
/** 课程的收藏本: 目前仅作用在口语课程会使用到该数据 */ | |||
lateinit var collectList: HashMap<String, Long> | |||
/** 复习的数据 */ | |||
lateinit var reviewDataList: MutableList<String> | |||
/** 课程所有课时 */ | |||
lateinit var allLesson: List<Lesson> | |||
//课程的详细信息 | |||
lateinit var courseDetail: CourseDetail | |||
//获取课程的统计信息 | |||
//课程收藏本: 主要用于口语对话学习的数据 | |||
//获取课程的复习数据 | |||
//获取课程的章节数据 | |||
fun loadMain() : MutableLiveData<Boolean> { | |||
showHideLoading(true) | |||
val mutableLiveData = MutableLiveData<Boolean>() | |||
Observable.concat( | |||
DataRepository.getCourseStatistics().flatMap { | |||
courseDetail = it | |||
return@flatMap DataRepository.getCourseAllLesson(dbControlBase, it) | |||
}, DataRepository.getReviewData() | |||
, DataRepository.getCourseCollect()) | |||
.compose(diskIo2DiskIo()) | |||
.subscribe(object :Observer<Any>{ | |||
override fun onSubscribe(d: Disposable?) { | |||
} | |||
override fun onNext(t: Any?) { | |||
t?.let { it -> | |||
if (it is List<*>){ | |||
allLesson = it as List<Lesson> | |||
} | |||
} | |||
} | |||
override fun onError(e: Throwable?) { | |||
e?.printStackTrace() | |||
} | |||
override fun onComplete() { | |||
showHideLoading(false) | |||
mutableLiveData.postValue(true) | |||
} | |||
}) | |||
return mutableLiveData | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
package com.xkl.cdl.module.m_center_learn.coursechildren | |||
import android.os.Bundle | |||
import androidx.lifecycle.ViewModelProvider | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.base.fragment.BaseFragmentVM | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.databinding.FragmentCourseLessonBinding | |||
import com.xkl.cdl.databinding.FragmentCourseReviewBinding | |||
/** | |||
* 课程章节目录 | |||
* @property param1 String? | |||
* @property param2 String? | |||
*/ | |||
class CourseReviewFragment : BaseFragmentVM<FragmentCourseReviewBinding, CourseMainFragmentViewModel>() { | |||
companion object { | |||
@JvmStatic | |||
fun newInstance() = CourseReviewFragment() | |||
} | |||
override fun initFragment() { | |||
//根据课程类型进行显示 | |||
binding.tvTips.text = when(vm.course.courseType){ | |||
AppConstants.COURSE_TYPE_ENGLISH_DISCERN -> "你将进行 [认读] 课程智能复习" | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> "你将进行 [辨音] 课程智能复习" | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL -> "你将进行 [拼写] 课程智能复习" | |||
else -> "你将进行课程智能复习" | |||
} | |||
binding.tvReviewCount.text = String.format("本次智能复习数%d",vm.course.courseReviewNumber) | |||
//开始测试事件 | |||
binding.tvStartReview.click { | |||
showToast("开始复习") | |||
} | |||
} | |||
override fun loadData() { | |||
} | |||
override fun initViewModel(): CourseMainFragmentViewModel { | |||
return ViewModelProvider(requireParentFragment())[CourseMainFragmentViewModel::class.java] | |||
} | |||
} |
@@ -0,0 +1,133 @@ | |||
package com.xkl.cdl.module.m_center_learn.coursechildren | |||
import android.os.Bundle | |||
import android.view.View | |||
import androidx.lifecycle.ViewModelProvider | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.base.fragment.BaseFragmentVM | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.extension.setHtml | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.databinding.FragmentCourseTotalTestBinding | |||
/** | |||
* 课程总测试: 学前总,学后总 | |||
* @property param1 String? | |||
* @property param2 String? | |||
*/ | |||
class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, CourseMainFragmentViewModel>() { | |||
companion object { | |||
@JvmStatic | |||
fun newInstance(totalTestType: Int) = CourseTotalTestFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(AppConfig.INTENT_1, totalTestType) | |||
} | |||
} | |||
} | |||
override fun initViewModel(): CourseMainFragmentViewModel { | |||
return ViewModelProvider(requireParentFragment())[CourseMainFragmentViewModel::class.java] | |||
} | |||
//传递过来的总测类型: 学前,学后 | |||
private var totalTestType = 0 | |||
override fun initFragment() { | |||
totalTestType = requireArguments().getInt(AppConfig.INTENT_1) | |||
when (totalTestType) { | |||
AppConstants.TEST_TYPE_BEFORE_TOTAL -> { | |||
//学前总测 | |||
binding.run { | |||
tvTitle.setText(R.string.test_total_before_title) | |||
tvCountTip.text = "共25题,预计3分钟" | |||
//按钮初始 | |||
button2.run { | |||
setText(R.string.start_test) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
} | |||
} | |||
AppConstants.TEST_TYPE_AFTER_TOTAL -> { | |||
//学后总测 | |||
binding.run { | |||
ivIcon.setImageResource(if (java.util.Random().nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | |||
tvTitle.setText(R.string.tips_current_course_learn_over) | |||
tvMainTip.visibility = View.VISIBLE | |||
//根据测试成绩处理 | |||
vm.courseDetail.st_before = 81.0 | |||
vm.courseDetail.st_before.let { | |||
when { | |||
it == -1.0 -> { //未测 | |||
tvMainTip.setText(R.string.test_total_after_tip_1) | |||
tvCountTip.text = "共25题,预计3分钟" | |||
button2.run { | |||
setText(R.string.test_type_after_total) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
} | |||
it < AppConstants.TEST_SCORE_LEVEL_1 -> { //测试未通过 | |||
tvMainTip.setHtml("你还未通过学后总测试,上次得分: <font color=\'#F26255\'>$it</font>") | |||
button1.run { | |||
visibility = View.VISIBLE | |||
setText(R.string.continue_learn) | |||
click { view -> | |||
continueLearn(view) | |||
} | |||
} | |||
button2.run { | |||
setText(R.string.start_test) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
} | |||
it >= AppConstants.TEST_SCORE_LEVEL_1 -> { //测试通过 | |||
tvMainTip.setHtml("你已通过学后总测试,上次得分: <font color=\'#5082E6\'>$it</font>") | |||
tvTips.visibility = View.VISIBLE | |||
tvCountTip.visibility = View.GONE | |||
button1.run { | |||
visibility = View.VISIBLE | |||
setText(R.string.test_again) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
button2.run { | |||
setText(R.string.continue_learn) | |||
click { view -> | |||
continueLearn(view) | |||
} | |||
} | |||
tvClearLearnRecord.visibility = View.VISIBLE | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
override fun loadData() { | |||
} | |||
/**继续学习*/ | |||
private fun continueLearn(view: View) { | |||
showToast("继续学习") | |||
} | |||
/** 开始测试 */ | |||
private fun startTest(view: View) { | |||
showToast("开始测试") | |||
} | |||
} |
@@ -3,17 +3,23 @@ package com.xkl.cdl.module.splash | |||
import android.annotation.SuppressLint | |||
import android.os.Bundle | |||
import com.suliang.common.base.activity.BaseActivity | |||
import com.suliang.common.util.LogUtil | |||
import com.suliang.common.util.file.FileUtil | |||
import com.suliang.common.util.thread.AppExecutors | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.data.manager.FilePathManager | |||
import com.xkl.cdl.data.manager.db.DbCoursePackManager | |||
import com.xkl.cdl.databinding.ActivitySplashBinding | |||
import com.xkl.cdl.dialog.LearnDialog | |||
import com.xkl.cdl.module.main.MainActivity | |||
import mobile_cache.Mobile_cache | |||
import java.io.File | |||
import java.util.concurrent.TimeUnit | |||
@SuppressLint("CustomSplashScreen") | |||
class SplashActivity : BaseActivity<ActivitySplashBinding>() { | |||
class SplashActivity : BaseActivity<ActivitySplashBinding>(), LearnDialog.DialogFragmentListener { | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
if (!isTaskRoot) { | |||
@@ -28,28 +34,58 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() { | |||
} | |||
override fun loadData() { | |||
// try { | |||
// val file: String = File(FileUtil.getSaveDirFile("db"), "mydb").absolutePath | |||
// val mobile = Mobile_cache.new_(file) | |||
// mobile.delete() | |||
// println(" -------------> " + mobile.get("abc")) | |||
// | |||
// } catch (e: Exception) { | |||
// e.printStackTrace() | |||
// } | |||
learnDialog = LearnDialog().apply { | |||
show(supportFragmentManager,javaClass.name) | |||
} | |||
LogUtil.e("Dialog -- > ${learnDialog.hashCode()}") | |||
if (true) return | |||
showHideLoading(true) | |||
AppExecutors.io.execute { | |||
//数据文件是否存在 | |||
val coursePackFile = File(FileUtil.getSaveDirPath("db"), "course-pack.db") | |||
if (!coursePackFile.exists()) { | |||
val copyAssetResult = FileUtil.copyAsset("course-pack.db", coursePackFile) | |||
} | |||
//读取课程数据 | |||
// TODO: 2022/3/22 读取当前app绑定的课程数据, | |||
DbCoursePackManager().queryBindingCoursePack("262,261,264") | |||
DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615") | |||
//复制课程的数据库到对应位置 | |||
CourseManager.checkCourseDb() | |||
//定时跳跃到住主界面 | |||
AppExecutors.scheduledExecutor.schedule({ | |||
AppExecutors.mainThread.execute { | |||
showHideLoading(false) | |||
startActivity(MainActivity::class.java) | |||
finish() | |||
} | |||
}, 1, TimeUnit.SECONDS) | |||
AppExecutors.mainThread.execute { | |||
showHideLoading(false) | |||
startActivity(MainActivity::class.java) | |||
finish() | |||
} | |||
}, 1, TimeUnit.SECONDS) | |||
} | |||
} | |||
lateinit var learnDialog :LearnDialog | |||
lateinit var learnDialog1: LearnDialog | |||
override fun rightClick() { | |||
if (!this::learnDialog1.isInitialized) { | |||
learnDialog1 = LearnDialog() | |||
} | |||
LogUtil.e("Dialog 1 -- > ${learnDialog1.hashCode()}") | |||
learnDialog1.show(supportFragmentManager,javaClass.name) | |||
} | |||
override fun leftClick() { | |||
learnDialog1.dismiss() | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<!--按钮:按下字体--> | |||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<item android:color="@color/theme_color" android:state_pressed="true"/> | |||
<item android:color="@color/main_text_color" android:state_pressed="false"/> | |||
</selector> |
@@ -0,0 +1,5 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<corners android:radius="12dp"/> | |||
<solid android:color="@color/white"/> | |||
</shape> |
@@ -8,27 +8,30 @@ | |||
<variable | |||
name="coursePack" | |||
type="com.xkl.cdl.data.course.CoursePack" /> | |||
type="com.xkl.cdl.data.bean.course.CoursePack" /> | |||
<import type="android.view.View"/> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_center_learn.CourseMainActivity"> | |||
tools:context=".module.m_center_learn.CoursePackMainActivity" | |||
android:background="@color/white"> | |||
<!--模糊图--> | |||
<ImageView | |||
android:id="@+id/img_course_pack_cover_blur" | |||
android:layout_width="0dp" | |||
android:layout_height="0dp" | |||
android:scaleType="matrix" | |||
bind:imgByteArray="@{coursePack.cover}" | |||
bind:blur= "@{false}" | |||
android:scaleType="fitXY" | |||
bind:imgBytes="@{coursePack.cover}" | |||
bind:blur= "@{true}" | |||
app:layout_constraintBottom_toBottomOf="@+id/view_placeholder_1" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
tools:background="@color/gray_2" /> | |||
tools:background="@color/gray_2" | |||
android:alpha="0.5"/> | |||
<!--状态栏--> | |||
<View | |||
@@ -41,9 +44,11 @@ | |||
<include | |||
android:id="@+id/include_title_bar" | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/title_bar_height" | |||
layout="@layout/include_title_bar" | |||
app:layout_constraintTop_toBottomOf="@+id/status_bar_view" | |||
bind:title="@string/course_detail" /> | |||
bind:titleValue="@{@string/course_detail}" /> | |||
<View | |||
android:id="@+id/view_placeholder_1" |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnExamSpellActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnCReadingActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnCTaskActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnCVideoActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnExamWordActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnSpellActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.learn.LearnWordActivity"> | |||
</androidx.constraintlayout.widget.ConstraintLayout> |
@@ -0,0 +1,54 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:background="@drawable/shape_rounder_toplr_24_white"> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="wrap_content" | |||
android:layout_height="46dp" | |||
android:text="@string/please_select_the_operation_you_want_to_do" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:gravity="center" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<ImageView | |||
android:id="@+id/iv_cancel" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toTopOf="@id/tv_title" | |||
app:layout_constraintBottom_toBottomOf="@+id/tv_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
android:src="@drawable/ic_delete" | |||
android:layout_marginEnd="24dp" /> | |||
<View | |||
android:id="@+id/v_line" | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/line_height" | |||
android:background="@color/gray_1" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_title" /> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/rv_repeat" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toBottomOf="@id/v_line" | |||
android:overScrollMode="never" | |||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | |||
android:orientation="vertical"/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,64 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:background="@drawable/shape_rounder_toplr_24_white"> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="wrap_content" | |||
android:layout_height="46dp" | |||
android:gravity="center" | |||
android:text="@string/please_select_the_operation_you_want_to_do" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<ImageView | |||
android:id="@+id/iv_cancel" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginEnd="24dp" | |||
android:src="@drawable/ic_delete" | |||
app:layout_constraintBottom_toBottomOf="@+id/tv_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toTopOf="@id/tv_title" /> | |||
<View | |||
android:id="@+id/v_line" | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/line_height" | |||
android:background="@color/gray_1" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_title" /> | |||
<TextView | |||
android:id="@+id/tv_auto_play" | |||
android:layout_width="match_parent" | |||
android:layout_height="48dp" | |||
android:gravity="center" | |||
android:text="@string/auto_play_the_words_learned" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
app:layout_constraintTop_toBottomOf="@+id/v_line" /> | |||
<TextView | |||
android:id="@+id/tv_clear_learn_record" | |||
android:layout_width="match_parent" | |||
android:layout_height="48dp" | |||
android:gravity="center" | |||
android:text="@string/clear_learn_record" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_auto_play" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,25 @@ | |||
<?xml version="1.0" encoding="utf-8"?><!--重复播放次数加载框--> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content"> | |||
<TextView | |||
android:id="@+id/tv_option" | |||
android:layout_width="match_parent" | |||
android:layout_height="48dp" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/normalSize" | |||
tools:text="重复次数" | |||
android:gravity="center" | |||
app:layout_constraintTop_toTopOf="parent" | |||
/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,204 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="300dp" | |||
android:layout_height="wrap_content"> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="0dp" | |||
android:layout_marginTop="76dp" | |||
android:background="@drawable/shape_rounder_12_white" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.0" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent"> | |||
<ImageView | |||
android:id="@+id/iv_close" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="8dp" | |||
android:layout_marginEnd="8dp" | |||
android:src="@drawable/ic_delete" | |||
android:visibility="gone" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
tools:visibility="visible" /> | |||
<TextView | |||
android:id="@+id/tv_score" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="80dp" | |||
android:textColor="@color/theme_color" | |||
android:textSize="28dp" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
tools:text="%d分" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<TextView | |||
android:id="@+id/tv_tip" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="@string/current_test_score" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintEnd_toEndOf="@+id/tv_score" | |||
app:layout_constraintStart_toStartOf="@+id/tv_score" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_score" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="12dp" | |||
app:layout_goneMarginTop="80dp" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/smallSize" | |||
android:textStyle="bold" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_tip" | |||
tools:text="课时学前测试" /> | |||
<TextView | |||
android:id="@+id/tv_lesson_name" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="8dp" | |||
android:gravity="center" | |||
android:paddingStart="@dimen/global_spacing" | |||
android:paddingEnd="@dimen/global_spacing" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_title" | |||
tools:text="[%s%s]"/> | |||
<TextView | |||
android:id="@+id/tv_count_time" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_lesson_name" | |||
tools:text="@string/test_count_time_format"/> | |||
<TextView | |||
android:id="@+id/tv_tip_1" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_title" | |||
tools:text="@string/test_before_test_over_tip" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<include | |||
android:id="@+id/inc_statistics_number" | |||
layout="@layout/inc_over_number" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_tip_1" | |||
android:visibility="gone"/> | |||
<androidx.constraintlayout.widget.Barrier | |||
android:id="@+id/barrier" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:barrierDirection="bottom" | |||
app:barrierMargin="@dimen/miniSize" | |||
app:constraint_referenced_ids="tv_count_time,inc_statistics_number" /> | |||
<View | |||
android:id="@+id/bottom_top_line" | |||
android:layout_width="wrap_content" | |||
android:layout_height="@dimen/line_height" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:background="@color/gray_3" | |||
app:layout_constraintTop_toBottomOf="@+id/barrier" /> | |||
<!--一直显示的按钮: 即常驻按钮 --> | |||
<TextView | |||
android:id="@+id/tv_right" | |||
android:layout_width="0dp" | |||
android:layout_height="40dp" | |||
android:gravity="center" | |||
android:text="@string/start_test" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/bottom_top_line" | |||
app:layout_constraintStart_toEndOf="@id/vSplit" | |||
/> | |||
<View | |||
android:id="@+id/vSplit" | |||
android:layout_width="@dimen/line_height" | |||
android:layout_height="0dp" | |||
app:layout_constraintEnd_toStartOf="@+id/tv_right" | |||
app:layout_constraintStart_toEndOf="@+id/tv_left" | |||
android:background="@color/gray_3" | |||
app:layout_constraintTop_toTopOf="@+id/tv_right" | |||
app:layout_constraintBottom_toBottomOf="@+id/tv_right" /> | |||
<!--左边按钮--> | |||
<TextView | |||
android:id="@+id/tv_left" | |||
android:layout_width="0dp" | |||
android:layout_height="40dp" | |||
android:gravity="center" | |||
android:text="@string/start_test" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toStartOf="@+id/vSplit" | |||
app:layout_constraintTop_toTopOf="@+id/vSplit" | |||
app:layout_constraintBottom_toBottomOf="@+id/vSplit" | |||
android:visibility="gone" | |||
/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
<ImageView | |||
android:id="@+id/img_iv" | |||
android:layout_width="160dp" | |||
android:layout_height="160dp" | |||
android:layout_centerHorizontal="true" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
android:src="@mipmap/girl_2" | |||
/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,65 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_center_learn.coursechildren.CourseLessonFragment"> | |||
<!-- LinearLayout 仅在口语课程时显示--> | |||
<LinearLayout | |||
android:id="@+id/spoken_top_layout" | |||
android:layout_width="0dp" | |||
android:layout_height="wrap_content" | |||
android:background="@color/gray_3" | |||
android:orientation="horizontal" | |||
android:visibility="gone" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
tools:visibility="visible"> | |||
<TextView | |||
android:id="@+id/tv_auto_dialogue" | |||
android:layout_width="0dp" | |||
android:layout_height="match_parent" | |||
android:layout_weight="1" | |||
android:gravity="center" | |||
android:paddingTop="8dp" | |||
android:paddingBottom="8dp" | |||
android:text="@string/english_spoken_pattern_auto_play" | |||
android:textColor="@color/selectpress_maintextcolor_to_themcolor" | |||
android:textSize="@dimen/normalSize" /> | |||
<TextView | |||
android:id="@+id/tv_follow_dialogue" | |||
android:layout_width="0dp" | |||
android:layout_height="match_parent" | |||
android:layout_weight="1" | |||
android:gravity="center" | |||
android:paddingTop="8dp" | |||
android:paddingBottom="8dp" | |||
android:text="@string/english_spoken_pattern_follow" | |||
android:textColor="@color/selectpress_maintextcolor_to_themcolor" | |||
android:textSize="@dimen/normalSize" /> | |||
</LinearLayout> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/recyclerView" | |||
android:layout_width="0dp" | |||
android:layout_height="0dp" | |||
android:overScrollMode="never" | |||
android:scrollbars="none" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/spoken_top_layout" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:id="@+id/layout_root" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_center_learn.coursechildren.CourseMainFragment"> | |||
</FrameLayout> |
@@ -0,0 +1,66 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_center_learn.coursechildren.CourseReviewFragment"> | |||
<ImageView | |||
android:id="@+id/iv_icon" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:src="@mipmap/boy_3" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_tips" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintHorizontal_bias="0.497" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.2" | |||
app:layout_constraintVertical_chainStyle="packed"/> | |||
<TextView | |||
android:id="@+id/tv_tips" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="12dp" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
android:textStyle="bold" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_start_review" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/iv_icon" | |||
tools:text="你将进行智能复习/你将进行[%s]课程智能复习" /> | |||
<TextView | |||
android:id="@+id/tv_review_count" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_tips" | |||
tools:text="本次智能复习数%d" /> | |||
<Button | |||
android:id="@+id/tv_start_review" | |||
style="@style/common_button_style" | |||
android:text="@string/start_review" | |||
app:cornerRadius="8dp" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_tips" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,136 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:background="@color/white" | |||
tools:context=".module.m_center_learn.coursechildren.CourseTotalTestFragment"> | |||
<ImageView | |||
android:id="@+id/iv_icon" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:src="@mipmap/boy_1" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintVertical_bias="0.2" | |||
app:layout_constraintVertical_chainStyle="packed" /> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="12dp" | |||
android:text="@string/test_total_after_tip_1" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
android:textStyle="bold" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_main_tip" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/iv_icon" | |||
android:visibility="visible" /> | |||
<TextView | |||
android:id="@+id/tv_main_tip" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="12dp" | |||
android:text="@string/test_total_before_title" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_tips" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_title" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<TextView | |||
android:id="@+id/tv_tips" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:text="@string/test_total_after_tip_3" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_count_tip" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_main_tip" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<TextView | |||
android:id="@+id/tv_count_tip" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBottom_toTopOf="@+id/button_2" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_tips" | |||
tools:text="@string/test_count_time_format" /> | |||
<Button | |||
android:id="@+id/button_1" | |||
style="@style/Widget.MaterialComponents.Button.UnelevatedButton" | |||
android:layout_width="0dp" | |||
android:layout_height="@dimen/common_button_height" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:insetTop="0dp" | |||
android:insetBottom="0dp" | |||
app:cornerRadius="8dp" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toStartOf="@+id/button_2" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="@+id/button_2" | |||
app:strokeColor="@color/theme_color" | |||
app:strokeWidth="@dimen/line_height" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<Button | |||
android:id="@+id/button_2" | |||
style="@style/common_button_style" | |||
android:layout_width="0dp" | |||
android:layout_height="@dimen/common_button_height" | |||
android:layout_marginStart="12dp" | |||
android:layout_marginTop="40dp" | |||
android:layout_marginEnd="@dimen/global_spacing" | |||
app:cornerRadius="8dp" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toEndOf="@+id/button_1" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_count_tip" | |||
app:layout_goneMarginStart="@dimen/global_spacing" /> | |||
<TextView | |||
android:id="@+id/tv_clear_learn_record" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="24dp" | |||
android:text="@string/clear_learn_record" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:visibility="gone" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/button_2" | |||
tools:visibility="visible"/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,76 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
tools:showIn="@layout/dialog_lesson_learn"> | |||
<androidx.constraintlayout.widget.Guideline | |||
android:id="@+id/guideline_1" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:orientation="vertical" | |||
app:layout_constraintGuide_percent="0.5" /> | |||
<TextView | |||
android:id="@+id/tv_correct_tip" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="8dp" | |||
android:layout_marginRight="28dp" | |||
android:text="@string/correct" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintEnd_toEndOf="@+id/guideline_1" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<TextView | |||
android:id="@+id/tv_error_tip" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginStart="28dp" | |||
android:layout_marginTop="8dp" | |||
android:text="@string/error" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintStart_toEndOf="@+id/guideline_1" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<TextView | |||
android:id="@+id/tv_correct_number" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:textColor="@color/green_1" | |||
android:textSize="@dimen/bigSize" | |||
android:textStyle="bold" | |||
app:layout_constraintEnd_toEndOf="@+id/tv_correct_tip" | |||
app:layout_constraintStart_toStartOf="@+id/tv_correct_tip" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_correct_tip" | |||
tools:text="20" /> | |||
<TextView | |||
android:id="@+id/tv_error_number" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="4dp" | |||
android:textColor="@color/red_1" | |||
android:textSize="@dimen/bigSize" | |||
android:textStyle="bold" | |||
app:layout_constraintEnd_toEndOf="@+id/tv_error_tip" | |||
app:layout_constraintStart_toStartOf="@+id/tv_error_tip" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_error_tip" | |||
tools:text="0" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -1,52 +1,59 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="28dp" | |||
android:background="@color/gray_3" | |||
android:paddingStart="@dimen/global_spacing" | |||
android:paddingEnd="@dimen/global_spacing" | |||
tools:showIn="@layout/activity_course_main"> | |||
<TextView | |||
android:id="@+id/tv_progress" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
tools:text="%s学习进度: %d%" /> | |||
<ProgressBar | |||
android:id="@+id/progressbar" | |||
style="@android:style/Widget.ProgressBar.Horizontal" | |||
android:layout_width="0dp" | |||
android:layout_height="4dp" | |||
android:layout_marginStart="26dp" | |||
android:layout_marginEnd="26dp" | |||
android:layout_weight="1" | |||
android:max="1000" | |||
android:progressDrawable="@drawable/progress_center" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toStartOf="@+id/iv_more" | |||
app:layout_constraintStart_toEndOf="@+id/tv_progress" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<com.google.android.material.imageview.ShapeableImageView | |||
android:id="@+id/iv_more" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:src="@drawable/ic_more" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toEndOf="@+id/progressbar" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="28dp" | |||
android:background="@color/gray_3" | |||
android:paddingStart="@dimen/global_spacing" | |||
android:paddingEnd="@dimen/global_spacing" | |||
tools:showIn="@layout/activity_course_main"> | |||
<TextView | |||
android:id="@+id/tv_progress" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/miniSize" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
tools:text="%s学习进度: %d%" /> | |||
<ProgressBar | |||
android:id="@+id/progressbar" | |||
style="@android:style/Widget.ProgressBar.Horizontal" | |||
android:layout_width="0dp" | |||
android:layout_height="4dp" | |||
android:layout_marginStart="26dp" | |||
android:layout_marginEnd="26dp" | |||
android:layout_weight="1" | |||
android:max="1000" | |||
android:progressDrawable="@drawable/progress_center" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toStartOf="@+id/iv_more" | |||
app:layout_constraintStart_toEndOf="@+id/tv_progress" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<com.google.android.material.imageview.ShapeableImageView | |||
android:id="@+id/iv_more" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:src="@drawable/ic_more" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toEndOf="@+id/progressbar" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> | |||
@@ -21,12 +21,15 @@ | |||
android:drawableStart="@drawable/ic_discern" | |||
android:text="认读" | |||
bind:svgColor="@{@color/theme_color}" | |||
android:textColor="@color/theme_color" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toStartOf="@+id/iv_arrow_1" | |||
android:gravity="center" | |||
android:drawablePadding="4dp" /> | |||
android:drawablePadding="4dp" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<ImageView | |||
android:id="@+id/iv_arrow_1" | |||
@@ -47,13 +50,16 @@ | |||
android:layout_height="match_parent" | |||
android:drawableStart="@drawable/ic_spell" | |||
bind:svgColor="@{@color/theme_color}" | |||
android:textColor="@color/theme_color" | |||
android:text="拼写" | |||
app:layout_constraintStart_toEndOf="@+id/iv_arrow_1" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toStartOf="@+id/iv_arrow_2" | |||
android:gravity="center" | |||
android:drawablePadding="4dp" /> | |||
android:drawablePadding="4dp" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
<ImageView | |||
android:id="@+id/iv_arrow_2" | |||
@@ -74,12 +80,15 @@ | |||
android:drawableStart="@drawable/ic_voice" | |||
android:text="辨音" | |||
bind:svgColor="@{@color/theme_color}" | |||
android:textColor="@color/theme_color" | |||
app:layout_constraintStart_toEndOf="@+id/iv_arrow_2" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
android:gravity="center" | |||
android:drawablePadding="4dp" /> | |||
android:drawablePadding="4dp" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -2,11 +2,14 @@ | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
xmlns:app="http://schemas.android.com/apk/res-auto"> | |||
<!--使用bind添加属性值最好添加一个默认值,否则会将没有设置的属性设置未默认值,如:设置标题和颜色,如果没有设置颜色默认值,则标题将为透明色--> | |||
<data> | |||
<variable | |||
name="title" | |||
name="titleValue" | |||
type="java.lang.String" /> | |||
<variable | |||
name="titleColor" | |||
type="Integer" /> | |||
</data> | |||
<com.suliang.common.widget.TitleBar | |||
@@ -16,7 +19,8 @@ | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:titleTextValue="@{title}" | |||
app:titleTextValue="@{titleValue}" | |||
app:titleTextColor="@{titleColor??@color/main_text_color}" | |||
/> | |||
</layout> |
@@ -0,0 +1,98 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools"> | |||
<data> | |||
<variable | |||
name="data" | |||
type="com.xkl.cdl.data.bean.course.Lesson" /> | |||
</data> | |||
<LinearLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:orientation="vertical"> | |||
<TextView | |||
android:id="@+id/tv_chapter_name" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:layout_marginEnd="@dimen/global_spacing" | |||
android:paddingTop="8dp" | |||
android:text="@{data.chapterName}" | |||
tools:text="unit1" | |||
android:visibility="gone" | |||
tools:visibility="visible" /> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:id="@+id/layout_content" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:paddingTop="5dp" | |||
android:paddingBottom="5dp"> | |||
<TextView | |||
android:id="@+id/tv_serial_number" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
tools:text="01" | |||
android:textSize="28dp" | |||
android:textColor="@color/gray_1" | |||
android:text='@{String.format("%02d",data.lessonPositionInList + 1)}' | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:layout_marginStart="@dimen/global_spacing"/> | |||
<com.google.android.material.imageview.ShapeableImageView | |||
android:id="@+id/iv_arrow_right" | |||
android:layout_width="36dp" | |||
android:layout_height="36dp" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:layout_marginEnd="@dimen/global_spacing" | |||
android:scaleType="centerInside" | |||
android:src="@drawable/ic_arrow_right" | |||
app:shapeAppearance="@style/roundedCornerStyle" | |||
app:strokeColor="@color/gray_2" | |||
app:strokeWidth="@dimen/line_height" | |||
android:padding="@dimen/line_height" | |||
/> | |||
<TextView | |||
android:id="@+id/tv_lesson_name" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
tools:text="单词体验课01" | |||
android:textSize="@dimen/normalSize" | |||
android:textColor="@color/gray_2" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
app:layout_constraintStart_toEndOf="@+id/tv_serial_number" | |||
app:layout_constraintEnd_toStartOf="@+id/iv_arrow_right" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_lesson_number" | |||
app:layout_constraintHorizontal_bias="0" | |||
app:layout_constraintVertical_chainStyle="packed" | |||
android:text="@{data.lessonName}"/> | |||
<TextView | |||
android:id="@+id/tv_lesson_number" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintStart_toStartOf="@+id/tv_lesson_name" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_lesson_name" | |||
app:layout_constraintEnd_toEndOf="@+id/iv_arrow_right" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintHorizontal_bias="0" | |||
tools:text="@string/lesson_number_format" | |||
android:text="@{@string/lesson_number_format(data.totalNumber,data.correctNumber,data.errorNumber)}"/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</LinearLayout> | |||
</layout> |
@@ -7,7 +7,7 @@ | |||
<variable | |||
name="coursePack" | |||
type="com.xkl.cdl.data.course.CoursePack" /> | |||
type="com.xkl.cdl.data.bean.course.CoursePack" /> | |||
</data> | |||
@@ -0,0 +1,3 @@ | |||
<resources> | |||
<dimen name="fab_margin">48dp</dimen> | |||
</resources> |
@@ -0,0 +1,3 @@ | |||
<resources> | |||
<dimen name="fab_margin">200dp</dimen> | |||
</resources> |
@@ -0,0 +1,3 @@ | |||
<resources> | |||
<dimen name="fab_margin">48dp</dimen> | |||
</resources> |
@@ -17,6 +17,7 @@ | |||
<color name="theme_color">#FF5082E6</color> | |||
<color name="main_text_color">#323233</color> | |||
<color name="translation">#00000000</color> | |||
<color name="gray_1">#FFE6E6E6</color> | |||
<color name="gray_2">#8A8A99</color> | |||
<color name="white">#FFFFFFFF</color> | |||
@@ -24,4 +25,16 @@ | |||
<color name="blue_1">#52CC52</color> | |||
<color name="gray_3">#FAFAFA</color> | |||
<color name="green_1">#40A540</color> | |||
<color name="red_1">#FFF26255</color> | |||
<color name="num0">#E50213</color> | |||
<color name="num1">#E50251</color> | |||
<color name="num2">#E4560F</color> | |||
<color name="num3">#7D7530</color> | |||
<color name="num4">#048F3A</color> | |||
<color name="num5">#1680C4</color> | |||
<color name="num6">#014262</color> | |||
<color name="num7">#505050</color> | |||
</resources> |
@@ -10,6 +10,9 @@ | |||
<dimen name="biggerSize">20dp</dimen> | |||
<dimen name="title_bar_height">44dp</dimen> | |||
<dimen name="global_spacing">16dp</dimen> | |||
<dimen name="common_button_height">44dp</dimen> | |||
<dimen name="fab_margin">16dp</dimen> | |||
<dimen name="common_dialog_width">300dp</dimen> | |||
</resources> |
@@ -19,5 +19,42 @@ | |||
<string name="empty_nothing_search">没有搜索到任何内容</string> | |||
<string name="course_detail">课程详情</string> | |||
<string name="introduction">简介</string> | |||
<string name="start_review">开始复习</string> | |||
<string name="please_select_the_operation_you_want_to_do">请选择你要进行的操作</string> | |||
<string name="auto_play_the_words_learned">自动播放已学单词</string> | |||
<string name="clear_learn_record">清空学习记录</string> | |||
<string name="auto_play_repeat_1">重复1次</string> | |||
<string name="auto_play_repeat_2">重复2次</string> | |||
<string name="auto_play_repeat_3">重复3次</string> | |||
<string name="auto_play_repeat_4">重复4次</string> | |||
<string name="auto_play_repeat_5">重复5次</string> | |||
<string name="english_spoken_pattern_auto_play">自动播放</string> | |||
<string name="english_spoken_pattern_follow">跟读模式</string> | |||
<string name="lesson_number_format">条目%d - 正确%d | 错误%d</string> | |||
<string name="test_total_before_title">我当前掌握的知识量量是?去学前总测试一下吧!</string> | |||
<string name="test_count_time_format">共%1$d题,预计%2$d分钟</string> | |||
<string name="tips_current_course_learn_over">本课程学习完毕</string> | |||
<string name="test_total_after_tip_1">我的学习效果是?快去学后总测试吧!</string> | |||
<string name="test_total_after_tip_2">你还未通过学后总测试,上次得分:</string> | |||
<string name="test_total_after_tip_3">系统将为你安排智能复习</string> | |||
<string name="start_test">开始测试</string> | |||
<string name="continue_learn">继续学习</string> | |||
<string name="test_again">再测一次</string> | |||
<string name="test_type_after_total">学后总测试</string> | |||
<string name="title_activity_learn_base">LearnBaseActivity</string> | |||
<!-- Strings used for fragments for navigation --> | |||
<string name="first_fragment_label">First Fragment</string> | |||
<string name="second_fragment_label">Second Fragment</string> | |||
<string name="next">Next</string> | |||
<string name="previous">Previous</string> | |||
<string name="hello_first_fragment">Hello first fragment</string> | |||
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string> | |||
<string name="current_test_score">本次测试成绩</string> | |||
<string name="test_before_test_over_tip">测试成绩不理想?别分心,学考乐让你快速提分!</string> | |||
<string name="correct">正确</string> | |||
<string name="error">错误</string> | |||
<string name="start_learn">开始学习</string> | |||
</resources> |
@@ -8,4 +8,30 @@ | |||
<item name="cornerSize">8dp</item> | |||
</style> | |||
<!--通用按钮style https://blog.csdn.net/weixin_42046829/article/details/110224702 | |||
https://www.jianshu.com/p/bc71b4179cb2--> | |||
<style name="common_button_style" parent="Widget.MaterialComponents.Button.UnelevatedButton"> | |||
<item name="android:layout_width">0dp</item> | |||
<item name="android:layout_height">@dimen/common_button_height</item> | |||
<item name="android:gravity">center</item> | |||
<item name="android:insetTop">0dp</item> | |||
<item name="android:insetBottom">0dp</item> | |||
<item name="android:textSize">@dimen/smallSize</item> | |||
<item name="android:textColor">@color/white</item> | |||
<item name="android:layout_marginStart">38dp</item> | |||
<item name="android:layout_marginEnd">38dp</item> | |||
<item name="android:layout_marginTop">66dp</item> | |||
<item name="android:backgroundTint">@color/theme_color</item> | |||
</style> | |||
<!--dialog style --> | |||
<style name="dialog_style" parent="@android:style/Theme.Dialog"> | |||
<item name="android:windowBackground">@android:color/transparent</item> <!--窗口背景透明--> | |||
<item name="android:windowFrame">@null</item> <!--边框--> | |||
<item name="android:windowNoTitle">true</item> <!--无标题--> | |||
<item name="android:windowIsFloating">true</item> <!--是否浮现在activity之上--> | |||
<item name="android:windowIsTranslucent">true</item> <!--是否半透明--> | |||
<item name="android:backgroundDimEnabled">true</item> <!--模糊,背景透明是这个- 弹窗背景是否变暗 --> | |||
</style> | |||
</resources> |
@@ -3,13 +3,13 @@ | |||
<style name="Theme.XklLocal" parent="Theme.MaterialComponents.Light.DarkActionBar"> | |||
<!-- Primary brand color. --> | |||
<item name="colorPrimary">@color/white</item> <!--AppBar背景色--> | |||
<!-- <item name="colorPrimaryVariant">@color/white</item>--> | |||
<!-- <item name="colorPrimaryVariant">@color/white</item>--> | |||
<item name="colorOnPrimary">@color/black</item> | |||
<!-- <!– Secondary brand color. –>--> | |||
<!-- <item name="colorSecondary">@color/white</item>--> | |||
<!-- <item name="colorSecondaryVariant">@color/white</item>--> | |||
<!-- <item name="colorOnSecondary">@color/white</item>--> | |||
<!-- <!– Status bar color. –>--> | |||
<!-- <!– Secondary brand color. –>--> | |||
<!-- <item name="colorSecondary">@color/white</item>--> | |||
<!-- <item name="colorSecondaryVariant">@color/white</item>--> | |||
<!-- <item name="colorOnSecondary">@color/white</item>--> | |||
<!-- <!– Status bar color. –>--> | |||
<item name="android:statusBarColor" tools:targetApi="l">@color/white</item> | |||
<!-- Customize your theme here. --> | |||
<item name="android:textAllCaps">false</item> | |||
@@ -30,4 +30,13 @@ | |||
<item name="android:windowBackground">@drawable/theme_splash_bg</item> | |||
</style> | |||
<style name="Theme.XklLocal.NoActionBar"> | |||
<item name="windowActionBar">false</item> | |||
<item name="windowNoTitle">true</item> | |||
</style> | |||
<style name="Theme.XklLocal.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> | |||
<style name="Theme.XklLocal.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> | |||
</resources> |
@@ -82,7 +82,10 @@ ext { | |||
//SmartRefreshLayout | |||
SmartRefreshLayout: "io.github.scwang90:refresh-layout-kernel:2.0.5", | |||
//Lottie | |||
Lottie : "com.airbnb.android:lottie:5.0.3" | |||
Lottie : "com.airbnb.android:lottie:5.0.3", | |||
//Rxjava RxAndroid | |||
RxJava : "io.reactivex.rxjava3:rxjava:3.1.4", | |||
RxAndroid: "io.reactivex.rxjava3:rxandroid:3.0.0" | |||
] | |||
@@ -43,6 +43,7 @@ android { | |||
} | |||
dependencies { | |||
// implementation fileTree(include: ['*.jar',"*.aar"], dir: 'libs') | |||
implementation 'androidx.legacy:legacy-support-v4:1.0.0' | |||
rootProject.ext.dependencies_required.each{ k, v -> implementation v} | |||
testImplementation rootProject.ext.dependencies_testImplementation.junit | |||
@@ -59,6 +60,9 @@ dependencies { | |||
kapt customDependencies.GlideCompiler | |||
//glide translation | |||
api customDependencies.GlideTranslation | |||
//RxJava RxAndroid | |||
api customDependencies.RxJava | |||
api customDependencies.RxAndroid | |||
@@ -5,7 +5,7 @@ package com.suliang.common | |||
* create 2022/3/17 17:04 | |||
* Describe: | |||
*/ | |||
object Config { | |||
object AppConfig { | |||
const val INTENT_1 = "intent_1" | |||
const val INTENT_2 = "intent_2" | |||
const val INTENT_3 = "intent_3" |
@@ -54,5 +54,7 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment() { | |||
abstract fun initFragment() | |||
/** 是否布局背景透明 */ | |||
abstract fun isTransparent():Boolean | |||
open fun isTransparent():Boolean { | |||
return true | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
package com.suliang.common.base | |||
import android.graphics.drawable.AnimationDrawable | |||
import com.suliang.common.Config | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.databinding.LoadingFragmentBinding | |||
/** | |||
@@ -15,14 +15,14 @@ class LoadingDialog : BaseDialogFragment<LoadingFragmentBinding>() { | |||
@JvmStatic | |||
fun newInstance(msg : String): LoadingDialog { | |||
return LoadingDialog().apply { | |||
arguments?.putString(Config.INTENT_1,msg) | |||
arguments?.putString(AppConfig.INTENT_1,msg) | |||
} | |||
} | |||
} | |||
override fun initFragment() { | |||
//外部设置 | |||
arguments?.getString(Config.INTENT_1,null)?.let { | |||
arguments?.getString(AppConfig.INTENT_1,null)?.let { | |||
binding.loadText.text = it | |||
} | |||