| <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_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_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_learn_center.xml" value="0.25" /> | ||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_memo.xml" value="0.20104166666666667" /> | |||||
| <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/fragment_my.xml" value="0.28229166666666666" /> | ||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_control_button.xml" value="0.46467391304347827" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_control_button.xml" value="0.46467391304347827" /> | ||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_exam_spell_content.xml" value="0.45153985507246375" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_exam_spell_content.xml" value="0.45153985507246375" /> |
| package com.xkl.cdl | package com.xkl.cdl | ||||
| import android.annotation.SuppressLint | |||||
| import android.util.TypedValue | import android.util.TypedValue | ||||
| import android.view.View | import android.view.View | ||||
| import android.widget.LinearLayout | import android.widget.LinearLayout | ||||
| * @param example String? 例句 | * @param example String? 例句 | ||||
| * @param refrence String? 参考 | * @param refrence String? 参考 | ||||
| */ | */ | ||||
| @SuppressLint("SetTextI18n") | |||||
| fun IncWordDetailBinding.initValue(phrase : String?, example : String?, refrence : String?){ | fun IncWordDetailBinding.initValue(phrase : String?, example : String?, refrence : String?){ | ||||
| phrase?.let { | phrase?.let { | ||||
| tvPhraseFlag.visibility = View.VISIBLE | tvPhraseFlag.visibility = View.VISIBLE | ||||
| example?.let { | example?.let { | ||||
| tvExampleFlag.visibility = View.VISIBLE | tvExampleFlag.visibility = View.VISIBLE | ||||
| tvExample.visibility = View.VISIBLE | tvExample.visibility = View.VISIBLE | ||||
| tvExample.text = example | |||||
| tvExample.text = "▪ ${it.replace("\n", "\n▪ ")}" | |||||
| }?:let { | }?:let { | ||||
| tvExampleFlag.visibility = View.GONE | tvExampleFlag.visibility = View.GONE | ||||
| tvExample.visibility = View.GONE | tvExample.visibility = View.GONE |
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private val normalColorNotLearnOver by lazy { | |||||
| ContextCompat.getColor(context, R.color.gray_2) //学习未完成未选中时的颜色 | |||||
| } | |||||
| private val normalColorLearnOver by lazy { ContextCompat.getColor(context, R.color.gray_1) } //学习已完成未选中时的颜色 | |||||
| private val mainTextColor by lazy {ContextCompat.getColor(context, R.color.main_text_color) } //选中颜色 | |||||
| private val translationColor by lazy {ContextCompat.getColor(context, R.color.translation) } //透明颜色 | |||||
| private val themeColor by lazy { ContextCompat.getColor(context,R.color.theme_color) } //主题颜色 | |||||
| /** | /** | ||||
| * 处理颜色 选中色 未选中色(学习完成/学习未完成) | * 处理颜色 选中色 未选中色(学习完成/学习未完成) | ||||
| * @param lesson Lesson | * @param lesson Lesson | ||||
| */ | */ | ||||
| private fun ItemCourseLessonBinding.initColor(position: Int, 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的背景和状态设置 | //item的背景和状态设置 | ||||
| if (selectPos == position) { //选中,背景设置 | if (selectPos == position) { //选中,背景设置 | ||||
| layoutContent.setBackgroundColor(ContextCompat.getColor(context, R.color.gray_3)) //选中背景 | layoutContent.setBackgroundColor(ContextCompat.getColor(context, R.color.gray_3)) //选中背景 | ||||
| } | } | ||||
| } else { //未选中:根据学习情况判断 | } else { //未选中:根据学习情况判断 | ||||
| layoutContent.setBackgroundColor(translationColor) //未选中背景透明 | layoutContent.setBackgroundColor(translationColor) //未选中背景透明 | ||||
| if (lesson.learnIsOver) { | |||||
| if (lesson.learnIsOver) { //学习完成 | |||||
| tvLessonName.run { | tvLessonName.run { | ||||
| setTextColor(normalColorLearnOver) //课时名称颜色 | setTextColor(normalColorLearnOver) //课时名称颜色 | ||||
| paint.isFakeBoldText = false //加粗 | paint.isFakeBoldText = false //加粗 | ||||
| tvLessonNumber.setTextColor(normalColorLearnOver) //数量颜色 | tvLessonNumber.setTextColor(normalColorLearnOver) //数量颜色 | ||||
| ivArrowRight.run { | ivArrowRight.run { | ||||
| setBackgroundColor(translationColor) | setBackgroundColor(translationColor) | ||||
| imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.theme_color)) | |||||
| strokeColor = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.theme_color)) | |||||
| imageTintList = ColorStateList.valueOf(normalColorLearnOver) | |||||
| strokeColor = ColorStateList.valueOf(normalColorLearnOver) | |||||
| } | } | ||||
| } else { | |||||
| } else { //未完成 | |||||
| tvLessonName.run { | tvLessonName.run { | ||||
| setTextColor(normalColorNotLearnOver) //课时名称颜色 | setTextColor(normalColorNotLearnOver) //课时名称颜色 | ||||
| paint.isFakeBoldText = false //加粗 | paint.isFakeBoldText = false //加粗 | ||||
| tvLessonNumber.setTextColor(normalColorNotLearnOver) //数量颜色 | tvLessonNumber.setTextColor(normalColorNotLearnOver) //数量颜色 | ||||
| ivArrowRight.run { | ivArrowRight.run { | ||||
| setBackgroundColor(translationColor) | setBackgroundColor(translationColor) | ||||
| imageTintList = ColorStateList.valueOf(normalColorNotLearnOver) | |||||
| strokeColor = ColorStateList.valueOf(normalColorNotLearnOver) | |||||
| imageTintList = ColorStateList.valueOf(themeColor) | |||||
| strokeColor = ColorStateList.valueOf(themeColor) | |||||
| } | } | ||||
| } | } | ||||
| } | } |
| const val DIALOG_TYPE_EXAM_OVER = 2 | const val DIALOG_TYPE_EXAM_OVER = 2 | ||||
| /** 对话框类型: 学习结束弹窗类型 */ | /** 对话框类型: 学习结束弹窗类型 */ | ||||
| const val DIALOG_TYPE_LEARN_OVER = 3 | const val DIALOG_TYPE_LEARN_OVER = 3 | ||||
| /**对话框类型,item学习完成*/ | |||||
| const val DIALOG_TYPE_LESSON_ITEM_OVER = 4 | |||||
| /**--- 总线动作 --------------------------------- */ | /**--- 总线动作 --------------------------------- */ | ||||
| /**action key 改变界面 到目录页 */ | /**action key 改变界面 到目录页 */ | ||||
| const val EVENT_COURSE = "action_change_page" | |||||
| const val EVENT_CHANGE_PAGE = "action_change_page" | |||||
| /** lesson学习 数据传递 */ | |||||
| const val EVENT_LESSON_DATA = "lesson_learn_data" | |||||
| /** lesson学习中动作事件 : 课时学习中的动作*/ | |||||
| const val EVENT_LESSON_ACTION = "lesson_learn_action" | |||||
| /**总测数据与动作*/ | |||||
| const val EVENT_TOTAL_TEST = "total_test" | |||||
| /** 事件动作:学前总测结束弹窗之 开始学习 */ | /** 事件动作:学前总测结束弹窗之 开始学习 */ | ||||
| const val ACTION_COURSE_TEST_START_LEARN = 1 | const val ACTION_COURSE_TEST_START_LEARN = 1 | ||||
| const val ACTION_LESSON_AFTER_TEST_NEXT = 8 | const val ACTION_LESSON_AFTER_TEST_NEXT = 8 | ||||
| /**数据动作: 课时学习完成*/ | /**数据动作: 课时学习完成*/ | ||||
| const val DATA_LESSON_LEARN_OVER = 9 | const val DATA_LESSON_LEARN_OVER = 9 | ||||
| /**学后总测试完成: 再测一次*/ | |||||
| const val ACTION_COURSE_TEST_AFTER_TOTAL_AGAIN = 10 | |||||
| /** 学后总测试完成,切换到目录页显示 */ | |||||
| const val ACTION_COURSE_TEST_AFTER_TOTAL_OVER = 11 | |||||
| /**学后总测结束,传递数据*/ | |||||
| const val DATA_COURSE_AFTER_TEST_OVER = 12 | |||||
| /**--- 弹窗动作 --------------------------------- */ | /**--- 弹窗动作 --------------------------------- */ | ||||
| /** 学前总测结束弹窗: 开始学习 ,课时学前测试开始弹窗*/ | /** 学前总测结束弹窗: 开始学习 ,课时学前测试开始弹窗*/ | ||||
| const val DIALOG_LESSON_AFTER_TEST_AGAIN = 4 | const val DIALOG_LESSON_AFTER_TEST_AGAIN = 4 | ||||
| /**课时学后测试弹窗动作: 下一步*/ | /**课时学后测试弹窗动作: 下一步*/ | ||||
| const val DIALOG_LESSON_AFTER_TEST_NEXT = 5 | const val DIALOG_LESSON_AFTER_TEST_NEXT = 5 | ||||
| /**弹窗动作提示: 完成*/ | |||||
| const val DIALOG_OVER = 6 | |||||
| /**课时学后总测的再测一次*/ | |||||
| const val DIALOG_AFTER_TOTAL_TEST_AGAIN = 7 | |||||
| } | } |
| * 词汇量测试 | * 词汇量测试 | ||||
| * | * | ||||
| */ | */ | ||||
| class LearnDialogBean(val dialogType:Int) : Parcelable { | |||||
| class LearnDialogBean(val dialogType:Int) :Parcelable { | |||||
| /*---------------测试使用------------------------------------*/ | /*---------------测试使用------------------------------------*/ | ||||
| /** 测试类型 */ | /** 测试类型 */ | ||||
| /** 题数与时间 */ | /** 题数与时间 */ | ||||
| var showTimeCount = "" | var showTimeCount = "" | ||||
| constructor(parcel : Parcel) : this(parcel.readInt()) { | constructor(parcel : Parcel) : this(parcel.readInt()) { | ||||
| examType = parcel.readInt() | examType = parcel.readInt() | ||||
| score = parcel.readInt() | score = parcel.readInt() | ||||
| correctNumber = parcel.readInt() | correctNumber = parcel.readInt() | ||||
| errorNumber = parcel.readInt() | errorNumber = parcel.readInt() | ||||
| chapter_lesson_name = parcel.readString().toString() | |||||
| showTimeCount = parcel.readString().toString() | |||||
| } | } | ||||
| override fun writeToParcel(parcel : Parcel, flags : Int) { | override fun writeToParcel(parcel : Parcel, flags : Int) { | ||||
| parcel.writeInt(score) | parcel.writeInt(score) | ||||
| parcel.writeInt(correctNumber) | parcel.writeInt(correctNumber) | ||||
| parcel.writeInt(errorNumber) | parcel.writeInt(errorNumber) | ||||
| parcel.writeString(chapter_lesson_name) | |||||
| parcel.writeString(showTimeCount) | |||||
| } | } | ||||
| override fun describeContents() : Int { | override fun describeContents() : Int { | ||||
| return arrayOfNulls(size) | return arrayOfNulls(size) | ||||
| } | } | ||||
| } | } | ||||
| } | } |
| package com.xkl.cdl.data.bean.course | package com.xkl.cdl.data.bean.course | ||||
| import androidx.databinding.BaseObservable | |||||
| /** | /** | ||||
| * author suliang | * author suliang | ||||
| * create 2022/3/22 10:08 | * create 2022/3/22 10:08 |
| package com.xkl.cdl.data.bean.course | package com.xkl.cdl.data.bean.course | ||||
| import com.xkl.cdl.data.AppConstants | |||||
| import java.io.Serializable | |||||
| /** | /** | ||||
| * author suliang | * author suliang | ||||
| * create 2022/3/29 9:52 | * create 2022/3/29 9:52 | ||||
| * Describe: 课程学习的详情 | * Describe: 课程学习的详情 | ||||
| */ | */ | ||||
| class CourseDetail { | |||||
| class CourseDetail:Serializable{ | |||||
| var courseLearnProgress: Double = 0.0 //课程学习进度 | var courseLearnProgress: Double = 0.0 //课程学习进度 | ||||
| var st_before: Double = -1.0 //学前总成绩 : -1代表没有进行学前总测试 | |||||
| var st_after: Double = -1.0 //学后总成绩 : -1代表没有进行学后总测试 | |||||
| var st_before: Double = AppConstants.NOT_DOING //学前总成绩 : -1代表没有进行学前总测试 | |||||
| var st_after: Double = AppConstants.NOT_DOING //学后总成绩 : -1代表没有进行学后总测试 | |||||
| var before: HashMap<String, Double> = hashMapOf() //章节学前测试成绩,key=>{chapter_id}_{lesson_id} value=>成绩 | 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 after: HashMap<String, Double> = hashMapOf() //章节学后测试成绩,key=>{chapter_id}_{lesson_id} value=>成绩 | ||||
| var right = hashMapOf<String, Int>() //正确条目数,key=>{chapter_id}_{lesson_id} value=>条目数量 | var right = hashMapOf<String, Int>() //正确条目数,key=>{chapter_id}_{lesson_id} value=>条目数量 |
| /** 学习进度位置,为已学下标的位置,在作文课堂练习时,学习取当前条,其他取下一条*/ | /** 学习进度位置,为已学下标的位置,在作文课堂练习时,学习取当前条,其他取下一条*/ | ||||
| var learnedIndex: Int = -1 | var learnedIndex: Int = -1 | ||||
| /**课时学前测试成绩 */ | /**课时学前测试成绩 */ | ||||
| var beforeTestScore = -1.0 | |||||
| var beforeTestScore = AppConstants.NOT_DOING | |||||
| /** 课时学后测试 */ | /** 课时学后测试 */ | ||||
| var afterTestScore = -1.0 | |||||
| var afterTestScore = AppConstants.NOT_DOING | |||||
| /**是否学习完成: 为学习内容是否完成,不包含学前,学后测试*/ | /**是否学习完成: 为学习内容是否完成,不包含学前,学后测试*/ | ||||
| var learnIsOver = false | var learnIsOver = false | ||||
| /**是否是最后一个课时 */ | /**是否是最后一个课时 */ |
| } | } | ||||
| /** | /** | ||||
| * 计算项目总进度 | |||||
| * 计算项目总进度 ,并将课程进度值设置进入集合中 | |||||
| * @param subjectId Int 项目Id | * @param subjectId Int 项目Id | ||||
| * @param packId Long 修改进度的课程包id | * @param packId Long 修改进度的课程包id | ||||
| * @param courseId Long 修改进度的课程id | * @param courseId Long 修改进度的课程id | ||||
| if (totalCourseSize == 0) return 0.0 | if (totalCourseSize == 0) return 0.0 | ||||
| return totalProgress / totalCourseSize | return totalProgress / totalCourseSize | ||||
| } | } | ||||
| /** | |||||
| * 重学课程的课时时,计算项目的进度,不会进行赋值 | |||||
| * @param subjectId Int 项目 | |||||
| * @param courseId Long 重学的课程 | |||||
| * @param courseProgress Double 被重学课时的课程进度 | |||||
| * @return Double 项目的总进度 | |||||
| */ | |||||
| fun calculateSubjectProgressWithCourseLessonRelearn(subjectId : Int,coursePackId:Long, courseId : Long,courseProgress:Double) : Double { | |||||
| val totalProgress = mSortInfoList.get(subjectId)?.let { | |||||
| var tempProgress = 0.0 | |||||
| it.forEach { | |||||
| if (it.packId == coursePackId && it.courseId == courseId){ | |||||
| tempProgress += courseProgress | |||||
| return@forEach | |||||
| }else { | |||||
| tempProgress += it.s | |||||
| } | |||||
| } | |||||
| tempProgress | |||||
| }?: 0.0 | |||||
| if (totalProgress == 0.0 ) return totalProgress | |||||
| var totalCourseSize = 0 | |||||
| subjectWithCoursePackMap.get(subjectId)?.forEach { | |||||
| totalCourseSize += it.childrenCourses.size | |||||
| } | |||||
| if (totalCourseSize == 0) return 0.0 | |||||
| return totalProgress / totalCourseSize | |||||
| } | |||||
| } | } |
| totalNumber = this.wordIds.size //总数 | totalNumber = this.wordIds.size //总数 | ||||
| correctNumber = detail.right.getOrElse(key, { 0 }) //正确数 | correctNumber = detail.right.getOrElse(key, { 0 }) //正确数 | ||||
| errorNumber = detail.wrong.getOrElse(key, { 0 }) //错误数 | errorNumber = detail.wrong.getOrElse(key, { 0 }) //错误数 | ||||
| beforeTestScore = detail.before.getOrElse(key, { -1.0 }) //课时学前测试成绩 | |||||
| afterTestScore = detail.after.getOrElse(key, { -1.0 }) //课时学后测试成绩 | |||||
| beforeTestScore = detail.before.getOrElse(key, { AppConstants.NOT_DOING }) //课时学前测试成绩 | |||||
| afterTestScore = detail.after.getOrElse(key, { AppConstants.NOT_DOING }) //课时学后测试成绩 | |||||
| this.learnedIndex = learnIndex //学习位置,当前位置为已学 | this.learnedIndex = learnIndex //学习位置,当前位置为已学 | ||||
| this.learnIsOver = learnIsOver | this.learnIsOver = learnIsOver | ||||
| this.lessonType = lessonType | this.lessonType = lessonType |
| import android.util.LruCache | import android.util.LruCache | ||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| import com.suliang.common.AppConfig | import com.suliang.common.AppConfig | ||||
| import com.suliang.common.eventbus.NonStickyMutableLiveData | |||||
| import com.suliang.common.extension.diskIo2Main | import com.suliang.common.extension.diskIo2Main | ||||
| import com.suliang.common.util.file.FileUtil | import com.suliang.common.util.file.FileUtil | ||||
| import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
| } | } | ||||
| /** 通知查到的录音 */ | /** 通知查到的录音 */ | ||||
| var audioLiveData = NonStickyMutableLiveData<String?>() | |||||
| private lateinit var audioLiveData : MutableLiveData<String?> | |||||
| // fun initAudioLiveData() : MutableLiveData<String?>{ | |||||
| // audioLiveData = NonStickyMutableLiveData<String?>() | |||||
| // return audioLiveData | |||||
| // } | |||||
| fun initAudioLiveData() : MutableLiveData<String?> { | |||||
| audioLiveData = MutableLiveData<String?>() | |||||
| return audioLiveData | |||||
| } | |||||
| /** | /** | ||||
| * 获取对应音频 | * 获取对应音频 | ||||
| return@fromCallable lruCache.get(defaultKey) ?: "" | return@fromCallable lruCache.get(defaultKey) ?: "" | ||||
| }.compose(diskIo2Main()).subscribe { | }.compose(diskIo2Main()).subscribe { | ||||
| if (this::audioLiveData.isInitialized) | |||||
| audioLiveData.value = it | audioLiveData.value = it | ||||
| } | } | ||||
| } | } |
| package com.xkl.cdl.data.repository | package com.xkl.cdl.data.repository | ||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| import com.suliang.common.util.file.FileUtil | |||||
| import com.xkl.cdl.data.bean.course.CourseDetail | import com.xkl.cdl.data.bean.course.CourseDetail | ||||
| import com.xkl.cdl.data.bean.course.Lesson | import com.xkl.cdl.data.bean.course.Lesson | ||||
| import com.xkl.cdl.data.manager.db.DBCourseManager | import com.xkl.cdl.data.manager.db.DBCourseManager | ||||
| import com.xkl.cdl.data.manager.db.DbControlBase | import com.xkl.cdl.data.manager.db.DbControlBase | ||||
| import io.reactivex.rxjava3.core.Observable | import io.reactivex.rxjava3.core.Observable | ||||
| import mqComsumerV1.Struct | import mqComsumerV1.Struct | ||||
| import java.io.File | |||||
| /** | /** | ||||
| * author suliang | * author suliang | ||||
| } | } | ||||
| /** 获取课程的详情 */ | /** 获取课程的详情 */ | ||||
| fun getCourseStatistics(): Observable<CourseDetail>{ | |||||
| fun getCourseStatistics(subjectId:Int,coursePackId:Long,courseId:Long): Observable<CourseDetail>{ | |||||
| return Observable.create{ | return Observable.create{ | ||||
| val courseDetail = CourseDetail() | |||||
| // TODO: 2022/5/6 这里自己使用的缓存 | |||||
| val file = File(FileUtil.getSaveDirPath("appcache"), "${subjectId}_${coursePackId}_${courseId}") | |||||
| val courseDetail = if (file.exists()){ | |||||
| FileUtil.bytesToObject(FileUtil.readFile(file)) as CourseDetail | |||||
| }else{ | |||||
| CourseDetail() | |||||
| } | |||||
| it.onNext(courseDetail) | it.onNext(courseDetail) | ||||
| it.onComplete() | it.onComplete() | ||||
| } | } |
| import android.util.LruCache | import android.util.LruCache | ||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| import com.suliang.common.AppConfig | |||||
| import com.suliang.common.eventbus.NonStickyMutableLiveData | |||||
| import com.suliang.common.extension.diskIo2Main | import com.suliang.common.extension.diskIo2Main | ||||
| import com.suliang.common.util.file.FileUtil | |||||
| import com.xkl.cdl.data.AppConstants | |||||
| import com.xkl.cdl.data.manager.db.DBCourseManager | import com.xkl.cdl.data.manager.db.DBCourseManager | ||||
| import com.xkl.cdl.data.manager.db.DbControlBase | import com.xkl.cdl.data.manager.db.DbControlBase | ||||
| import io.reactivex.rxjava3.core.Observable | import io.reactivex.rxjava3.core.Observable | ||||
| import java.io.File | |||||
| import java.util.* | import java.util.* | ||||
| /** | /** | ||||
| } | } | ||||
| } | } | ||||
| /** 通知查到的录音 */ | |||||
| var photoLiveData = NonStickyMutableLiveData<ByteArray?>() | |||||
| /** 通知查到的图片字节码 */ | |||||
| private lateinit var photoLiveData : MutableLiveData<ByteArray?> | |||||
| fun initPhotoLiveData() : MutableLiveData<ByteArray?> { | |||||
| photoLiveData = MutableLiveData<ByteArray?>() | |||||
| return photoLiveData | |||||
| } | |||||
| /** | /** | ||||
| * 获取对应图片 | * 获取对应图片 | ||||
| * 1缓存 2文件 3数据库 | * 1缓存 2文件 3数据库 | ||||
| return@fromCallable lruCache.get(defaultKey) | return@fromCallable lruCache.get(defaultKey) | ||||
| }.compose(diskIo2Main()).subscribe { | }.compose(diskIo2Main()).subscribe { | ||||
| if (this::photoLiveData.isInitialized) | |||||
| photoLiveData.value = it | photoLiveData.value = it | ||||
| } | } | ||||
| } | } |
| package com.xkl.cdl.dialog | |||||
| /** | |||||
| * author suliang | |||||
| * create 2022/4/6 9:54 | |||||
| * Describe: LearnDialog 按钮点击动作 | |||||
| */ | |||||
| enum class DialogEventAction { | |||||
| /**下一步*/ | |||||
| NEXT, | |||||
| /** 开始学习 */ | |||||
| START_LEARN, | |||||
| /** 课时学前测试 */ | |||||
| START_LESSON_BEFORE_TEST | |||||
| // TODO: 2022/4/6 可以添加相应的动作action,来处理对应的动作 | |||||
| } |
| AppConstants.DIALOG_TYPE_EXAM_START -> when(learnDialogBean.examType){ | AppConstants.DIALOG_TYPE_EXAM_START -> when(learnDialogBean.examType){ | ||||
| //课时学前测试开始弹窗 | //课时学前测试开始弹窗 | ||||
| AppConstants.TEST_TYPE_BEFORE -> initLessonBeforeTestStart() | AppConstants.TEST_TYPE_BEFORE -> initLessonBeforeTestStart() | ||||
| //课时最后一个课时测试结束的下一步弹出此弹窗:学后总测试开始的弹窗 | |||||
| AppConstants.TEST_TYPE_AFTER_TOTAL -> initCourseAfterTestStart() | |||||
| } | } | ||||
| //测试结束弹窗 | //测试结束弹窗 | ||||
| AppConstants.DIALOG_TYPE_EXAM_OVER -> when (learnDialogBean.examType) { | AppConstants.DIALOG_TYPE_EXAM_OVER -> when (learnDialogBean.examType) { | ||||
| AppConstants.TEST_TYPE_BEFORE_TOTAL -> initCourseBeforeTotalTestOver() | AppConstants.TEST_TYPE_BEFORE_TOTAL -> initCourseBeforeTotalTestOver() | ||||
| //课时学前测试结束弹窗 | //课时学前测试结束弹窗 | ||||
| AppConstants.TEST_TYPE_BEFORE-> initLessonBeforeTestOver() | AppConstants.TEST_TYPE_BEFORE-> initLessonBeforeTestOver() | ||||
| //课时后测试结束 | |||||
| AppConstants.TEST_TYPE_AFTER -> initLessonAfterTestOver() | |||||
| //学后总测试结束弹窗 | |||||
| AppConstants.TEST_TYPE_AFTER_TOTAL -> initCourseAfterTestOver() | |||||
| } | } | ||||
| //学习结束弹窗 | //学习结束弹窗 | ||||
| AppConstants.DIALOG_TYPE_LEARN_OVER -> initLessonLearningOver() | AppConstants.DIALOG_TYPE_LEARN_OVER -> initLessonLearningOver() | ||||
| /**课时列表点击课时完全完成*/ | |||||
| AppConstants.DIALOG_TYPE_LESSON_ITEM_OVER -> initLessonItemClickLessonOver() | |||||
| } | } | ||||
| } | } | ||||
| */ | */ | ||||
| private fun initLessonBeforeTestStart() { | private fun initLessonBeforeTestStart() { | ||||
| binding.run { | binding.run { | ||||
| ivClose.visibility = View.VISIBLE | |||||
| tvTitle.visibility = View.VISIBLE | tvTitle.visibility = View.VISIBLE | ||||
| tvLessonName.visibility = View.VISIBLE | tvLessonName.visibility = View.VISIBLE | ||||
| tvCountTime.visibility = View.VISIBLE | tvCountTime.visibility = View.VISIBLE | ||||
| tvLessonName.text = learnDialogBean.chapter_lesson_name | tvLessonName.text = learnDialogBean.chapter_lesson_name | ||||
| tvCountTime.text = learnDialogBean.showTimeCount | tvCountTime.text = learnDialogBean.showTimeCount | ||||
| tvRight.text = "开始测试" | tvRight.text = "开始测试" | ||||
| imgIv.setImageResource(R.mipmap.girl_1) | |||||
| imgIv.setImageResource(if (Random.nextBoolean()) R.mipmap.boy_1 else R.mipmap.girl_1) | |||||
| //开始测试,进入课时学前测试界面 | //开始测试,进入课时学前测试界面 | ||||
| binding.tvRight.click { | binding.tvRight.click { | ||||
| onDialogListener(AppConstants.DIALOG_START_TEST, this@LearnDialog) | onDialogListener(AppConstants.DIALOG_START_TEST, this@LearnDialog) | ||||
| } | } | ||||
| // tvLeft.visibility = View.VISIBLE | |||||
| // vSplit.visibility = View.VISIBLE | |||||
| // tvLeft.text = "跳过测试" | |||||
| //跳过测试,直接进入学习界面 | |||||
| // binding.tvLeft.click { | |||||
| // onDialogListener(AppConstants.DIALOG_START_LEARN, this@LearnDialog) | |||||
| // } | |||||
| binding.ivClose.click { dismissAllowingStateLoss() } | |||||
| } | } | ||||
| } | } | ||||
| */ | */ | ||||
| private fun initLessonBeforeTestOver() { | private fun initLessonBeforeTestOver() { | ||||
| binding.run { | binding.run { | ||||
| imgIv.setImageResource(if (Random.nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | |||||
| tvScore.visibility = View.VISIBLE | tvScore.visibility = View.VISIBLE | ||||
| tvTip.visibility = View.VISIBLE | tvTip.visibility = View.VISIBLE | ||||
| tvTitle.visibility = View.VISIBLE | tvTitle.visibility = View.VISIBLE | ||||
| binding.run { | binding.run { | ||||
| imgIv.setImageResource(if (Random.nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | imgIv.setImageResource(if (Random.nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | ||||
| tvTitle.visibility = View.VISIBLE | tvTitle.visibility = View.VISIBLE | ||||
| tvTitle.text = "恭喜你,本课时学习完成" | |||||
| tvTitle.text = "恭喜你,本课时学习完成!" | |||||
| incStatisticsNumber.root.visibility = View.VISIBLE | incStatisticsNumber.root.visibility = View.VISIBLE | ||||
| tvLearnOverTip.visibility = View.VISIBLE | tvLearnOverTip.visibility = View.VISIBLE | ||||
| tvLearnOverForAfterCountTime.visibility = View.VISIBLE | tvLearnOverForAfterCountTime.visibility = View.VISIBLE | ||||
| tvLeft.visibility = View.VISIBLE | tvLeft.visibility = View.VISIBLE | ||||
| vSplit.visibility = View.VISIBLE | vSplit.visibility = View.VISIBLE | ||||
| tvTitle.text = "恭喜你,完成了课时学后测试" | tvTitle.text = "恭喜你,完成了课时学后测试" | ||||
| tvTop1.text = "重新学习" | |||||
| tvTop.text = "重新学习" | |||||
| tvLeft.text = "再测一次" | tvLeft.text = "再测一次" | ||||
| tvRight.text = "下一课时" | tvRight.text = "下一课时" | ||||
| onDialogListener(AppConstants.DIALOG_LESSON_AFTER_TEST_NEXT,this) | onDialogListener(AppConstants.DIALOG_LESSON_AFTER_TEST_NEXT,this) | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * 课程学后总测试开始前提示弹窗 | |||||
| */ | |||||
| private fun initCourseAfterTestStart() { | |||||
| binding.run { | |||||
| imgIv.setImageResource(if (Random.nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | |||||
| tvLessonName.visibility = View.INVISIBLE //占布局,避免布局变形 | |||||
| tvTitle.visibility = View.VISIBLE | |||||
| tvTitle.text = "恭喜你,本课程全部学习完成!" | |||||
| tvTip1.visibility = View.VISIBLE | |||||
| tvTip1.text = "我的学习效果是?快去学后总测试吧!" | |||||
| tvCountTime.visibility = View.VISIBLE | |||||
| tvCountTime.text = learnDialogBean.showTimeCount | |||||
| tvRight.text = "开始测试" | |||||
| //开始测试,进入课时学前测试界面 | |||||
| binding.tvRight.click { | |||||
| onDialogListener(AppConstants.DIALOG_START_TEST, this@LearnDialog) | |||||
| } | |||||
| tvLeft.visibility = View.VISIBLE | |||||
| vSplit.visibility = View.VISIBLE | |||||
| tvLeft.text = "完成" | |||||
| binding.tvLeft.click { | |||||
| onDialogListener(AppConstants.DIALOG_OVER, this@LearnDialog) | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 课程学后总测试结束弹窗 | |||||
| */ | |||||
| private fun initCourseAfterTestOver(){ | |||||
| initNumber() | |||||
| initScore() | |||||
| binding.run { | |||||
| tvScore.visibility = View.VISIBLE | |||||
| tvTip.visibility = View.VISIBLE | |||||
| tvTitle.visibility = View.VISIBLE | |||||
| tvTip1.visibility = View.VISIBLE | |||||
| incStatisticsNumber.root.visibility = View.VISIBLE | |||||
| tvTop.visibility = View.VISIBLE | |||||
| tvLeft.visibility = View.VISIBLE | |||||
| vSplit.visibility = View.VISIBLE | |||||
| tvTitle.text = "恭喜你,完成了学后总测试" | |||||
| tvTop.text = "继续学习" | |||||
| tvLeft.text = "再测一次" | |||||
| tvRight.text = "完成" | |||||
| } | |||||
| binding.tvTop.click { | |||||
| onDialogListener(AppConstants.DIALOG_OVER, this) | |||||
| } | |||||
| binding.tvLeft.click { | |||||
| onDialogListener(AppConstants.DIALOG_AFTER_TOTAL_TEST_AGAIN,this) | |||||
| } | |||||
| binding.tvRight.click { | |||||
| onDialogListener(AppConstants.DIALOG_OVER, this) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 课时列表item点击时课程已完全学习完成(学前测、学后测、学习都已完成)的提示弹窗 | |||||
| * tv_title,inc_statistics_number,tv_learn_over_tip,tv_learn_over_for_after_count_time,tv_left,vSplit | |||||
| */ | |||||
| private fun initLessonItemClickLessonOver(){ | |||||
| initNumber() | |||||
| binding.run { | |||||
| imgIv.setImageResource(if (Random.nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | |||||
| ivClose.visibility = View.VISIBLE | |||||
| tvTitle.visibility = View.VISIBLE | |||||
| tvTitle.text = "恭喜你,本课时学习完成!" | |||||
| incStatisticsNumber.root.visibility = View.VISIBLE | |||||
| tvLearnOverTip.visibility = View.VISIBLE | |||||
| tvLearnOverTip.text = "你可重新学习本课时,或重新进行课时学后测试" | |||||
| tvLearnOverForAfterCountTime.visibility = View.VISIBLE | |||||
| tvLearnOverForAfterCountTime.text = "(上次课时学后测试成绩:${learnDialogBean.score})" | |||||
| tvLeft.visibility = View.VISIBLE | |||||
| tvLeft.text = "重新学习" | |||||
| vSplit.visibility = View.VISIBLE | |||||
| tvRight.text = "课时学后测试" | |||||
| } | |||||
| binding.ivClose.click { dismissAllowingStateLoss() } | |||||
| binding.tvLeft.click { onDialogListener(AppConstants.DIALOG_LESSON_RELEARN, this) } | |||||
| binding.tvRight.click { onDialogListener(AppConstants.DIALOG_START_TEST, this) } | |||||
| } | |||||
| } | } |
| import androidx.recyclerview.widget.GridLayoutManager | import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.SimpleItemAnimator | import androidx.recyclerview.widget.SimpleItemAnimator | ||||
| import com.airbnb.lottie.LottieAnimationView | import com.airbnb.lottie.LottieAnimationView | ||||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||||
| import com.suliang.common.base.activity.BaseActivityVM | import com.suliang.common.base.activity.BaseActivityVM | ||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.suliang.common.extension.click | import com.suliang.common.extension.click | ||||
| import com.suliang.common.util.DateUtil | import com.suliang.common.util.DateUtil | ||||
| import com.suliang.common.util.DrawableUti | import com.suliang.common.util.DrawableUti | ||||
| } | } | ||||
| /** 查询到播放数据过来 */ | /** 查询到播放数据过来 */ | ||||
| AudioCache.audioLiveData.observe(this) { | |||||
| AudioCache.initAudioLiveData().observe(this) { | |||||
| if (it == null) { | if (it == null) { | ||||
| //发音文件为空 | //发音文件为空 | ||||
| showToast("未找到发音文件") | showToast("未找到发音文件") | ||||
| LearnDialog.newInstance(learnDialogBean).apply { | LearnDialog.newInstance(learnDialogBean).apply { | ||||
| onDialogListener = { action, dialog -> | onDialogListener = { action, dialog -> | ||||
| when (vm.intentData.examType) { | when (vm.intentData.examType) { | ||||
| //学前测试结束,只有一个按钮,开始学习 -> 发送消息切换到课时列表页 | |||||
| //学前总测试结束,只有一个按钮,开始学习 -> 发送消息切换到课时列表页 | |||||
| AppConstants.TEST_TYPE_BEFORE_TOTAL -> when (action) { | AppConstants.TEST_TYPE_BEFORE_TOTAL -> when (action) { | ||||
| AppConstants.DIALOG_START_LEARN -> { | AppConstants.DIALOG_START_LEARN -> { | ||||
| dialog.dismissAllowingStateLoss() | dialog.dismissAllowingStateLoss() | ||||
| //发送动作 : 继续学习 | //发送动作 : 继续学习 | ||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| LearnEventData(vm.intentData.subjectId, | |||||
| vm.intentData.courseId, | |||||
| AppConstants.ACTION_COURSE_TEST_START_LEARN) | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_CHANGE_PAGE).post(LearnEventData(vm.intentData.subjectId, | |||||
| vm.intentData.courseId, | |||||
| AppConstants.ACTION_COURSE_TEST_START_LEARN)) | |||||
| finish() | finish() | ||||
| } | } | ||||
| } | } | ||||
| AppConstants.TEST_TYPE_BEFORE -> when (action) { | AppConstants.TEST_TYPE_BEFORE -> when (action) { | ||||
| AppConstants.DIALOG_START_LEARN -> { | AppConstants.DIALOG_START_LEARN -> { | ||||
| dialog.dismissAllowingStateLoss() | dialog.dismissAllowingStateLoss() | ||||
| //发送动作 : 继续学习 | |||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| //发送动作 : 开始学习 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(vm.intentData.subjectId, | LearnEventData(vm.intentData.subjectId, | ||||
| vm.intentData.courseId, | vm.intentData.courseId, | ||||
| AppConstants.ACTION_LESSON_BEFORE_TEST_OVER_START_LEARN).apply { | AppConstants.ACTION_LESSON_BEFORE_TEST_OVER_START_LEARN).apply { | ||||
| leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | ||||
| } | |||||
| }) | |||||
| finish() | finish() | ||||
| } | } | ||||
| } | } | ||||
| if (isRightClick){ | if (isRightClick){ | ||||
| dialog.dismissAllowingStateLoss() | dialog.dismissAllowingStateLoss() | ||||
| //发送动作 : 重新学习 | //发送动作 : 重新学习 | ||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(vm.intentData.subjectId, | LearnEventData(vm.intentData.subjectId, | ||||
| vm.intentData.courseId, | vm.intentData.courseId, | ||||
| AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN).apply { | AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN).apply { | ||||
| leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | ||||
| } | |||||
| }) | |||||
| finish() | |||||
| } | } | ||||
| } | } | ||||
| }.show(childFragmentManager,"lesson_relearn_tip") | }.show(childFragmentManager,"lesson_relearn_tip") | ||||
| } | } | ||||
| //再测一次 | //再测一次 | ||||
| AppConstants.DIALOG_LESSON_AFTER_TEST_AGAIN -> { | AppConstants.DIALOG_LESSON_AFTER_TEST_AGAIN -> { | ||||
| //发送动作 : 继续学习 | |||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| //发送动作 : 再测一次 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(vm.intentData.subjectId, | LearnEventData(vm.intentData.subjectId, | ||||
| vm.intentData.courseId, | vm.intentData.courseId, | ||||
| AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN).apply { | AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN).apply { | ||||
| leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | ||||
| } | |||||
| }) | |||||
| finish() | |||||
| } | } | ||||
| //下一步 | //下一步 | ||||
| AppConstants.DIALOG_LESSON_AFTER_TEST_NEXT -> { | AppConstants.DIALOG_LESSON_AFTER_TEST_NEXT -> { | ||||
| //发送动作 : 继续学习 | |||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| //发送动作 : 下一步 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(vm.intentData.subjectId, | LearnEventData(vm.intentData.subjectId, | ||||
| vm.intentData.courseId, | vm.intentData.courseId, | ||||
| AppConstants.ACTION_LESSON_AFTER_TEST_NEXT).apply { | AppConstants.ACTION_LESSON_AFTER_TEST_NEXT).apply { | ||||
| leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | leesonPositionIndex = vm.intentData.lesson?.lessonPositionInList!! | ||||
| } | |||||
| }) | |||||
| finish() | |||||
| } | |||||
| } | |||||
| //学后总测试结束 | |||||
| AppConstants.TEST_TYPE_AFTER_TOTAL -> when(action){ | |||||
| //测试完成,切换到目录页 | |||||
| AppConstants.DIALOG_OVER -> { | |||||
| dialog.dismissAllowingStateLoss() | |||||
| //发送动作 : 继续学习 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_CHANGE_PAGE).post( | |||||
| LearnEventData(vm.intentData.subjectId, | |||||
| vm.intentData.courseId, | |||||
| AppConstants.ACTION_COURSE_TEST_AFTER_TOTAL_OVER)) | |||||
| finish() | |||||
| } | |||||
| //再测一次 | |||||
| AppConstants.DIALOG_AFTER_TOTAL_TEST_AGAIN -> { | |||||
| dialog.dismissAllowingStateLoss() | |||||
| //发送动作 : 再测一次 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_CHANGE_PAGE).post( | |||||
| LearnEventData(vm.intentData.subjectId, | |||||
| vm.intentData.courseId, | |||||
| AppConstants.ACTION_COURSE_TEST_AFTER_TOTAL_AGAIN)) | |||||
| finish() | |||||
| } | } | ||||
| } | } | ||||
| } | } |
| import androidx.lifecycle.LifecycleOwner | import androidx.lifecycle.LifecycleOwner | ||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| import androidx.lifecycle.viewModelScope | import androidx.lifecycle.viewModelScope | ||||
| import com.googlecode.protobuf.format.JsonFormat | |||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||||
| import com.suliang.common.extension.createRandomNewChar | import com.suliang.common.extension.createRandomNewChar | ||||
| import com.suliang.common.extension.diskIo2Main | import com.suliang.common.extension.diskIo2Main | ||||
| import com.suliang.common.util.DateUtil | import com.suliang.common.util.DateUtil | ||||
| //倒计时结束 | //倒计时结束 | ||||
| val currentCountingTimeOver = MutableLiveData<Boolean>() | val currentCountingTimeOver = MutableLiveData<Boolean>() | ||||
| init { | |||||
| isRunValidTime = false | |||||
| } | |||||
| /** 修改获取下一题的标记为true,则在onResume时,自动获取第一题 */ | /** 修改获取下一题的标记为true,则在onResume时,自动获取第一题 */ | ||||
| fun loadFirst(){ | fun loadFirst(){ | ||||
| isGetNextIng = true | isGetNextIng = true | ||||
| //计算分数 | //计算分数 | ||||
| calculateScore() | calculateScore() | ||||
| when(intentData.examType){ | when(intentData.examType){ | ||||
| AppConstants.TEST_TYPE_BEFORE -> { //学前总测为lesson添加错误数 与 分数 | |||||
| AppConstants.TEST_TYPE_BEFORE -> { //课时学前测试为lesson添加错误数 与 分数 | |||||
| intentData.lesson?.let { | intentData.lesson?.let { | ||||
| it.errorNumber = it.errorNumber + newErrorMap.size | |||||
| it.errorNumber += newErrorMap.size | |||||
| it.beforeTestScore = scoreValue.toDouble() | it.beforeTestScore = scoreValue.toDouble() | ||||
| } | } | ||||
| } | } | ||||
| } else { //相当于新错 | } else { //相当于新错 | ||||
| if (!newErrorMap.containsKey(key)) { | if (!newErrorMap.containsKey(key)) { | ||||
| newErrorMap[key] = true | newErrorMap[key] = true | ||||
| //课时前错误 ,则更新课时错误数量 | |||||
| if (intentData.examType == AppConstants.TEST_TYPE_BEFORE) { | |||||
| intentData.lesson!!.errorNumber = intentData.lesson!!.errorNumber + 1 | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| mLearnEntities.add(builder.build()) | mLearnEntities.add(builder.build()) | ||||
| //其他测试 | //其他测试 | ||||
| else -> { | else -> { | ||||
| val calculateCorrectNumber : Double = correctLiveData.value!! + unAnswerNumber * 0.25 | val calculateCorrectNumber : Double = correctLiveData.value!! + unAnswerNumber * 0.25 | ||||
| val scoreValue = ((calculateCorrectNumber - testData.size * 0.25) / (testData.size * 0.25) * 100).toInt() | |||||
| val scoreValue = ((calculateCorrectNumber - testData.size * 0.25) / (testData.size * 0.75) * 100).toInt() | |||||
| this.scoreValue = when { | this.scoreValue = when { | ||||
| scoreValue < 0 -> 0 | scoreValue < 0 -> 0 | ||||
| scoreValue > 100 -> 100 | scoreValue > 100 -> 100 | ||||
| else -> scoreValue | else -> scoreValue | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private fun sendEventBus(){ | private fun sendEventBus(){ | ||||
| when(intentData.examType){ | when(intentData.examType){ | ||||
| AppConstants.TEST_TYPE_BEFORE_TOTAL -> { //学前总测发送数据、学前总测发送数据 | AppConstants.TEST_TYPE_BEFORE_TOTAL -> { //学前总测发送数据、学前总测发送数据 | ||||
| LiveDataBus.withNonSticky<LearnEventData>(AppConstants.EVENT_COURSE).value = LearnEventData( | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_TOTAL_TEST).post( LearnEventData( | |||||
| intentData.subjectId, | intentData.subjectId, | ||||
| intentData.courseId, | intentData.courseId, | ||||
| AppConstants.DATA_COURSE_BEFORE_TEST_OVER).apply { | AppConstants.DATA_COURSE_BEFORE_TEST_OVER).apply { | ||||
| this.scoreValue = this@LearnExamViewModel.scoreValue | this.scoreValue = this@LearnExamViewModel.scoreValue | ||||
| this.newErrorMap = this@LearnExamViewModel.newErrorMap | this.newErrorMap = this@LearnExamViewModel.newErrorMap | ||||
| } | |||||
| }) | |||||
| } | } | ||||
| AppConstants.TEST_TYPE_BEFORE-> { // 课时学前测试结束发送数据 | AppConstants.TEST_TYPE_BEFORE-> { // 课时学前测试结束发送数据 | ||||
| LiveDataBus.withNonSticky<LearnEventData>(AppConstants.EVENT_COURSE).value = LearnEventData( | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_DATA).post( LearnEventData( | |||||
| intentData.subjectId, | intentData.subjectId, | ||||
| intentData.courseId, | intentData.courseId, | ||||
| AppConstants.DATA_LESSON_BEFORE_TEST_OVER).apply { | AppConstants.DATA_LESSON_BEFORE_TEST_OVER).apply { | ||||
| intentData.lesson?.let { | intentData.lesson?.let { | ||||
| leesonPositionIndex = it.lessonPositionInList | leesonPositionIndex = it.lessonPositionInList | ||||
| } | } | ||||
| } | |||||
| }) | |||||
| } | } | ||||
| AppConstants.TEST_TYPE_AFTER -> { //课时学后测试结束发送数据 | AppConstants.TEST_TYPE_AFTER -> { //课时学后测试结束发送数据 | ||||
| LiveDataBus.withNonSticky<LearnEventData>(AppConstants.EVENT_COURSE).value = LearnEventData( | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_DATA).post(LearnEventData( | |||||
| intentData.subjectId, | intentData.subjectId, | ||||
| intentData.courseId, | intentData.courseId, | ||||
| AppConstants.DATA_LESSON_AFTER_TEST_OVER).apply { | AppConstants.DATA_LESSON_AFTER_TEST_OVER).apply { | ||||
| this.newErrorMap = this@LearnExamViewModel.newErrorMap | |||||
| intentData.lesson?.let { | intentData.lesson?.let { | ||||
| leesonPositionIndex = it.lessonPositionInList | leesonPositionIndex = it.lessonPositionInList | ||||
| } | } | ||||
| } | |||||
| }) | |||||
| } | |||||
| AppConstants.TEST_TYPE_AFTER_TOTAL -> { //学后总测发送数据 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_TOTAL_TEST).post(LearnEventData( | |||||
| intentData.subjectId, | |||||
| intentData.courseId, | |||||
| AppConstants.DATA_COURSE_AFTER_TEST_OVER).apply { | |||||
| this.scoreValue = this@LearnExamViewModel.scoreValue | |||||
| }) | |||||
| } | } | ||||
| } | } | ||||
| } | } |
| import androidx.recyclerview.widget.RecyclerView | import androidx.recyclerview.widget.RecyclerView | ||||
| import androidx.recyclerview.widget.RecyclerView.OnScrollListener | import androidx.recyclerview.widget.RecyclerView.OnScrollListener | ||||
| import androidx.recyclerview.widget.SimpleItemAnimator | import androidx.recyclerview.widget.SimpleItemAnimator | ||||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||||
| import com.suliang.common.base.activity.BaseActivityVM | import com.suliang.common.base.activity.BaseActivityVM | ||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.suliang.common.extension.click | import com.suliang.common.extension.click | ||||
| import com.suliang.common.util.DateUtil | import com.suliang.common.util.DateUtil | ||||
| import com.suliang.common.util.LogUtil | import com.suliang.common.util.LogUtil | ||||
| vm.loadNext() | vm.loadNext() | ||||
| //发音数据 | //发音数据 | ||||
| AudioCache.audioLiveData.observe(this) { | |||||
| AudioCache.initAudioLiveData().observe(this) { | |||||
| it?.run { | it?.run { | ||||
| if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_ENGLISH_VOICE && bindingWord.ivVoice.visibility == View.VISIBLE) MPManager.play( | if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_ENGLISH_VOICE && bindingWord.ivVoice.visibility == View.VISIBLE) MPManager.play( | ||||
| it, listener = impListener) | it, listener = impListener) | ||||
| //如果需要显示图片,则添加监听 | //如果需要显示图片,则添加监听 | ||||
| if (vm.isNeedLoadPhoto) { | if (vm.isNeedLoadPhoto) { | ||||
| //图片数据 | //图片数据 | ||||
| PhotoCache.photoLiveData.observe(this) { | |||||
| PhotoCache.initPhotoLiveData().observe(this) { | |||||
| it?.run { ImageLoader.loadImage(bindingWord.imgWord, it) } ?: let { bindingWord.imgWord.visibility = View.GONE } | it?.run { ImageLoader.loadImage(bindingWord.imgWord, it) } ?: let { bindingWord.imgWord.visibility = View.GONE } | ||||
| } | } | ||||
| } | } | ||||
| private fun showLearnOverDialog() { | private fun showLearnOverDialog() { | ||||
| vm.loadAfterTest().observe(this) { showTimeCount -> | vm.loadAfterTest().observe(this) { showTimeCount -> | ||||
| LearnDialog.newInstance(LearnDialogBean(AppConstants.DIALOG_TYPE_LEARN_OVER).apply { | LearnDialog.newInstance(LearnDialogBean(AppConstants.DIALOG_TYPE_LEARN_OVER).apply { | ||||
| correctNumber = vm.learnData.lesson.correctNumber + vm.learnRuleUtil.currentCorrectMap.size | |||||
| errorNumber = vm.learnData.lesson.errorNumber + vm.learnRuleUtil.currentErrorMap.size | |||||
| correctNumber = vm.learnData.lesson.correctNumber | |||||
| errorNumber = vm.learnData.lesson.errorNumber | |||||
| this.showTimeCount = showTimeCount | this.showTimeCount = showTimeCount | ||||
| }).apply { | }).apply { | ||||
| onDialogListener = { action, dialog -> | onDialogListener = { action, dialog -> | ||||
| if (isRightClick){ | if (isRightClick){ | ||||
| dialog.dismissAllowingStateLoss() | dialog.dismissAllowingStateLoss() | ||||
| //发送动作 : 重新学习 | //发送动作 : 重新学习 | ||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| LearnEventData(vm.learnData.lesson.subjectId, | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(vm.learnData.lesson.subjectId, | |||||
| vm.learnData.lesson.courseId, | vm.learnData.lesson.courseId, | ||||
| AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN).apply { | AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN).apply { | ||||
| leesonPositionIndex = vm.learnData.lesson.lessonPositionInList | leesonPositionIndex = vm.learnData.lesson.lessonPositionInList | ||||
| } | |||||
| }) | |||||
| finish() | |||||
| } | } | ||||
| } | } | ||||
| }.show(childFragmentManager,"lesson_relearn_tip") | }.show(childFragmentManager,"lesson_relearn_tip") | ||||
| AppConstants.DIALOG_START_TEST -> { | AppConstants.DIALOG_START_TEST -> { | ||||
| dialog.dismissAllowingStateLoss() | dialog.dismissAllowingStateLoss() | ||||
| //发送动作 : 学后测试 | //发送动作 : 学后测试 | ||||
| LiveDataBus.with<LearnEventData>(AppConstants.EVENT_COURSE).value = | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(vm.learnData.lesson.subjectId, | LearnEventData(vm.learnData.lesson.subjectId, | ||||
| vm.learnData.lesson.courseId, | vm.learnData.lesson.courseId, | ||||
| AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN).apply { | AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN).apply { | ||||
| leesonPositionIndex = vm.learnData.lesson.lessonPositionInList | leesonPositionIndex = vm.learnData.lesson.lessonPositionInList | ||||
| } | |||||
| }) | |||||
| finish() | |||||
| } | } | ||||
| } | } | ||||
| } | } |
| import androidx.lifecycle.LifecycleOwner | import androidx.lifecycle.LifecycleOwner | ||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| import androidx.lifecycle.viewModelScope | import androidx.lifecycle.viewModelScope | ||||
| import com.googlecode.protobuf.format.JsonFormat | |||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||||
| import com.suliang.common.extension.createRandomNewChar | import com.suliang.common.extension.createRandomNewChar | ||||
| import com.suliang.common.extension.diskIo2Main | import com.suliang.common.extension.diskIo2Main | ||||
| import com.suliang.common.util.DateUtil | import com.suliang.common.util.DateUtil | ||||
| import com.suliang.common.util.LogUtil | |||||
| import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
| import com.xkl.cdl.data.DataTransferHolder | import com.xkl.cdl.data.DataTransferHolder | ||||
| import com.xkl.cdl.data.bean.LearnWord | import com.xkl.cdl.data.bean.LearnWord | ||||
| //数据上传完成监听: true 学习完成的上传 false可能是半途的返回事件,直接退出 | //数据上传完成监听: true 学习完成的上传 false可能是半途的返回事件,直接退出 | ||||
| val saveDataLiveData = MutableLiveData<Boolean>() | val saveDataLiveData = MutableLiveData<Boolean>() | ||||
| /** 获取数据 */ | /** 获取数据 */ | ||||
| fun loadNext() { | fun loadNext() { | ||||
| //修改标记 | //修改标记 | ||||
| currentLearnWord.value = it | currentLearnWord.value = it | ||||
| } ?: let { //没有数据 即学习完成 | } ?: let { //没有数据 即学习完成 | ||||
| isAllOver = true | isAllOver = true | ||||
| // 停止有效计时 | |||||
| isRunValidTime = false | |||||
| //停止总计时 | //停止总计时 | ||||
| stopTotalCountTing() | stopTotalCountTing() | ||||
| // TODO: 2022/4/26 停止有效计时 | |||||
| //封装保存数据 | //封装保存数据 | ||||
| saveData() | saveData() | ||||
| } | } | ||||
| learnedIndex = currentLessonLearnedPosition | learnedIndex = currentLessonLearnedPosition | ||||
| correctNumber += learnRuleUtil.currentCorrectMap.size | correctNumber += learnRuleUtil.currentCorrectMap.size | ||||
| errorNumber += learnRuleUtil.currentErrorMap.size | errorNumber += learnRuleUtil.currentErrorMap.size | ||||
| learnIsOver = (correctNumber + errorNumber == totalNumber) | |||||
| learnIsOver = learnedIndex == wordIds.size - 1 | |||||
| } | } | ||||
| //添加到错误本集合中,主要用于小游戏练习(学前总 课时都没有添加,从这里添加到集合后发送出去,添加到集合) | //添加到错误本集合中,主要用于小游戏练习(学前总 课时都没有添加,从这里添加到集合后发送出去,添加到集合) | ||||
| learnData.examErrorMap?.putAll(learnRuleUtil.currentErrorMap) | learnData.examErrorMap?.putAll(learnRuleUtil.currentErrorMap) | ||||
| /** 发送数据事件 */ | /** 发送数据事件 */ | ||||
| private fun sendEventBus() { | private fun sendEventBus() { | ||||
| LiveDataBus.withNonSticky<LearnEventData>(AppConstants.EVENT_COURSE).value = LearnEventData(learnData.lesson.subjectId, | |||||
| learnData.lesson.courseId, | |||||
| AppConstants.DATA_LESSON_LEARN_OVER).apply { | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_DATA).post(LearnEventData(learnData.lesson.subjectId, | |||||
| learnData.lesson.courseId, | |||||
| AppConstants.DATA_LESSON_LEARN_OVER).apply { | |||||
| this.leesonPositionIndex = learnData.lesson.lessonPositionInList | this.leesonPositionIndex = learnData.lesson.lessonPositionInList | ||||
| this.newErrorMap = learnData.examErrorMap | this.newErrorMap = learnData.examErrorMap | ||||
| } | |||||
| }) | |||||
| } | } | ||||
| import com.xkl.cdl.adapter.AdapterAutoPlaySelectRepeat | import com.xkl.cdl.adapter.AdapterAutoPlaySelectRepeat | ||||
| import com.xkl.cdl.adapter.ViewPagerAdapter | import com.xkl.cdl.adapter.ViewPagerAdapter | ||||
| import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
| import com.xkl.cdl.data.bean.LearnDialogBean | |||||
| import com.xkl.cdl.data.binding.BindingAdapter | import com.xkl.cdl.data.binding.BindingAdapter | ||||
| import com.xkl.cdl.data.manager.CourseManager | import com.xkl.cdl.data.manager.CourseManager | ||||
| import com.xkl.cdl.databinding.ActivityCourseMainBinding | import com.xkl.cdl.databinding.ActivityCourseMainBinding | ||||
| import com.xkl.cdl.databinding.DialogBottomAutoPlaySelectBinding | import com.xkl.cdl.databinding.DialogBottomAutoPlaySelectBinding | ||||
| import com.xkl.cdl.databinding.DialogBottomCourseMoreBinding | import com.xkl.cdl.databinding.DialogBottomCourseMoreBinding | ||||
| import com.xkl.cdl.dialog.CommonDialog | |||||
| import com.xkl.cdl.dialog.CommonDialogBean | |||||
| import com.xkl.cdl.module.m_center_learn.coursechildren.CourseMainFragment | import com.xkl.cdl.module.m_center_learn.coursechildren.CourseMainFragment | ||||
| import com.zackratos.ultimatebarx.ultimatebarx.statusBarOnly | import com.zackratos.ultimatebarx.ultimatebarx.statusBarOnly | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| //改变page后设置进度 | |||||
| //改变page后设置进度,获取该课程的进度进行设置 | |||||
| vm.currentCourseProgress.value = vm.coursePack.childrenCourses[position].courseLearnProgress | vm.currentCourseProgress.value = vm.coursePack.childrenCourses[position].courseLearnProgress | ||||
| } | } | ||||
| }) | }) | ||||
| progressbar.progress = it.toInt() | progressbar.progress = it.toInt() | ||||
| tvProgress.text = if (binding.includeCourseTypeTab.root.visibility == View.VISIBLE) { | tvProgress.text = if (binding.includeCourseTypeTab.root.visibility == View.VISIBLE) { | ||||
| val format = when (binding.viewPager2.currentItem) { | val format = when (binding.viewPager2.currentItem) { | ||||
| 0 -> "认读进度:%s" | |||||
| 1 -> "拼写进度:%s" | |||||
| 2 -> "辨音进度:%s" | |||||
| else -> "进度:%s" | |||||
| 0 -> "认读进度: %s%%" | |||||
| 1 -> "拼写进度: %s%%" | |||||
| 2 -> "辨音进度: %s%%" | |||||
| else -> "进度: %s%%" | |||||
| } | } | ||||
| String.format(format, CourseManager.useToShowProgress(it)) | String.format(format, CourseManager.useToShowProgress(it)) | ||||
| } else { | } else { | ||||
| String.format("进度:%s", CourseManager.useToShowProgress(it)) | |||||
| String.format("进度: %s%%", CourseManager.useToShowProgress(it)) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| //更多按钮点击 | //更多按钮点击 | ||||
| binding.includeCourseProgress.ivMore.click { | binding.includeCourseProgress.ivMore.click { | ||||
| if (vm.showMoreEnable) | |||||
| showMoreDialog() | showMoreDialog() | ||||
| else | |||||
| showToast("请先进行学习") | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| moreBinding.tvClearLearnRecord.click { | moreBinding.tvClearLearnRecord.click { | ||||
| dismiss() | dismiss() | ||||
| // TODO: 2022/3/29 弹窗显示清除学习记录 | |||||
| showCourseRelearnDialog() | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| moreDialog?.show() | moreDialog?.show() | ||||
| } | } | ||||
| /** 课程重学弹窗提示 */ | |||||
| fun showCourseRelearnDialog(){ | |||||
| //弹窗显示清除学习记录 | |||||
| val bean = CommonDialogBean(titleText = R.string.course_relearn_title, | |||||
| contentText = R.string.course_relearn_content, | |||||
| leftText = R.string.course_relearn_sure, rightText = R.string.cancel) | |||||
| CommonDialog.newInstance(bean).apply { | |||||
| onCommonDialogButtonClickListener = { dialog, isRightClick -> | |||||
| dialog.dismissAllowingStateLoss() | |||||
| if (!isRightClick){ | |||||
| ((this@CoursePackMainActivity.binding.viewPager2.adapter as ViewPagerAdapter).getItem(this@CoursePackMainActivity.binding.viewPager2.currentItem) as CourseMainFragment).run { | |||||
| this.courseRelearn() | |||||
| } | |||||
| } | |||||
| } | |||||
| }.show(supportFragmentManager,"course_relearn_dialog") | |||||
| } | |||||
| /** 自动播放次数选择: 仅单词会有该选项 */ | /** 自动播放次数选择: 仅单词会有该选项 */ | ||||
| private fun showAutoPlaySelectDialog() { | private fun showAutoPlaySelectDialog() { | ||||
| if (autoPlaySeletDialog == null) { | if (autoPlaySeletDialog == null) { | ||||
| private fun startAutoPlay(time: Int) { | private fun startAutoPlay(time: Int) { | ||||
| } | } | ||||
| override fun onStop() { | |||||
| super.onStop() | |||||
| //如果是中文项目,更新课程包的进度 | |||||
| if (vm.coursePack.subjectId == AppConstants.SUBJECT_CHINESE){ | |||||
| vm.coursePack.learnProgress = vm.coursePack.childrenCourses[0].courseLearnProgress | |||||
| } | |||||
| } | |||||
| /** ViewModel Factory工厂 */ | /** ViewModel Factory工厂 */ |
| * Describe: 课程主页 | * Describe: 课程主页 | ||||
| */ | */ | ||||
| class CoursePackMainActivityViewModel(subjectId: Int , coursePackInPosition : Int) : BaseViewModel() { | class CoursePackMainActivityViewModel(subjectId: Int , coursePackInPosition : Int) : BaseViewModel() { | ||||
| //操作的课程包 | //操作的课程包 | ||||
| val coursePack = CourseManager.subjectWithCoursePackMap[subjectId]!![coursePackInPosition] | val coursePack = CourseManager.subjectWithCoursePackMap[subjectId]!![coursePackInPosition] | ||||
| //设置显示当前课程的进度值和显示内容 | //设置显示当前课程的进度值和显示内容 | ||||
| val currentCourseProgress = MutableLiveData<Double>() | val currentCourseProgress = MutableLiveData<Double>() | ||||
| //更多点击是否有效 | |||||
| var showMoreEnable = false | |||||
| } | } |
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | import androidx.recyclerview.widget.RecyclerView | ||||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||||
| import com.suliang.common.base.fragment.BaseFragmentVM | import com.suliang.common.base.fragment.BaseFragmentVM | ||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.suliang.common.util.DateUtil | |||||
| import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
| import com.xkl.cdl.adapter.AdapterLesson | import com.xkl.cdl.adapter.AdapterLesson | ||||
| import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
| import com.xkl.cdl.data.bean.intentdata.ExamData | import com.xkl.cdl.data.bean.intentdata.ExamData | ||||
| import com.xkl.cdl.data.event.LearnEventData | import com.xkl.cdl.data.event.LearnEventData | ||||
| import com.xkl.cdl.data.manager.CourseManager | import com.xkl.cdl.data.manager.CourseManager | ||||
| import com.xkl.cdl.data.repository.DataRepository | |||||
| import com.xkl.cdl.databinding.FragmentCourseLessonBinding | import com.xkl.cdl.databinding.FragmentCourseLessonBinding | ||||
| import com.xkl.cdl.dialog.CommonDialog | |||||
| import com.xkl.cdl.dialog.CommonDialogBean | |||||
| import com.xkl.cdl.dialog.LearnDialog | import com.xkl.cdl.dialog.LearnDialog | ||||
| import com.xkl.cdl.module.learn.LearnWordActivity | import com.xkl.cdl.module.learn.LearnWordActivity | ||||
| import mqComsumerV1.Struct | |||||
| import java.text.DateFormat | |||||
| /** | /** | ||||
| * 课程章节目录 | * 课程章节目录 | ||||
| layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) | layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) | ||||
| adapterLesson = AdapterLesson(vm).apply { | adapterLesson = AdapterLesson(vm).apply { | ||||
| onItemClick = onLessonClick | onItemClick = onLessonClick | ||||
| //默认选中位置,默认为0 ,如果学习完成则设置为-1 | |||||
| selectPos = vm.initSelectPosition() | |||||
| } | } | ||||
| adapter = adapterLesson | adapter = adapterLesson | ||||
| } | } | ||||
| private fun listenerLiveBus() { | private fun listenerLiveBus() { | ||||
| //监听数据 | //监听数据 | ||||
| LiveDataBus.withNonSticky<LearnEventData>(AppConstants.EVENT_COURSE).observe(this) { learnEventData -> | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_DATA).observe(this) { learnEventData -> | |||||
| if (learnEventData.subjectId != vm.course.subjectId || learnEventData.courseId != vm.course.courseId) return@observe | if (learnEventData.subjectId != vm.course.subjectId || learnEventData.courseId != vm.course.courseId) return@observe | ||||
| when (learnEventData.actionFlag) { | when (learnEventData.actionFlag) { | ||||
| //课时学前测试结束,传递数据回来更新数据 | //课时学前测试结束,传递数据回来更新数据 | ||||
| AppConstants.DATA_LESSON_BEFORE_TEST_OVER -> { | AppConstants.DATA_LESSON_BEFORE_TEST_OVER -> { | ||||
| // 更新Lesson 更新detail课时学前成绩,错误条目数,测试前错误列表 | // 更新Lesson 更新detail课时学前成绩,错误条目数,测试前错误列表 | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| //课时学前测试结束,开始学习 -> 进入学习界面 | |||||
| AppConstants.ACTION_LESSON_BEFORE_TEST_OVER_START_LEARN -> { | |||||
| startLearn(vm.allLesson[learnEventData.leesonPositionIndex]) | |||||
| } | |||||
| //课时学习结束 | |||||
| //课时学习完成 | |||||
| AppConstants.DATA_LESSON_LEARN_OVER -> { | AppConstants.DATA_LESSON_LEARN_OVER -> { | ||||
| // 更新Lesson 更新detail错误条目数 | |||||
| if (learnEventData.subjectId != vm.course.subjectId || learnEventData.courseId != vm.course.courseId) return@observe | |||||
| //更新Lesson 更新detail错误条目数 | |||||
| adapterLesson.notifyItemChanged(learnEventData.leesonPositionIndex) | adapterLesson.notifyItemChanged(learnEventData.leesonPositionIndex) | ||||
| vm.allLesson[learnEventData.leesonPositionIndex].let { | vm.allLesson[learnEventData.leesonPositionIndex].let { | ||||
| val key = "${it.chapterId}_${it.lessonId}" | val key = "${it.chapterId}_${it.lessonId}" | ||||
| //更新错误数 | |||||
| vm.courseDetail.wrong.put(key, it.errorNumber) | vm.courseDetail.wrong.put(key, it.errorNumber) | ||||
| //更新正确数 | |||||
| vm.courseDetail.right.put(key, it.correctNumber) | |||||
| //添加到错误本中,现在主要用于小游戏取值 | //添加到错误本中,现在主要用于小游戏取值 | ||||
| learnEventData.newErrorMap?.forEach { | learnEventData.newErrorMap?.forEach { | ||||
| vm.courseDetail.temporary_words.put(it.key, "") | vm.courseDetail.temporary_words.put(it.key, "") | ||||
| } | } | ||||
| vm.courseDetail.courseLearnProgress = courseProgress | vm.courseDetail.courseLearnProgress = courseProgress | ||||
| vm.course.courseLearnProgress = courseProgress | vm.course.courseLearnProgress = courseProgress | ||||
| vm.coursePackMainActivityVM.currentCourseProgress.value = courseProgress | |||||
| //项目总进度 | //项目总进度 | ||||
| val subjectProgress = CourseManager.calculateSubjectProgress(vm.course.subjectId, vm.course.coursePackId, | val subjectProgress = CourseManager.calculateSubjectProgress(vm.course.subjectId, vm.course.coursePackId, | ||||
| vm.course.courseId, courseProgress) | vm.course.courseId, courseProgress) | ||||
| vm.courseDetail.after.put(key, it.beforeTestScore) | vm.courseDetail.after.put(key, it.beforeTestScore) | ||||
| } | } | ||||
| } | } | ||||
| //学后测试结束,弹窗动作 | |||||
| } | |||||
| } | |||||
| //监听课时学习的动作 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).observe(this) { learnEventData -> | |||||
| if (learnEventData.subjectId != vm.course.subjectId || learnEventData.courseId != vm.course.courseId) return@observe | |||||
| when (learnEventData.actionFlag) { | |||||
| //课时学前测试结束,开始学习 -> 进入学习界面 | |||||
| AppConstants.ACTION_LESSON_BEFORE_TEST_OVER_START_LEARN -> { | |||||
| startLearn(vm.allLesson[learnEventData.leesonPositionIndex]) | |||||
| } | |||||
| //学后测试结束,弹窗动作 课时重新学习 | |||||
| AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN -> { | AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN -> { | ||||
| //课时学后测试,点击重学 | //课时学后测试,点击重学 | ||||
| // TODO: 2022/4/22 清除当前课时数据,并更新当前课时,后进入学习界面 | // TODO: 2022/4/22 清除当前课时数据,并更新当前课时,后进入学习界面 | ||||
| learnEventData.leesonPositionIndex | |||||
| vm.allLesson[learnEventData.leesonPositionIndex].learnIsOver = false | |||||
| vm.relearnLesson(learnEventData.leesonPositionIndex).observe(this) { | |||||
| //item更新 | |||||
| adapterLesson.notifyItemChanged(learnEventData.leesonPositionIndex) | |||||
| //进行点击,此时当前课时item应该处于显示中,可直接点击 | |||||
| (binding.recyclerView.layoutManager as LinearLayoutManager).findViewByPosition( | |||||
| learnEventData.leesonPositionIndex) | |||||
| ?.findViewById<ConstraintLayout>(R.id.layout_content) | |||||
| ?.performClick() | |||||
| } | |||||
| } | } | ||||
| /**课时学后测试弹窗动作: 再测一次 ,学习结束弹窗: 开始学后测试,共同点:直接进入测试,没有弹窗提示*/ | /**课时学后测试弹窗动作: 再测一次 ,学习结束弹窗: 开始学后测试,共同点:直接进入测试,没有弹窗提示*/ | ||||
| AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN -> { | AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN -> { | ||||
| //学后测试,再测一次 | //学后测试,再测一次 | ||||
| loadLessonAfterTest(vm.allLesson[learnEventData.leesonPositionIndex]) | loadLessonAfterTest(vm.allLesson[learnEventData.leesonPositionIndex]) | ||||
| } | } | ||||
| //下一步 | |||||
| AppConstants.ACTION_LESSON_AFTER_TEST_NEXT -> { | AppConstants.ACTION_LESSON_AFTER_TEST_NEXT -> { | ||||
| //下一课时 or 下一步(提示课程学习完成) | //下一课时 or 下一步(提示课程学习完成) | ||||
| // TODO: 2022/4/22 判断课程是否学习完成,学习完成,显示课程学习完成弹窗,否则进入下一个没有学习完成的课时,进行学习 | |||||
| when(vm.course.courseLearnProgress){ | |||||
| 100.0 -> showCourseOverDialog() | |||||
| when (vm.course.courseLearnProgress) { | |||||
| 100.0 -> { | |||||
| adapterLesson.selectPos = -1 | |||||
| adapterLesson.notifyDataSetChanged() | |||||
| showCourseOverDialog() | |||||
| } | |||||
| else -> { | else -> { | ||||
| var nextLessonPosition = -1 | var nextLessonPosition = -1 | ||||
| //从下一课时开始到最后一个课时 | //从下一课时开始到最后一个课时 | ||||
| for ( i in learnEventData.leesonPositionIndex + 1 until vm.allLesson.size){ | |||||
| for (i in learnEventData.leesonPositionIndex + 1 until vm.allLesson.size) { | |||||
| if (!vm.allLesson[i].learnIsOver) { | if (!vm.allLesson[i].learnIsOver) { | ||||
| nextLessonPosition = i | nextLessonPosition = i | ||||
| break | break | ||||
| val linearLayoutManager = binding.recyclerView.layoutManager as LinearLayoutManager | val linearLayoutManager = binding.recyclerView.layoutManager as LinearLayoutManager | ||||
| val findFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() //第一个可见位置 | val findFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() //第一个可见位置 | ||||
| val findLastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition() //最后一个可见位置 | val findLastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition() //最后一个可见位置 | ||||
| if (nextLessonPosition in findFirstVisibleItemPosition .. findLastVisibleItemPosition){ | |||||
| linearLayoutManager.findViewByPosition(nextLessonPosition)?.findViewById<ConstraintLayout>(R.id.layout_content)?.performClick() | |||||
| }else{ | |||||
| if (nextLessonPosition in findFirstVisibleItemPosition .. findLastVisibleItemPosition) { | |||||
| linearLayoutManager.findViewByPosition(nextLessonPosition) | |||||
| ?.findViewById<ConstraintLayout>(R.id.layout_content) | |||||
| ?.performClick() | |||||
| } else { | |||||
| recycleViewScrollListener.lessonPosition = nextLessonPosition | recycleViewScrollListener.lessonPosition = nextLessonPosition | ||||
| binding.recyclerView.addOnScrollListener(recycleViewScrollListener) | binding.recyclerView.addOnScrollListener(recycleViewScrollListener) | ||||
| binding.recyclerView.smoothScrollToPosition(nextLessonPosition) | binding.recyclerView.smoothScrollToPosition(nextLessonPosition) | ||||
| var lessonPosition = 0 | var lessonPosition = 0 | ||||
| override fun onScrollStateChanged(recyclerView : RecyclerView, newState : Int) { | override fun onScrollStateChanged(recyclerView : RecyclerView, newState : Int) { | ||||
| super.onScrollStateChanged(recyclerView, newState) | super.onScrollStateChanged(recyclerView, newState) | ||||
| if (newState == RecyclerView.SCROLL_STATE_IDLE){ | |||||
| if (newState == RecyclerView.SCROLL_STATE_IDLE) { | |||||
| binding.recyclerView.removeOnScrollListener(this) | binding.recyclerView.removeOnScrollListener(this) | ||||
| val linearLayoutManager = binding.recyclerView.layoutManager as LinearLayoutManager | val linearLayoutManager = binding.recyclerView.layoutManager as LinearLayoutManager | ||||
| linearLayoutManager.findViewByPosition(lessonPosition)?.findViewById<ConstraintLayout>(R.id.layout_content)?.performClick() | |||||
| linearLayoutManager.findViewByPosition(lessonPosition) | |||||
| ?.findViewById<ConstraintLayout>(R.id.layout_content) | |||||
| ?.performClick() | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private val onLessonClick : (v : View, position : Int, lesson : Lesson) -> Unit = { view, position, entity -> | private val onLessonClick : (v : View, position : Int, lesson : Lesson) -> Unit = { view, position, entity -> | ||||
| when (entity.lessonType) { | when (entity.lessonType) { | ||||
| AppConstants.LESSON_TYPE_WORD -> { | AppConstants.LESSON_TYPE_WORD -> { | ||||
| startLearn(entity) | |||||
| /* if (entity.beforeTestScore == AppConstants.NOT_DOING){ //课时学前测试,没有做 | |||||
| //弹窗显示学前测试提示 | |||||
| showLessonBeforeTestStartDialog(entity) | |||||
| }else if (!entity.learnIsOver){ //当前课时未学完,直接开始学习 | |||||
| startLearn(entity) | |||||
| }else if (entity.afterTestScore != AppConstants.NOT_DOING){ | |||||
| loadLessonAfterTest(entity) | |||||
| }else{ //当前课时学习完成的弹窗 | |||||
| showLessonAllOverDialog(entity) | |||||
| }*/ | |||||
| if (entity.beforeTestScore == AppConstants.NOT_DOING) { //课时学前测试,没有做 | |||||
| //弹窗显示学前测试提示 | |||||
| showLessonBeforeTestStartDialog(entity) | |||||
| } else if (!entity.learnIsOver) { //当前课时未学完,直接开始学习 | |||||
| startLearn(entity) | |||||
| } else if (entity.afterTestScore == AppConstants.NOT_DOING) { | |||||
| loadLessonAfterTest(entity) | |||||
| } else { //当前课时学习完成的弹窗 | |||||
| showLessonAllOverDialog(entity) | |||||
| } | |||||
| } | } | ||||
| AppConstants.LESSON_TYPE_SENTENCE -> { | AppConstants.LESSON_TYPE_SENTENCE -> { | ||||
| * @param lesson Lesson 课时 | * @param lesson Lesson 课时 | ||||
| */ | */ | ||||
| private fun startLearn(lesson : Lesson) { | private fun startLearn(lesson : Lesson) { | ||||
| vm.loadLessonLearnData(lesson).observe(this) { | |||||
| DataTransferHolder.instance.putData(value = it) | |||||
| startActivity(LearnWordActivity::class.java) | |||||
| when (lesson.lessonType) { | |||||
| AppConstants.LESSON_TYPE_WORD -> { | |||||
| startLessonLearnForWord(lesson) | |||||
| /* if (entity.beforeTestScore == AppConstants.NOT_DOING){ //课时学前测试,没有做 | |||||
| //弹窗显示学前测试提示 | |||||
| showLessonBeforeTestStartDialog(entity) | |||||
| }else if (!entity.learnIsOver){ //当前课时未学完,直接开始学习 | |||||
| startLearn(entity) | |||||
| }else if (entity.afterTestScore != AppConstants.NOT_DOING){ | |||||
| loadLessonAfterTest(entity) | |||||
| }else{ //当前课时学习完成的弹窗 | |||||
| showLessonAllOverDialog(entity) | |||||
| }*/ | |||||
| } | |||||
| 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 -> { | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /** lesson的学习 lessonType 为 word类型 */ | /** lesson的学习 lessonType 为 word类型 */ | ||||
| private fun startLessonLearnForWord() { | |||||
| private fun startLessonLearnForWord(lesson : Lesson) { | |||||
| vm.loadLessonLearnData(lesson).observe(this) { | |||||
| DataTransferHolder.instance.putData(value = it) | |||||
| startActivity(LearnWordActivity::class.java) | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| * 当前课时学前、学习、学后都完成了的弹窗 | * 当前课时学前、学习、学后都完成了的弹窗 | ||||
| */ | */ | ||||
| private fun showLessonAllOverDialog(lesson : Lesson) { | private fun showLessonAllOverDialog(lesson : Lesson) { | ||||
| LearnDialog.newInstance(LearnDialogBean(AppConstants.DIALOG_TYPE_LESSON_ITEM_OVER).apply { | |||||
| correctNumber = lesson.correctNumber | |||||
| errorNumber = lesson.errorNumber | |||||
| score = lesson.afterTestScore.toInt() | |||||
| }).apply { | |||||
| onDialogListener = { action, dialog -> | |||||
| when (action) { | |||||
| //重学动作 | |||||
| AppConstants.DIALOG_LESSON_RELEARN -> CommonDialog.newInstance( | |||||
| CommonDialogBean(titleText = R.string.lesson_relearn_title, | |||||
| contentText = R.string.lesson_relearn_content, leftText = R.string.cancel, | |||||
| rightText = R.string.sure)).apply { | |||||
| onCommonDialogButtonClickListener = { relearnDialog, isRightClick -> | |||||
| relearnDialog.dismissAllowingStateLoss() | |||||
| if (isRightClick) { | |||||
| dialog.dismissAllowingStateLoss() | |||||
| //发送动作 : 重新学习 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( | |||||
| LearnEventData(lesson.subjectId, lesson.courseId, | |||||
| AppConstants.ACTION_LESSON_AFTER_TEST_RELEARN).apply { | |||||
| leesonPositionIndex = lesson.lessonPositionInList | |||||
| }) | |||||
| } | |||||
| } | |||||
| }.show(childFragmentManager, "lesson_relearn_tip") | |||||
| // 开始学后测试 | |||||
| AppConstants.DIALOG_START_TEST -> { | |||||
| dialog.dismissAllowingStateLoss() | |||||
| //发送动作 : 学后测试 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_ACTION).post( LearnEventData(lesson.subjectId, lesson.courseId, | |||||
| AppConstants.ACTION_LESSON_AFTER_TEST_AGAIN).apply { | |||||
| leesonPositionIndex = lesson.lessonPositionInList | |||||
| }) | |||||
| } | |||||
| } | |||||
| } | |||||
| }.show(childFragmentManager, "learn_over_dialog") | |||||
| } | } | ||||
| /** | /** | ||||
| * 显示课程学习完成的弹窗 | |||||
| * 显示课程学习完成的弹窗,在最后一个课时测试完成的下一步,相当于在课时目录页显示去学后总测试的弹窗 | |||||
| */ | */ | ||||
| private fun showCourseOverDialog() { | private fun showCourseOverDialog() { | ||||
| // TODO: 2022/4/29 课程学习完成弹窗 | |||||
| vm.loadTest(AppConstants.TEST_TYPE_AFTER_TOTAL).observe(this) { | |||||
| val learnDialogBean = LearnDialogBean(AppConstants.DIALOG_TYPE_EXAM_START).apply { | |||||
| examType = AppConstants.TEST_TYPE_AFTER_TOTAL | |||||
| showTimeCount = CourseManager.expectedTestTime(vm.course.courseType, examType, it) | |||||
| } | |||||
| LearnDialog.newInstance(learnDialogBean).apply { | |||||
| onDialogListener = { action, dialog -> | |||||
| dialog.dismissAllowingStateLoss() | |||||
| when (action) { | |||||
| //开始是学后总测试 | |||||
| AppConstants.DIALOG_START_TEST -> {//生成数据 | |||||
| val examData = ExamData(vm.course.subjectId, learnDialogBean.examType, vm.course.courseTitle, | |||||
| vm.course.courseTitle).apply { | |||||
| coursePackId = vm.course.coursePackId | |||||
| coursePackType = vm.course.coursePackType | |||||
| courseId = vm.course.courseId | |||||
| courseType = vm.course.courseType | |||||
| this.testData = it | |||||
| } | |||||
| (parentFragment as CourseMainFragment).startExam(examData) | |||||
| } | |||||
| } | |||||
| } | |||||
| }.show(childFragmentManager, "course_learn_after_test_before") | |||||
| } | |||||
| } | } | ||||
| package com.xkl.cdl.module.m_center_learn.coursechildren | package com.xkl.cdl.module.m_center_learn.coursechildren | ||||
| import android.os.Bundle | import android.os.Bundle | ||||
| import androidx.fragment.app.Fragment | |||||
| import androidx.lifecycle.ViewModel | import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||||
| import com.suliang.common.AppConfig | import com.suliang.common.AppConfig | ||||
| import com.suliang.common.base.fragment.BaseFragmentVM | import com.suliang.common.base.fragment.BaseFragmentVM | ||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.suliang.common.extension.replaceFragment | import com.suliang.common.extension.replaceFragment | ||||
| import com.suliang.common.util.LogUtil | |||||
| import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
| import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
| import com.xkl.cdl.data.DataTransferHolder | import com.xkl.cdl.data.DataTransferHolder | ||||
| } | } | ||||
| } | } | ||||
| /**标记当前显示的fragment*/ | |||||
| private lateinit var currentFragment : Fragment | |||||
| override fun initViewModel() : CourseMainFragmentViewModel { | override fun initViewModel() : CourseMainFragmentViewModel { | ||||
| return ViewModelProvider(this, | |||||
| ViewModelFactory(requireArguments().getInt(AppConfig.INTENT_1)))[CourseMainFragmentViewModel::class.java].apply { | |||||
| val vmmodel = ViewModelProvider(this, ViewModelFactory( | |||||
| requireArguments().getInt(AppConfig.INTENT_1)))[CourseMainFragmentViewModel::class.java].apply { | |||||
| coursePackMainActivityVM = ViewModelProvider(requireActivity())[CoursePackMainActivityViewModel::class.java] | coursePackMainActivityVM = ViewModelProvider(requireActivity())[CoursePackMainActivityViewModel::class.java] | ||||
| // LogUtil.e("CourseMainFragment coursePackMainActivityVM hashCode -> ${coursePackMainActivityVM.hashCode()}") | |||||
| } | } | ||||
| lifecycle.addObserver(vmmodel) | |||||
| return vmmodel | |||||
| } | } | ||||
| override fun initFragment() { | override fun initFragment() { | ||||
| //设置课程 和 需要操作的类型 | //设置课程 和 需要操作的类型 | ||||
| vm.course = vm.coursePackMainActivityVM.coursePack.childrenCourses[vm.courseIndex].apply { | vm.course = vm.coursePackMainActivityVM.coursePack.childrenCourses[vm.courseIndex].apply { | ||||
| vm.dbControlBase = DbControlBase(subjectId, coursePackId,coursePackType, courseId, courseType) | |||||
| vm.dbControlBase = DbControlBase(subjectId, coursePackId, coursePackType, courseId, courseType) | |||||
| } | } | ||||
| //监听动作 总测完成,切换到目录页 | //监听动作 总测完成,切换到目录页 | ||||
| LiveDataBus.withNonSticky<LearnEventData>(AppConstants.EVENT_COURSE).observe(this) { | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_CHANGE_PAGE).observe(this) { | |||||
| if (it.subjectId != vm.course.subjectId || it.courseId != vm.course.courseId) return@observe | if (it.subjectId != vm.course.subjectId || it.courseId != vm.course.courseId) return@observe | ||||
| when (it.actionFlag) { | when (it.actionFlag) { | ||||
| // 学前总测、学后总测 之继续学习 -> 切换到目录页 | // 学前总测、学后总测 之继续学习 -> 切换到目录页 | ||||
| AppConstants.ACTION_COURSE_TEST_START_LEARN -> changeFragment(1) | |||||
| AppConstants.ACTION_COURSE_TEST_START_LEARN -> if (currentFragment !is CourseLessonFragment) changeFragment(1) | |||||
| } | |||||
| } | |||||
| //监听动作 总测完成 | |||||
| LiveEventBus.get<LearnEventData>(AppConstants.EVENT_TOTAL_TEST).observe(this) { | |||||
| if (it.subjectId != vm.course.subjectId || it.courseId != vm.course.courseId) return@observe | |||||
| when (it.actionFlag) { | |||||
| //学前总测结束,传递数据回来更新数据 | //学前总测结束,传递数据回来更新数据 | ||||
| AppConstants.DATA_COURSE_BEFORE_TEST_OVER -> { | AppConstants.DATA_COURSE_BEFORE_TEST_OVER -> { | ||||
| vm.courseDetail.st_before = it.scoreValue.toDouble() //学前总分 | vm.courseDetail.st_before = it.scoreValue.toDouble() //学前总分 | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| //学后总测结束传递数据回来。更新数据 | |||||
| AppConstants.DATA_COURSE_AFTER_TEST_OVER -> vm.courseDetail.st_after = it.scoreValue.toDouble() //学后总分 | |||||
| //学后总测试结束动作: 再测一次 | |||||
| AppConstants.ACTION_COURSE_TEST_AFTER_TOTAL_AGAIN -> { | |||||
| vm.loadTest(AppConstants.TEST_TYPE_AFTER_TOTAL).observe(this) { | |||||
| val examData = ExamData(vm.course.subjectId, AppConstants.TEST_TYPE_AFTER_TOTAL, vm.course.courseTitle, | |||||
| vm.course.courseTitle).apply { | |||||
| coursePackId = vm.course.coursePackId | |||||
| coursePackType = vm.course.coursePackType | |||||
| courseId = vm.course.courseId | |||||
| courseType = vm.course.courseType | |||||
| this.testData = it | |||||
| } | |||||
| startExam(examData) | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| override fun loadData() { | override fun loadData() { | ||||
| LogUtil.e("CourseMainFragment 加载数据 --》 ${vm.courseIndex}") | |||||
| vm.loadMain().observe(this) { | vm.loadMain().observe(this) { | ||||
| changeChildrenFragment() | changeChildrenFragment() | ||||
| } | } | ||||
| * 改变加载的子Fragment | * 改变加载的子Fragment | ||||
| */ | */ | ||||
| private fun changeChildrenFragment() { | 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)) | |||||
| //学习目录 | |||||
| // TODO: 2022/5/5 复习页面加载 | |||||
| vm.courseDetail.run { | vm.courseDetail.run { | ||||
| if (st_before == AppConstants.NOT_DOING) { //学前总测未做 | if (st_before == AppConstants.NOT_DOING) { //学前总测未做 | ||||
| replaceFragment(R.id.layout_root, CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_BEFORE_TOTAL)) | |||||
| currentFragment = CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_BEFORE_TOTAL) | |||||
| replaceFragment(R.id.layout_root, currentFragment) | |||||
| } else if (courseLearnProgress != 100.0) { //学习未完成 | } else if (courseLearnProgress != 100.0) { //学习未完成 | ||||
| replaceFragment(R.id.layout_root, CourseLessonFragment.newInstance()) | |||||
| currentFragment = CourseLessonFragment.newInstance() | |||||
| replaceFragment(R.id.layout_root, currentFragment) | |||||
| } else { //学习完成,学后总测试界面 | } else { //学习完成,学后总测试界面 | ||||
| replaceFragment(R.id.layout_root, CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_AFTER_TOTAL)) | |||||
| currentFragment = CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_AFTER_TOTAL) | |||||
| replaceFragment(R.id.layout_root,currentFragment) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| */ | */ | ||||
| fun changeFragment(position : Int) { | fun changeFragment(position : Int) { | ||||
| when (position) { | when (position) { | ||||
| 1 -> replaceFragment(R.id.layout_root, CourseLessonFragment.newInstance()) | |||||
| 2 -> replaceFragment(R.id.layout_root, CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_AFTER_TOTAL)) | |||||
| 1 -> { | |||||
| currentFragment = CourseLessonFragment.newInstance() | |||||
| replaceFragment(R.id.layout_root,currentFragment ) | |||||
| } | |||||
| 2 -> { | |||||
| currentFragment = CourseTotalTestFragment.newInstance(AppConstants.TEST_TYPE_AFTER_TOTAL) | |||||
| replaceFragment(R.id.layout_root, currentFragment) | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| LearnExamActivity.newInstance(requireContext()) | LearnExamActivity.newInstance(requireContext()) | ||||
| } | } | ||||
| override fun onDestroy() { | |||||
| super.onDestroy() | |||||
| //退出本课程后移除该课程的事件监听 | |||||
| // LiveDataBus.remove(AppConstants.EVENT_COURSE) | |||||
| /** 课程重学方法 */ | |||||
| fun courseRelearn() { | |||||
| //调用重学,重学重新加载数据,重新加载界面 | |||||
| vm.relearnCourse().observe(this){ | |||||
| loadData() | |||||
| } | |||||
| } | } | ||||
| package com.xkl.cdl.module.m_center_learn.coursechildren | package com.xkl.cdl.module.m_center_learn.coursechildren | ||||
| import androidx.lifecycle.LifecycleOwner | |||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| import com.suliang.common.base.viewmodel.BaseViewModel | import com.suliang.common.base.viewmodel.BaseViewModel | ||||
| import com.suliang.common.extension.diskIo2DiskIo | import com.suliang.common.extension.diskIo2DiskIo | ||||
| import com.suliang.common.extension.diskIo2Main | import com.suliang.common.extension.diskIo2Main | ||||
| import com.suliang.common.util.DateUtil | import com.suliang.common.util.DateUtil | ||||
| import com.suliang.common.util.file.FileUtil | |||||
| import com.xkl.cdl.data.AppConstants | |||||
| import com.xkl.cdl.data.bean.LearnWord | import com.xkl.cdl.data.bean.LearnWord | ||||
| import com.xkl.cdl.data.bean.course.Course | import com.xkl.cdl.data.bean.course.Course | ||||
| import com.xkl.cdl.data.bean.course.CourseDetail | import com.xkl.cdl.data.bean.course.CourseDetail | ||||
| import com.xkl.cdl.data.bean.course.ExamBean | import com.xkl.cdl.data.bean.course.ExamBean | ||||
| import com.xkl.cdl.data.bean.course.Lesson | import com.xkl.cdl.data.bean.course.Lesson | ||||
| import com.xkl.cdl.data.bean.intentdata.LearnData | import com.xkl.cdl.data.bean.intentdata.LearnData | ||||
| import com.xkl.cdl.data.manager.CourseManager | |||||
| import com.xkl.cdl.data.manager.db.DBCourseManager | import com.xkl.cdl.data.manager.db.DBCourseManager | ||||
| import com.xkl.cdl.data.manager.db.DbControlBase | import com.xkl.cdl.data.manager.db.DbControlBase | ||||
| import com.xkl.cdl.data.repository.DataRepository | import com.xkl.cdl.data.repository.DataRepository | ||||
| import io.reactivex.rxjava3.core.Observable | import io.reactivex.rxjava3.core.Observable | ||||
| import io.reactivex.rxjava3.functions.BiFunction | import io.reactivex.rxjava3.functions.BiFunction | ||||
| import mqComsumerV1.Struct | import mqComsumerV1.Struct | ||||
| import java.io.File | |||||
| import java.util.* | import java.util.* | ||||
| import kotlin.collections.HashMap | import kotlin.collections.HashMap | ||||
| //获取课程的复习数据 | //获取课程的复习数据 | ||||
| //获取课程的章节数据 | //获取课程的章节数据 | ||||
| fun loadMain() : MutableLiveData<Boolean> { | fun loadMain() : MutableLiveData<Boolean> { | ||||
| // showHideLoading(true) | |||||
| val mutableLiveData = MutableLiveData<Boolean>() | val mutableLiveData = MutableLiveData<Boolean>() | ||||
| Observable.zip(DataRepository.getCourseStatistics().flatMap { | |||||
| Observable.zip(DataRepository.getCourseStatistics(course.subjectId,course.coursePackId,course.courseId).flatMap { | |||||
| courseDetail = it | courseDetail = it | ||||
| course.courseLearnProgress = it.courseLearnProgress | |||||
| return@flatMap DataRepository.getCourseAllLesson(dbControlBase, it) | return@flatMap DataRepository.getCourseAllLesson(dbControlBase, it) | ||||
| }.flatMap { | }.flatMap { | ||||
| allLesson = it | allLesson = it | ||||
| }, | }, | ||||
| DataRepository.getReviewData(), | DataRepository.getReviewData(), | ||||
| BiFunction<HashMap<String, Long>, Array<String>, Boolean> { t1 : HashMap<String, Long>?, t2 : Array<String>? -> | BiFunction<HashMap<String, Long>, Array<String>, Boolean> { t1 : HashMap<String, Long>?, t2 : Array<String>? -> | ||||
| // TODO: 2022/5/5 初始化需要复习的数据 | |||||
| showMoreIsEnable() | |||||
| true | true | ||||
| }).compose(diskIo2Main()).subscribe { | }).compose(diskIo2Main()).subscribe { | ||||
| // showHideLoading(false) | |||||
| mutableLiveData.value = it | mutableLiveData.value = it | ||||
| } | } | ||||
| return mutableLiveData | return mutableLiveData | ||||
| } | } | ||||
| /** 课程包主页上的更多按钮点击是否有效 */ | |||||
| private fun showMoreIsEnable(){ | |||||
| coursePackMainActivityVM.showMoreEnable = courseDetail.st_before != AppConstants.NOT_DOING | |||||
| } | |||||
| /** | /** | ||||
| * 获取课程的测试数据 | * 获取课程的测试数据 | ||||
| * @param testType Int 测试类型 | * @param testType Int 测试类型 | ||||
| .subscribe { | .subscribe { | ||||
| result.value = LearnData(lesson).apply { | result.value = LearnData(lesson).apply { | ||||
| learnWordList = it | learnWordList = it | ||||
| examErrorMap = courseDetail.exam_w_r_list | |||||
| } | } | ||||
| } | } | ||||
| return result | return result | ||||
| }.compose(diskIo2DiskIo()).subscribe() | }.compose(diskIo2DiskIo()).subscribe() | ||||
| } | } | ||||
| /** 初始化默认选中位置 */ | |||||
| fun initSelectPosition() : Int { | |||||
| //没有学习点,默认课程学习课时位置为第一个 | |||||
| var temposition = 0 | |||||
| when{ | |||||
| //学后总测试完成,默认无选中 | |||||
| courseDetail.st_after != AppConstants.NOT_DOING -> temposition = -1 | |||||
| //有学习点 | |||||
| courseDetail.course_learn_point.isNotEmpty() -> { | |||||
| run m@{ | |||||
| allLesson.forEachIndexed { index, lesson -> | |||||
| if ("${lesson.chapterId}_${lesson.lessonId}" == courseDetail.course_learn_point) { | |||||
| temposition = index | |||||
| return@m | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return temposition | |||||
| } | |||||
| /** | |||||
| * 课时重学 | |||||
| * @param lessonPositionIndex Int 重学课时所在位置 | |||||
| */ | |||||
| fun relearnLesson(lessonPositionIndex : Int):MutableLiveData<Boolean> { | |||||
| val result = MutableLiveData<Boolean>() | |||||
| //重学课时后课程的进度 | |||||
| val courseProgress = CourseManager.calculateEnglishCourseProgress(allLesson,true,lessonPositionIndex) | |||||
| //重学课时后项目的总进度 | |||||
| val subjectProgress = CourseManager.calculateSubjectProgressWithCourseLessonRelearn(course.subjectId,course.coursePackId,course.courseId,courseProgress) | |||||
| Observable.fromCallable { | |||||
| // TODO: 2022/5/5 进行数据清除和保存 | |||||
| }.compose(diskIo2DiskIo()).subscribe{ | |||||
| //更新lesson | |||||
| val lesson = allLesson[lessonPositionIndex].apply { | |||||
| errorNumber = 0 | |||||
| correctNumber = 0 | |||||
| learnedIndex = -1 | |||||
| learnIsOver = false | |||||
| afterTestScore = AppConstants.NOT_DOING | |||||
| } | |||||
| //更新courseDetail | |||||
| courseDetail.run { | |||||
| val lessonKey = "${lesson.chapterId}_${lesson.lessonId}" | |||||
| //正确错误数归0,不会清除备忘本数据 | |||||
| right[lessonKey] = 0 | |||||
| wrong[lessonKey] = 0 | |||||
| //移除学后测试成绩 | |||||
| after.remove(lessonKey) | |||||
| //移除章节学习点 | |||||
| lesson_learn_point.remove(lessonKey) | |||||
| val wordStartKey = "${lessonKey}_" | |||||
| //移除总测、课时学前测试的学习错误数据 | |||||
| exam_w_r_list.filterKeys { | |||||
| it.startsWith(wordStartKey) | |||||
| }.forEach{ | |||||
| exam_w_r_list.remove(it.key) | |||||
| } | |||||
| //移除错误本中的记录 | |||||
| temporary_words.filterKeys { it.startsWith(wordStartKey) }.forEach{ | |||||
| temporary_words.remove(it.key) | |||||
| } | |||||
| //更新课程进度 | |||||
| courseLearnProgress = courseProgress | |||||
| course.courseLearnProgress = courseProgress | |||||
| coursePackMainActivityVM.currentCourseProgress.postValue(courseProgress) | |||||
| //更新统计总进度 | |||||
| CourseManager.calculateSubjectProgress(course.subjectId, course.coursePackId, | |||||
| course.courseId, courseProgress) | |||||
| //完成 | |||||
| result.postValue(true) | |||||
| } | |||||
| } | |||||
| return result | |||||
| } | |||||
| /** | |||||
| * 课程重学方法 | |||||
| */ | |||||
| fun relearnCourse(): MutableLiveData<Boolean> { | |||||
| val result = MutableLiveData<Boolean>() | |||||
| //重学需要重新计算进度 | |||||
| val subjectProgress = CourseManager.calculateSubjectProgressWithCourseRelearn(course.subjectId,course.coursePackId,course.courseId) | |||||
| Observable.fromCallable { | |||||
| // TODO: 2022/5/5 调用课程重学 重新请求详情 | |||||
| val file = File(FileUtil.getSaveDirPath("appcache"), "${course.subjectId}_${course.coursePackId}_${course.courseId}") | |||||
| if (file.exists()){ file.delete() } | |||||
| }.compose(diskIo2DiskIo()) | |||||
| .subscribe{ | |||||
| courseDetail.run { | |||||
| courseLearnProgress = 0.0 | |||||
| st_before = AppConstants.NOT_DOING | |||||
| st_after = AppConstants.NOT_DOING | |||||
| before.clear() | |||||
| after.clear() | |||||
| right.clear() | |||||
| wrong.clear() | |||||
| lesson_learn_point.clear() | |||||
| exam_w_r_list.clear() | |||||
| course_learn_point = "" | |||||
| rl += 1 | |||||
| temporary_words.clear() | |||||
| vp.clear() | |||||
| exercise_schedule.clear() | |||||
| } | |||||
| result.postValue(true) | |||||
| } | |||||
| return result | |||||
| } | |||||
| // TODO: 2022/5/6 这里在退出时进行了统计数据缓存保存,在loadMain的时候进行了read缓存 ,后期需要清除 | |||||
| override fun onDestroy(owner : LifecycleOwner) { | |||||
| val objectToBytes = FileUtil.objectToBytes(courseDetail) | |||||
| FileUtil.writeBytesToFile(FileUtil.getSaveDirPath("appcache"),"${course.subjectId}_${course.coursePackId}_${course.courseId}",objectToBytes) | |||||
| super.onDestroy(owner) | |||||
| } | |||||
| } | } |
| import com.xkl.cdl.data.bean.intentdata.ExamData | import com.xkl.cdl.data.bean.intentdata.ExamData | ||||
| import com.xkl.cdl.data.manager.CourseManager | import com.xkl.cdl.data.manager.CourseManager | ||||
| import com.xkl.cdl.databinding.FragmentCourseTotalTestBinding | import com.xkl.cdl.databinding.FragmentCourseTotalTestBinding | ||||
| import com.xkl.cdl.module.m_center_learn.CoursePackMainActivity | |||||
| /** | /** | ||||
| * 课程总测试: 学前总,学后总 | * 课程总测试: 学前总,学后总 | ||||
| * @property totalTestType 测试类型 | * @property totalTestType 测试类型 | ||||
| */ | */ | ||||
| class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, CourseMainFragmentViewModel>() { | class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, CourseMainFragmentViewModel>() { | ||||
| companion object { | companion object { | ||||
| @JvmStatic | @JvmStatic | ||||
| fun newInstance(totalTestType: Int) = CourseTotalTestFragment().apply { | |||||
| fun newInstance(totalTestType : Int) = CourseTotalTestFragment().apply { | |||||
| arguments = Bundle().apply { | arguments = Bundle().apply { | ||||
| putInt(AppConfig.INTENT_1, totalTestType) | putInt(AppConfig.INTENT_1, totalTestType) | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| override fun initViewModel(): CourseMainFragmentViewModel { | |||||
| override fun initViewModel() : CourseMainFragmentViewModel { | |||||
| return ViewModelProvider(requireParentFragment())[CourseMainFragmentViewModel::class.java] | return ViewModelProvider(requireParentFragment())[CourseMainFragmentViewModel::class.java] | ||||
| } | } | ||||
| //由于使用的是与父类相同的loadingEvent,所以将此evnet移除 | //由于使用的是与父类相同的loadingEvent,所以将此evnet移除 | ||||
| vm.loadingEvent.removeObservers(this) | vm.loadingEvent.removeObservers(this) | ||||
| } | } | ||||
| //传递过来的总测类型: 学前,学后 | //传递过来的总测类型: 学前,学后 | ||||
| private var totalTestType = 0 | private var totalTestType = 0 | ||||
| //测试的数据 | //测试的数据 | ||||
| private var testData : List<ExamBean> = emptyList() | private var testData : List<ExamBean> = emptyList() | ||||
| override fun initFragment() { | override fun initFragment() { | ||||
| totalTestType = requireArguments().getInt(AppConfig.INTENT_1) | totalTestType = requireArguments().getInt(AppConfig.INTENT_1) | ||||
| } | } | ||||
| override fun loadData() { | override fun loadData() { | ||||
| vm.loadTest(totalTestType).observe(this){ | |||||
| vm.loadTest(totalTestType).observe(this) { | |||||
| testData = it | testData = it | ||||
| initView() | initView() | ||||
| } | } | ||||
| } | } | ||||
| private fun initView(){ | |||||
| binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType,totalTestType,testData!!) | |||||
| private fun initView() { | |||||
| binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, testData!!) | |||||
| when (totalTestType) { | when (totalTestType) { | ||||
| AppConstants.TEST_TYPE_BEFORE_TOTAL -> { | AppConstants.TEST_TYPE_BEFORE_TOTAL -> { | ||||
| // TODO: 2022/4/21 需要把开始学习给取消了 | // TODO: 2022/4/21 需要把开始学习给取消了 | ||||
| tvTitle.setText(R.string.tips_current_course_learn_over) | tvTitle.setText(R.string.tips_current_course_learn_over) | ||||
| tvMainTip.visibility = View.VISIBLE | tvMainTip.visibility = View.VISIBLE | ||||
| //根据测试成绩处理 | //根据测试成绩处理 | ||||
| vm.courseDetail.st_before = 81.0 | |||||
| vm.courseDetail.st_before.let { | vm.courseDetail.st_before.let { | ||||
| when { | |||||
| it == -1.0 -> { //未测 | |||||
| when (it) { | |||||
| AppConstants.NOT_DOING -> { //未测 | |||||
| tvMainTip.setText(R.string.test_total_after_tip_1) | tvMainTip.setText(R.string.test_total_after_tip_1) | ||||
| button2.run { | button2.run { | ||||
| setText(R.string.test_type_after_total) | setText(R.string.test_type_after_total) | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| 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) | |||||
| } | |||||
| else -> { //有成绩,直接完成 | |||||
| if (it >= AppConstants.TEST_SCORE_LEVEL_2) { | |||||
| tvMainTip.setHtml("你已完成学后总测试,上次得分: <font color=\'#5082E6\'>$it</font>") | |||||
| }else { | |||||
| tvMainTip.setHtml("你已完成学后总测试,上次得分: <font color=\'#F26255\'>$it</font>") | |||||
| } | } | ||||
| } | |||||
| it >= AppConstants.TEST_SCORE_LEVEL_1 -> { //测试通过 | |||||
| tvMainTip.setHtml("你已通过学后总测试,上次得分: <font color=\'#5082E6\'>$it</font>") | |||||
| tvTips.visibility = View.VISIBLE | tvTips.visibility = View.VISIBLE | ||||
| tvCountTip.visibility = View.GONE | tvCountTip.visibility = View.GONE | ||||
| button1.run { | button1.run { | ||||
| } | } | ||||
| } | } | ||||
| tvClearLearnRecord.visibility = View.VISIBLE | tvClearLearnRecord.visibility = View.VISIBLE | ||||
| tvClearLearnRecord.click { | |||||
| (activity as CoursePackMainActivity).showCourseRelearnDialog() | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /**继续学习*/ | /**继续学习*/ | ||||
| private fun continueLearn(view: View) { | |||||
| private fun continueLearn(view : View) { | |||||
| (requireParentFragment() as CourseMainFragment).changeFragment(1) | (requireParentFragment() as CourseMainFragment).changeFragment(1) | ||||
| } | } | ||||
| /** 开始测试 : 生成测试题,跳转到测试 | /** 开始测试 : 生成测试题,跳转到测试 | ||||
| * | * | ||||
| */ | */ | ||||
| private fun startTest(view: View) { | |||||
| private fun startTest(view : View) { | |||||
| //生成数据 | //生成数据 | ||||
| val examData = ExamData(vm.course.subjectId, totalTestType, vm.course.courseTitle, vm.course.courseTitle).apply { | val examData = ExamData(vm.course.subjectId, totalTestType, vm.course.courseTitle, vm.course.courseTitle).apply { | ||||
| coursePackId = vm.course.coursePackId | coursePackId = vm.course.coursePackId | ||||
| } | } | ||||
| (parentFragment as CourseMainFragment).startExam(examData) | (parentFragment as CourseMainFragment).startExam(examData) | ||||
| } | } | ||||
| } | } |
| import android.os.Bundle | import android.os.Bundle | ||||
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
| import com.suliang.common.base.activity.BaseActivityVM | import com.suliang.common.base.activity.BaseActivityVM | ||||
| import com.suliang.common.eventbus.LiveDataBus | |||||
| import com.suliang.common.extension.loadFragment | import com.suliang.common.extension.loadFragment | ||||
| import com.suliang.common.extension.showHideFragment | import com.suliang.common.extension.showHideFragment | ||||
| import com.suliang.common.util.LogUtil | |||||
| import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
| import com.xkl.cdl.databinding.ActivityMainBinding | import com.xkl.cdl.databinding.ActivityMainBinding | ||||
| import com.xkl.cdl.module.m_center_learn.LearnCenterFragment | import com.xkl.cdl.module.m_center_learn.LearnCenterFragment | ||||
| import com.xkl.cdl.module.m_my.MyFragment | import com.xkl.cdl.module.m_my.MyFragment | ||||
| import com.xkl.cdl.module.m_service_center.ServiceCenterFragment | import com.xkl.cdl.module.m_service_center.ServiceCenterFragment | ||||
| import com.xkl.cdl.module.m_statics.StaticsFragment | import com.xkl.cdl.module.m_statics.StaticsFragment | ||||
| import com.xkl.cdl.module.splash.SplashActivity | |||||
| /** | /** | ||||
| * 主界面、控制切换子Fragment | * 主界面、控制切换子Fragment |
| package com.xkl.cdl.util | package com.xkl.cdl.util | ||||
| import com.suliang.common.util.LogUtil | |||||
| import com.xkl.cdl.data.bean.BaseWord | import com.xkl.cdl.data.bean.BaseWord | ||||
| import java.io.* | import java.io.* | ||||
| import java.util.* | import java.util.* | ||||
| currentCorrectMap[key] = true | currentCorrectMap[key] = true | ||||
| } | } | ||||
| if (isLearnFirst) currentIsError = false | if (isLearnFirst) currentIsError = false | ||||
| LogUtil.e("currentCorrectMap--->${currentCorrectMap.size} --> $currentCorrectMap") | |||||
| } | } | ||||
| /** | /** | ||||
| } else if (!isInExamErrorMap(key) && !isInCurrentErrorMap(key)) { //测试中数据的错误 | } else if (!isInExamErrorMap(key) && !isInCurrentErrorMap(key)) { //测试中数据的错误 | ||||
| currentErrorMap[key] = true | currentErrorMap[key] = true | ||||
| } | } | ||||
| LogUtil.e("currentErrorMap --->${currentErrorMap.size} $currentErrorMap") | |||||
| //开始进行数据扩容替换 | //开始进行数据扩容替换 | ||||
| replaceErrorToNull(item) //替换已有错误为空 | replaceErrorToNull(item) //替换已有错误为空 | ||||
| insertErrorWord(item, false) //开始插入 | insertErrorWord(item, false) //开始插入 | ||||
| * @return true在 false不存在 | * @return true在 false不存在 | ||||
| */ | */ | ||||
| fun isInExamErrorMap(key : String) : Boolean { | fun isInExamErrorMap(key : String) : Boolean { | ||||
| return examErrorsMap?.getOrDefault(key, null) ?: false | |||||
| return examErrorsMap?.getOrDefault(key, false) ?: false | |||||
| } | } | ||||
| /** 是否是在学习的错误列表中 */ | /** 是否是在学习的错误列表中 */ |
| android:visibility="gone" | android:visibility="gone" | ||||
| /> | /> | ||||
| <!--所有布局id--> | <!--所有布局id--> | ||||
| <!-- <androidx.constraintlayout.widget.Group--> | |||||
| <!-- android:layout_width="wrap_content"--> | |||||
| <!-- android:layout_height="wrap_content"--> | |||||
| <!-- app:constraint_referenced_ids="iv_close,tv_score,tv_tip,tv_title,--> | |||||
| <!-- tv_lesson_name,tv_count_time,,tv_tip_1,--> | |||||
| <!-- inc_statistics_number,--> | |||||
| <!-- tv_learn_over_tip,--> | |||||
| <!-- tv_learn_over_for_after_count_time,--> | |||||
| <!-- tv_top,tv_top_1,tv_left,vSplit"--> | |||||
| <!-- tools:visibility="gone"--> | |||||
| <!-- />--> | |||||
| <!-- <androidx.constraintlayout.widget.Group | |||||
| android:layout_width="wrap_content" | |||||
| android:layout_height="wrap_content" | |||||
| app:constraint_referenced_ids="iv_close,tv_score,tv_tip,tv_title, | |||||
| tv_lesson_name,tv_count_time,,tv_tip_1, | |||||
| inc_statistics_number, | |||||
| tv_learn_over_tip, | |||||
| tv_learn_over_for_after_count_time, | |||||
| tv_top,tv_top_1,tv_left,vSplit" | |||||
| tools:visibility="gone" | |||||
| /> | |||||
| <androidx.constraintlayout.widget.Group | |||||
| android:layout_width="wrap_content" | |||||
| android:layout_height="wrap_content" | |||||
| app:constraint_referenced_ids="tv_title,tv_tip_1,tv_lesson_name,tv_count_time,tv_left,vSplit" | |||||
| />--> | |||||
| <!-- <!–学前总测试控制显示的布局id–>--> | <!-- <!–学前总测试控制显示的布局id–>--> | ||||
| <!-- <androidx.constraintlayout.widget.Group--> | <!-- <androidx.constraintlayout.widget.Group--> | ||||
| <!-- android:id="@+id/group_total_test"--> | <!-- android:id="@+id/group_total_test"--> | ||||
| /> --> | /> --> | ||||
| <!--课时正常学习结束的布局组 --> | |||||
| <!-- 课时完全结束的点击显示弹窗的布局组 --> | |||||
| <!-- <androidx.constraintlayout.widget.Group--> | <!-- <androidx.constraintlayout.widget.Group--> | ||||
| <!-- android:layout_width="wrap_content"--> | <!-- android:layout_width="wrap_content"--> | ||||
| <!-- android:layout_height="wrap_content"--> | <!-- android:layout_height="wrap_content"--> |
| android:layout_marginStart="28dp" | android:layout_marginStart="28dp" | ||||
| android:layout_marginTop="8dp" | android:layout_marginTop="8dp" | ||||
| android:text="@string/error" | android:text="@string/error" | ||||
| android:textColor="@color/gray_2" | |||||
| android:textColor="@color/main_text_color" | |||||
| android:textSize="@dimen/smallerSize" | android:textSize="@dimen/smallerSize" | ||||
| app:layout_constraintStart_toEndOf="@+id/guideline_1" | app:layout_constraintStart_toEndOf="@+id/guideline_1" | ||||
| app:layout_constraintTop_toTopOf="parent" /> | app:layout_constraintTop_toTopOf="parent" /> |
| <string name="auto_playing">自动播放中···</string> | <string name="auto_playing">自动播放中···</string> | ||||
| <string name="quit_learn_title">你确定要退出本课程的学习吗?</string> | <string name="quit_learn_title">你确定要退出本课程的学习吗?</string> | ||||
| <string name="quit_learn_content">退出后系统将保存你的学习进度</string> | <string name="quit_learn_content">退出后系统将保存你的学习进度</string> | ||||
| <string name="course_relearn_title">你确定要清空本课程的学习记录吗?</string> | |||||
| <string name="course_relearn_content">清空后你的学习记录将不可恢复,请谨慎操作</string> | |||||
| <string name="course_relearn_sure">确认清空</string> | |||||
| </resources> | </resources> |
| grpc_android: "io.grpc:grpc-android:1.27.0", | grpc_android: "io.grpc:grpc-android:1.27.0", | ||||
| grpc_protobuf: "io.grpc:grpc-protobuf:1.27.0", | grpc_protobuf: "io.grpc:grpc-protobuf:1.27.0", | ||||
| grpc_stub: "io.grpc:grpc-stub:1.27.0", | grpc_stub: "io.grpc:grpc-stub:1.27.0", | ||||
| //liveEventBus https://github.com/JeremyLiao/LiveEventBus | |||||
| liveEventBus : "io.github.jeremyliao:live-event-bus-x:1.8.0" | |||||
| ] | ] | ||||
| coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' | coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' | ||||
| //MMKV | //MMKV | ||||
| api customDependencies.MMKV | api customDependencies.MMKV | ||||
| // liveEventBus | |||||
| api customDependencies.liveEventBus | |||||
| * Describe: 打印生命周期的Activity | * Describe: 打印生命周期的Activity | ||||
| */ | */ | ||||
| open class LifecycleLogActivity : AppCompatActivity() { | open class LifecycleLogActivity : AppCompatActivity() { | ||||
| override fun onCreate(savedInstanceState: Bundle?) { | |||||
| super.onCreate(savedInstanceState) | |||||
| LogUtil.e("onCreate()") | |||||
| } | |||||
| override fun onRestart() { | |||||
| super.onRestart() | |||||
| LogUtil.e("onRestart()") | |||||
| } | |||||
| override fun onStart() { | |||||
| super.onStart() | |||||
| LogUtil.e("onStart()") | |||||
| } | |||||
| override fun onResume() { | |||||
| super.onResume() | |||||
| LogUtil.e("onResume()") | |||||
| } | |||||
| override fun onPause() { | |||||
| super.onPause() | |||||
| LogUtil.e("onPause()") | |||||
| } | |||||
| override fun onStop() { | |||||
| super.onStop() | |||||
| LogUtil.e("onStop()") | |||||
| } | |||||
| override fun onDestroy() { | |||||
| super.onDestroy() | |||||
| LogUtil.e("onDestroy()") | |||||
| } | |||||
| override fun onSaveInstanceState(outState: Bundle) { | |||||
| super.onSaveInstanceState(outState) | |||||
| LogUtil.e("onSaveInstanceState()") | |||||
| } | |||||
| override fun onRestoreInstanceState(savedInstanceState: Bundle) { | |||||
| super.onRestoreInstanceState(savedInstanceState) | |||||
| LogUtil.e("onRestoreInstanceState()") | |||||
| } | |||||
| // override fun onCreate(savedInstanceState: Bundle?) { | |||||
| // super.onCreate(savedInstanceState) | |||||
| // LogUtil.e("onCreate()") | |||||
| // } | |||||
| // | |||||
| // override fun onRestart() { | |||||
| // super.onRestart() | |||||
| // LogUtil.e("onRestart()") | |||||
| // } | |||||
| // | |||||
| // override fun onStart() { | |||||
| // super.onStart() | |||||
| // LogUtil.e("onStart()") | |||||
| // } | |||||
| // | |||||
| // override fun onResume() { | |||||
| // super.onResume() | |||||
| // LogUtil.e("onResume()") | |||||
| // } | |||||
| // | |||||
| // override fun onPause() { | |||||
| // super.onPause() | |||||
| // LogUtil.e("onPause()") | |||||
| // } | |||||
| // | |||||
| // override fun onStop() { | |||||
| // super.onStop() | |||||
| // LogUtil.e("onStop()") | |||||
| // } | |||||
| // | |||||
| // override fun onDestroy() { | |||||
| // super.onDestroy() | |||||
| // LogUtil.e("onDestroy()") | |||||
| // } | |||||
| // | |||||
| // override fun onSaveInstanceState(outState: Bundle) { | |||||
| // super.onSaveInstanceState(outState) | |||||
| // LogUtil.e("onSaveInstanceState()") | |||||
| // } | |||||
| // | |||||
| // override fun onRestoreInstanceState(savedInstanceState: Bundle) { | |||||
| // super.onRestoreInstanceState(savedInstanceState) | |||||
| // LogUtil.e("onRestoreInstanceState()") | |||||
| // } | |||||
| } | } |
| override fun initFirst() { | override fun initFirst() { | ||||
| vm = initViewModel() | vm = initViewModel() | ||||
| lifecycle.addObserver(vm) | |||||
| vm.pageEvent.observe(this) { startActivity(it) } | vm.pageEvent.observe(this) { startActivity(it) } | ||||
| vm.toastEvent.observe(this){ showToast(it) } | vm.toastEvent.observe(this){ showToast(it) } | ||||
| vm.loadingEvent.observe(this) { | vm.loadingEvent.observe(this) { |
| open class BaseViewModel : ViewModel(), ViewModelLifecycle, ViewBehavior { | open class BaseViewModel : ViewModel(), ViewModelLifecycle, ViewBehavior { | ||||
| override fun onCreate(owner: LifecycleOwner) { | override fun onCreate(owner: LifecycleOwner) { | ||||
| super.onCreate(owner) | super.onCreate(owner) | ||||
| LogUtil.i("${javaClass.name} onCreate() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onCreate() ") | |||||
| } | } | ||||
| override fun onStart(owner: LifecycleOwner) { | override fun onStart(owner: LifecycleOwner) { | ||||
| super.onStart(owner) | super.onStart(owner) | ||||
| LogUtil.i("${javaClass.name} onStart() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onStart() ") | |||||
| } | } | ||||
| override fun onResume(owner: LifecycleOwner) { | override fun onResume(owner: LifecycleOwner) { | ||||
| super.onResume(owner) | super.onResume(owner) | ||||
| LogUtil.i("${javaClass.name} onResume() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onResume() ") | |||||
| } | } | ||||
| override fun onPause(owner: LifecycleOwner) { | override fun onPause(owner: LifecycleOwner) { | ||||
| super.onPause(owner) | super.onPause(owner) | ||||
| LogUtil.i("${javaClass.name} onPause() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onPause() ") | |||||
| } | } | ||||
| override fun onStop(owner: LifecycleOwner) { | override fun onStop(owner: LifecycleOwner) { | ||||
| super.onStop(owner) | super.onStop(owner) | ||||
| LogUtil.i("${javaClass.name} onStop() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onStop() ") | |||||
| } | } | ||||
| override fun onDestroy(owner: LifecycleOwner) { | override fun onDestroy(owner: LifecycleOwner) { | ||||
| super.onDestroy(owner) | super.onDestroy(owner) | ||||
| LogUtil.i("${javaClass.name} onDestroy() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onDestroy() ") | |||||
| } | } | ||||
| override fun onCleared() { | override fun onCleared() { | ||||
| super.onCleared() | super.onCleared() | ||||
| LogUtil.i("${javaClass.name} onCleared() ") | |||||
| LogUtil.i("${javaClass.name}_${hashCode()} onCleared() ") | |||||
| } | } | ||||
| package com.suliang.common.eventbus | package com.suliang.common.eventbus | ||||
| import android.os.Looper | |||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
| /** | /** | ||||
| * author suliang | * author suliang | ||||
| * create 2022/3/15 10:01 | * create 2022/3/15 10:01 | ||||
| * Describe: 事件总线,这条总线把任何类中的数据直接传递到activity 或是 fragment 上 | * Describe: 事件总线,这条总线把任何类中的数据直接传递到activity 或是 fragment 上 | ||||
| * https://blog.csdn.net/lp131452064/article/details/82736296 | |||||
| * https://juejin.cn/post/6844903768459329544 | |||||
| */ | */ | ||||
| @Deprecated("this class is deprecated" ,replaceWith = ReplaceWith("LiveEventBus"),level = DeprecationLevel.ERROR) | |||||
| object LiveDataBus { | object LiveDataBus { | ||||
| private val bus = mutableMapOf<String, MutableLiveData<Any>>() | |||||
| /** | |||||
| * 发送事件 | |||||
| * @param key String | |||||
| * @param value T | |||||
| * @param isSticky 是否是粘性事件,默认为false | |||||
| */ | |||||
| fun <T : Any> postEvent(key:String, value:T, isSticky : Boolean = false){ | |||||
| if (Looper.getMainLooper().thread == Thread.currentThread()){ | |||||
| subscribeEvent<T>(key,isSticky).value = value | |||||
| }else{ | |||||
| subscribeEvent<T>(key,isSticky).postValue(value) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 订阅事件 | |||||
| * @param key bus中的key | |||||
| * @param isSticky 是否是粘性事件,默认为false | |||||
| */ | |||||
| fun <T:Any> subscribeEvent(key:String,isSticky:Boolean = false): MutableLiveData<T> { | |||||
| if (!bus.containsKey(key)){ | |||||
| if (isSticky){ | |||||
| bus[key] = MutableLiveData() | |||||
| }else{ | |||||
| bus[key] = NonStickyMutableLivedata() | |||||
| } | |||||
| } | |||||
| return bus[key] as MutableLiveData<T> | |||||
| } | |||||
| fun remove(key : String) { | |||||
| bus.remove(key) | |||||
| } | |||||
| fun clearAll() { | |||||
| bus.clear() | |||||
| } | |||||
| // @SuppressWarnings("UNCHECKED_CAST") | |||||
| // @Synchronized | |||||
| // fun <T> with(key : String) : MutableLiveData<T> { | |||||
| // if (!bus.containsKey(key)) { | |||||
| // bus[key] = MutableLiveData() | |||||
| // } | |||||
| // return bus[key] as MutableLiveData<T> | |||||
| // } | |||||
| // | |||||
| // @SuppressWarnings("UNCHECKED_CAST") | |||||
| // @Synchronized | |||||
| // fun <T> withNonSticky(key : String) : MutableLiveData<T> { | |||||
| // if (!bus.containsKey(key)) { | |||||
| // bus[key] = NonStickyMutableLivedata() | |||||
| // } | |||||
| // return bus[key] as MutableLiveData<T> | |||||
| // } | |||||
| private val bus = mutableMapOf<String,MutableLiveData<Any>>() | |||||
| // /** | // /** | ||||
| // * 注册订阅者 | // * 注册订阅者 | ||||
| //java使用传入泛型class, kotlin使用可直接传入泛型,不需要class类型 | //java使用传入泛型class, kotlin使用可直接传入泛型,不需要class类型 | ||||
| @SuppressWarnings("UNCHECKED_CAST") | |||||
| @Synchronized | |||||
| fun <T> with(key:String) : MutableLiveData<T>{ | |||||
| if (!bus.containsKey(key)){ | |||||
| bus[key] = MutableLiveData() | |||||
| } | |||||
| return bus[key] as MutableLiveData<T> | |||||
| } | |||||
| @SuppressWarnings("UNCHECKED_CAST") | |||||
| @Synchronized | |||||
| fun <T> withNonSticky(key:String) : MutableLiveData<T>{ | |||||
| if (!bus.containsKey(key)){ | |||||
| bus[key] = NonStickyMutableLiveData() | |||||
| } | |||||
| return bus[key] as MutableLiveData<T> | |||||
| } | |||||
| @SuppressWarnings("UNCHECKED_CAST") | |||||
| @Synchronized | |||||
| fun <T> with(key:String,type: Class<T>) : MutableLiveData<T>{ | |||||
| if (!bus.containsKey(key)){ | |||||
| bus[key] = MutableLiveData() | |||||
| } | |||||
| return bus[key] as MutableLiveData<T> | |||||
| } | |||||
| @SuppressWarnings("UNCHECKED_CAST") | |||||
| @Synchronized | |||||
| fun <T> withNonSticky(key:String,type: Class<T>) : MutableLiveData<T>{ | |||||
| if (!bus.containsKey(key)){ | |||||
| bus[key] = NonStickyMutableLiveData() | |||||
| } | |||||
| return bus[key] as MutableLiveData<T> | |||||
| } | |||||
| fun remove(key:String){ | |||||
| bus.remove(key) | |||||
| } | |||||
| fun clearAll(){ | |||||
| bus.clear() | |||||
| } | |||||
| // @SuppressWarnings("UNCHECKED_CAST") | |||||
| // @Synchronized | |||||
| // fun <T> with(key:String,type: Class<T>) : MutableLiveData<T>{ | |||||
| // if (!bus.containsKey(key)){ | |||||
| // bus[key] = MutableLiveData() | |||||
| // } | |||||
| // return bus[key] as MutableLiveData<T> | |||||
| // } | |||||
| // @SuppressWarnings("UNCHECKED_CAST") | |||||
| // @Synchronized | |||||
| // fun <T> withNonSticky(key:String,type: Class<T>) : MutableLiveData<T>{ | |||||
| // if (!bus.containsKey(key)){ | |||||
| // bus[key] = NonStickyMutableLiveData() | |||||
| // } | |||||
| // return bus[key] as MutableLiveData<T> | |||||
| // } | |||||
| } | } |
| * author suliang | * author suliang | ||||
| * create 2022/3/15 10:51 | * create 2022/3/15 10:51 | ||||
| * Describe: 非粘性LiveData ,需要先设置监听再发送数据,即后注册的监听收不到以前的监听 | * Describe: 非粘性LiveData ,需要先设置监听再发送数据,即后注册的监听收不到以前的监听 | ||||
| * 事件总线的LiveData 非粘性事件传false(刚注册时如果有事件则不发送) 粘性事件传true | |||||
| * @param isSticky false非粘性事件 true粘性事件 | |||||
| */ | */ | ||||
| class NonStickyMutableLiveData<T> : MutableLiveData<T>() { | |||||
| // private var stickFlag : Boolean = false | |||||
| internal class NonStickyMutableLivedata<T> : MutableLiveData<T>() { | |||||
| // override fun observe(owner : LifecycleOwner, observer : Observer<in T>) { | |||||
| // super.observe(owner, ObserverWrapper<T>(observer)) | |||||
| // } | |||||
| // | |||||
| // class ObserverWrapper<T>(var observer:Observer<in T>) : Observer<T> { | |||||
| // var isSticky = false | |||||
| // override fun onChanged(t : T) { | |||||
| // if (isSticky){ | |||||
| // observer.onChanged(t) | |||||
| // }else{ | |||||
| // isSticky = true | |||||
| // } | |||||
| // } | |||||
| // } | |||||
| override fun observe(owner: LifecycleOwner, observer: Observer<in T>) { | override fun observe(owner: LifecycleOwner, observer: Observer<in T>) { | ||||
| super.observe(owner, observer) | super.observe(owner, observer) | ||||
| hook(observer) | hook(observer) | ||||
| // if (!stickFlag){ | |||||
| // hook(observer) | |||||
| // stickFlag = true | |||||
| // } | |||||
| } | } | ||||
| private fun hook(observer: Observer<in T>) = try { | |||||
| override fun removeObserver(observer : Observer<in T>) { | |||||
| super.removeObserver(observer) | |||||
| } | |||||
| private fun hook(observer : Observer<in T>) = try { | |||||
| //得到 mLastVersion | //得到 mLastVersion | ||||
| //获取到LiveData的类中的mObserver对象 | //获取到LiveData的类中的mObserver对象 | ||||
| // SafeIterableMap<Observer<? super T> , ObserverWrapper> mObservers | // SafeIterableMap<Observer<? super T> , ObserverWrapper> mObservers | ||||
| //得到map对应的class对象 | //得到map对应的class对象 | ||||
| val mObserversClass = mObserVersObject.javaClass | val mObserversClass = mObserVersObject.javaClass | ||||
| //获取到mObservers对象的get方法 | //获取到mObservers对象的get方法 | ||||
| val get:Method = mObserversClass.getDeclaredMethod("get", Any::class.java) | |||||
| val get : Method = mObserversClass.getDeclaredMethod("get", Any::class.java) | |||||
| get.isAccessible = true | get.isAccessible = true | ||||
| //执行get方法,获取到对象 | //执行get方法,获取到对象 | ||||
| val invokeEntry = get.invoke(mObserVersObject, observer) | val invokeEntry = get.invoke(mObserVersObject, observer) | ||||
| val observerWrapper = if (invokeEntry is Map.Entry<*, *>) { | val observerWrapper = if (invokeEntry is Map.Entry<*, *>) { | ||||
| invokeEntry.value | invokeEntry.value | ||||
| } else throw NullPointerException("observerWrapper is null") | } else throw NullPointerException("observerWrapper is null") | ||||
| //得到observerWrapper的对象,编译擦除问题会引起多态冲突,所以用getSupperClass | //得到observerWrapper的对象,编译擦除问题会引起多态冲突,所以用getSupperClass | ||||
| //getClass 返回对应的当前正在运行是的类所对应的 | //getClass 返回对应的当前正在运行是的类所对应的 | ||||
| val mLastVersion = observerWrapper!!::class.java.superclass.getDeclaredField("mLastVersion") | val mLastVersion = observerWrapper!!::class.java.superclass.getDeclaredField("mLastVersion") | ||||
| mVersion.isAccessible = true | mVersion.isAccessible = true | ||||
| //把mVersion数据填入到mLastVersion中 | //把mVersion数据填入到mLastVersion中 | ||||
| val mVersionValue = mVersion.get(this) | val mVersionValue = mVersion.get(this) | ||||
| mLastVersion.set(observerWrapper,mVersionValue) | |||||
| }catch (e: Exception){ | |||||
| mLastVersion.set(observerWrapper, mVersionValue) | |||||
| } catch (e : Exception) { | |||||
| e.printStackTrace() | e.printStackTrace() | ||||
| } | } | ||||
| } | } |
| } | } | ||||
| this.setOnTouchListener{ view , motionEvent -> | this.setOnTouchListener{ view , motionEvent -> | ||||
| when(motionEvent.action){ | when(motionEvent.action){ | ||||
| MotionEvent.ACTION_DOWN -> view.alpha = 0.7f | |||||
| MotionEvent.ACTION_DOWN -> view.alpha = 0.8f | |||||
| MotionEvent.ACTION_UP -> view.alpha = 1f | MotionEvent.ACTION_UP -> view.alpha = 1f | ||||
| else -> view.alpha = 1f | else -> view.alpha = 1f | ||||
| } | } |
| closeStream(out) | closeStream(out) | ||||
| return result | return result | ||||
| } | } | ||||
| /*** | |||||
| * 从对象获取字节数组 | |||||
| * @param data Any 对象,需要实现序列化 | |||||
| * @return ByteArray 字节数组 | |||||
| * @throws Exception | |||||
| */ | |||||
| @Throws(Exception::class) | @Throws(Exception::class) | ||||
| fun objectToBytes(data: Any): ByteArray { | |||||
| fun objectToBytes(data: Serializable): ByteArray { | |||||
| var oos: ObjectOutputStream? = null | var oos: ObjectOutputStream? = null | ||||
| return try { | return try { | ||||
| val bos = ByteArrayOutputStream() | val bos = ByteArrayOutputStream() | ||||
| oos?.close() | oos?.close() | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * 从字节数组获取对象 | |||||
| * @param data ByteArray | |||||
| * @return Any | |||||
| */ | |||||
| fun bytesToObject(data:ByteArray): Any{ | |||||
| return ObjectInputStream(ByteArrayInputStream(data)).readObject() | |||||
| } | |||||
| /** | /** | ||||
| * 获取文件大小 | * 获取文件大小 |
| <resources> | <resources> | ||||
| <!-- TODO: Remove or change this placeholder text --> | |||||
| <string name="hello_blank_fragment">Hello blank fragment</string> | |||||
| </resources> | </resources> |