| @@ -110,6 +110,7 @@ object AppConstants { | |||
| /** 未做测试,没有做等用-1表示的内容 */ | |||
| const val NOT_DOING = -1.0 | |||
| const val DOING_OVER = 100.0 | |||
| /** 测试通过:>80 < 90 继续加油 <80 悲伤 */ | |||
| const val TEST_SCORE_LEVEL_1 = 80 | |||
| @@ -1,5 +1,6 @@ | |||
| package com.xkl.cdl.data.bean | |||
| import androidx.annotation.ColorRes | |||
| import com.xkl.cdl.R | |||
| import java.io.Serializable | |||
| @@ -46,7 +47,8 @@ open class BaseWord(val subjectId: Int, | |||
| var repeatNum: Int = 0 | |||
| /**显示颜色*/ | |||
| var showColor: Int = 0 | |||
| @ColorRes | |||
| var showColor:Int = 0 | |||
| get() { | |||
| return when (repeatNum) { | |||
| 0 -> R.color.num0 | |||
| @@ -72,9 +72,9 @@ object BindingAdapter { | |||
| learnProgress == 0.0 -> view.resources.getString(R.string.start) | |||
| learnProgress < 0.1 -> "0.1%" | |||
| learnProgress < 100 -> { | |||
| DecimalFormat("#.#%").apply { | |||
| DecimalFormat("#.##").apply { | |||
| roundingMode = RoundingMode.DOWN | |||
| }.format(BigDecimal(learnProgress)) | |||
| }.format(learnProgress) + "%" | |||
| } | |||
| else -> "100%" | |||
| } | |||
| @@ -25,21 +25,7 @@ object CourseManager { | |||
| val mSortInfoList = hashMapOf<Int, MutableList<AppApi.CourseSortedInfo.Builder>>() | |||
| /** | |||
| * 获取对应项目的课程数量 | |||
| * @param subjectId Int 项目 | |||
| * @return Int 课程数量 | |||
| */ | |||
| fun getSubjectForCourseSize(subjectId : Int) : Int { | |||
| return subjectWithCoursePackMap[subjectId]?.let { | |||
| var count = 0 | |||
| it.forEach { coursePack -> | |||
| count += coursePack.childrenCourses?.size ?: 0 | |||
| } | |||
| count | |||
| } ?: 0 | |||
| } | |||
| /** | |||
| * 搜索项目下的课程包 | |||
| * @param subjectId Int 项目id | |||
| @@ -107,7 +93,7 @@ object CourseManager { | |||
| return when { | |||
| progress == 0.0 -> "0" | |||
| progress < 0.1 -> "0.1" | |||
| progress < 100 -> DecimalFormat("#.#").apply { | |||
| progress < 100 -> DecimalFormat("#.##").apply { | |||
| //直接舍弃 | |||
| roundingMode = RoundingMode.DOWN | |||
| }.format(BigDecimal(progress)) | |||
| @@ -282,10 +268,7 @@ object CourseManager { | |||
| if (totalProgress == 0.0 ) return totalProgress | |||
| var totalCourseSize = 0 | |||
| subjectWithCoursePackMap.get(subjectId)?.forEach { | |||
| totalCourseSize += it.childrenCourses.size | |||
| } | |||
| val totalCourseSize = getSubjectForCourseSize(subjectId) | |||
| if (totalCourseSize == 0) return 0.0 | |||
| return totalProgress / totalCourseSize | |||
| } | |||
| @@ -313,11 +296,24 @@ object CourseManager { | |||
| if (totalProgress == 0.0 ) return totalProgress | |||
| var totalCourseSize = 0 | |||
| subjectWithCoursePackMap.get(subjectId)?.forEach { | |||
| totalCourseSize += it.childrenCourses.size | |||
| } | |||
| val totalCourseSize = getSubjectForCourseSize(subjectId) | |||
| if (totalCourseSize == 0) return 0.0 | |||
| return totalProgress / totalCourseSize | |||
| } | |||
| /** | |||
| * 获取对应项目的课程数量 | |||
| * @param subjectId Int 项目 | |||
| * @return Int 课程数量 | |||
| */ | |||
| private fun getSubjectForCourseSize(subjectId : Int) : Int { | |||
| return subjectWithCoursePackMap[subjectId]?.let { | |||
| var count = 0 | |||
| it.forEach { coursePack -> | |||
| count += coursePack.childrenCourses.size ?: 0 | |||
| } | |||
| count | |||
| } ?: 0 | |||
| } | |||
| } | |||
| @@ -31,7 +31,7 @@ object DBCourseManager { | |||
| private const val NORMAL = "XKL_COURSE_DATA_KEY" | |||
| private const val SPOKEN = "XKL_SPOKEN_COURSE_DATA_KEY" | |||
| private const val COMPOSITION = "XKL_LOCAL_COMPOSITION_DATA_KEY" | |||
| private const val LITERACY = "XKL_LOCAL_CHINESE_COURSE_KEY" | |||
| private const val LITERACY_PINYING = "XKL_LOCAL_CHINESE_COURSE_KEY" | |||
| private var mDataBase : SQLiteDatabase? = null | |||
| private fun open(base : DbControlBase) { | |||
| @@ -45,7 +45,7 @@ object DBCourseManager { | |||
| val p = when (base.courseType) { | |||
| AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION | |||
| AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> SPOKEN | |||
| AppConstants.COURSE_TYPE_CHINESE_LITERACY -> LITERACY | |||
| AppConstants.COURSE_TYPE_CHINESE_LITERACY,AppConstants.COURSE_TYPE_CHINESE_PINYIN -> LITERACY_PINYING | |||
| else -> NORMAL | |||
| } | |||
| mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path, | |||
| @@ -444,6 +444,7 @@ object DBCourseManager { | |||
| when (dbcb.courseType) { | |||
| AppConstants.COURSE_TYPE_CHINESE_LITERACY -> { | |||
| word = getString(getColumnIndex("word1")) | |||
| literacyIspolyphone = getInt(getColumnIndex("polyphone")) > 0 | |||
| phonetic_cn = getString(getColumnIndex("phonetic")) | |||
| } | |||
| @@ -17,6 +17,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator | |||
| import com.jeremyliao.liveeventbus.LiveEventBus | |||
| import com.suliang.common.base.activity.BaseActivityVM | |||
| import com.suliang.common.extension.click | |||
| import com.suliang.common.extension.setHtml | |||
| import com.suliang.common.util.DateUtil | |||
| import com.suliang.common.util.DrawableUti | |||
| import com.suliang.common.util.image.ImageLoader | |||
| @@ -422,8 +423,11 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
| //单词内容 | |||
| bindingWord.incWord.tvWord.apply { | |||
| //识字需单独处理 | |||
| text = if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY) ViewUtil.literacyToHtmlWord( | |||
| learnWord.word, learnWord.showColor) else learnWord.word | |||
| if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY){ | |||
| setHtml(ViewUtil.literacyToHtmlWord(learnWord.word, learnWord.showColor)) | |||
| } else { | |||
| text = learnWord.word | |||
| } | |||
| setTextColor(ContextCompat.getColor(this@LearnWordActivity, learnWord.showColor)) //单词显示颜色 | |||
| } | |||
| //音标 | |||
| @@ -457,8 +461,11 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
| //单词内容 | |||
| bindingWord.incWord.tvWord.apply { | |||
| //识字需单独处理 | |||
| text = if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY) ViewUtil.literacyToHtmlWord( | |||
| learnWord.word, learnWord.showColor) else learnWord.word | |||
| if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY) { | |||
| setHtml(ViewUtil.literacyToHtmlWord(learnWord.word, learnWord.showColor)) | |||
| } else { | |||
| text = learnWord.word | |||
| } | |||
| setTextColor(ContextCompat.getColor(this@LearnWordActivity, learnWord.showColor)) //单词显示颜色 | |||
| } | |||
| //音标 | |||
| @@ -552,7 +559,7 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
| binding.incControlButton.tvCenter.visibility = View.VISIBLE | |||
| //音标,显示重读 | |||
| when(vm.learnData.lesson.coursePackType){ | |||
| AppConstants.COURSEPACK_TYPE_ENGLISH_SOUNDMARK -> View.VISIBLE | |||
| AppConstants.COURSEPACK_TYPE_ENGLISH_SOUNDMARK ->binding.incControlButton.tvRight.visibility = View.VISIBLE | |||
| } | |||
| } | |||
| @@ -176,11 +176,13 @@ class CourseMainFragmentViewModel(val courseIndex : Int) : BaseViewModel() { | |||
| when { | |||
| //学后总测试完成,默认无选中 | |||
| courseDetail.st_after != AppConstants.NOT_DOING -> temposition = -1 | |||
| //进度100 | |||
| courseDetail.courseLearnProgress == AppConstants.DOING_OVER -> temposition = -1 | |||
| //有学习点 | |||
| courseDetail.course_learn_point.isNotEmpty() -> { | |||
| run m@{ | |||
| allLesson.forEachIndexed { index, lesson -> | |||
| if ("${lesson.chapterId}_${lesson.lessonId}" == courseDetail.course_learn_point) { | |||
| if (courseDetail.course_learn_point.startsWith("${lesson.chapterId}_${lesson.lessonId}_")) { | |||
| temposition = index | |||
| return@m | |||
| } | |||
| @@ -52,11 +52,34 @@ class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, C | |||
| } | |||
| override fun loadData() { | |||
| when (totalTestType) { | |||
| AppConstants.TEST_TYPE_BEFORE_TOTAL -> vm.loadTest(totalTestType).observe(this) { | |||
| initTotalBeforeView(it) | |||
| vm.loadTest(totalTestType).observe(this) { | |||
| binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, it) | |||
| when (totalTestType) { | |||
| AppConstants.TEST_TYPE_BEFORE_TOTAL -> initTotalBeforeView(it) | |||
| AppConstants.TEST_TYPE_AFTER_TOTAL -> initTotalAfterView() | |||
| } | |||
| } | |||
| } | |||
| /** 学前测试初始 */ | |||
| private fun initTotalBeforeView(testData : List<ExamBean>) { | |||
| //学前总测 | |||
| binding.run { | |||
| tvTitle.setText(R.string.test_total_before_title) | |||
| // button1.run { | |||
| // setText(R.string.start_learn) | |||
| // visibility = View.VISIBLE | |||
| // click { | |||
| // continueLearn(it) | |||
| // } | |||
| // } | |||
| //按钮初始 | |||
| button2.run { | |||
| setText(R.string.start_test) | |||
| click { view -> | |||
| startTest(view) | |||
| } | |||
| } | |||
| AppConstants.TEST_TYPE_AFTER_TOTAL -> initTotalAfterView() | |||
| } | |||
| } | |||
| @@ -67,10 +90,17 @@ class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, C | |||
| tvTitle.setText(R.string.tips_current_course_learn_over) | |||
| tvMainTip.visibility = View.VISIBLE | |||
| //根据测试成绩处理 | |||
| vm.courseDetail.st_before.let { | |||
| vm.courseDetail.st_after.let { | |||
| when (it) { | |||
| AppConstants.NOT_DOING -> { //未测 | |||
| tvMainTip.setText(R.string.test_total_after_tip_1) | |||
| button1.run { | |||
| visibility = View.VISIBLE | |||
| setText(R.string.start_learn) | |||
| click { | |||
| continueLearn(it) | |||
| } | |||
| } | |||
| button2.run { | |||
| setText(R.string.test_type_after_total) | |||
| click { view -> | |||
| @@ -110,29 +140,7 @@ class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, C | |||
| } | |||
| } | |||
| /** 学前测试初始 */ | |||
| private fun initTotalBeforeView(testData : List<ExamBean>) { | |||
| // TODO: 2022/4/21 需要把开始学习给取消了 | |||
| binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, testData) | |||
| binding.button1.visibility = View.VISIBLE | |||
| //学前总测 | |||
| binding.run { | |||
| tvTitle.setText(R.string.test_total_before_title) | |||
| button1.run { | |||
| setText(R.string.start_learn) | |||
| click { | |||
| continueLearn(it) | |||
| } | |||
| } | |||
| //按钮初始 | |||
| button2.run { | |||
| setText(R.string.start_test) | |||
| click { view -> | |||
| startTest(view) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /**继续学习*/ | |||
| private fun continueLearn(view : View) { | |||
| @@ -52,6 +52,7 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(){ | |||
| AppExecutors.io.execute { | |||
| //读取课程数据 | |||
| // TODO: 2022/5/16 读取课程的sort信息进行保存,针对作文课程,同时需要设置其课程包的进度 | |||
| // TODO: 2022/3/22 读取当前app绑定的课程数据, | |||
| DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615,516,411") | |||
| //复制课程的数据库到对应位置 | |||
| @@ -4,6 +4,9 @@ import android.text.Html | |||
| import android.text.Spanned | |||
| import android.widget.TextView | |||
| import androidx.annotation.ColorInt | |||
| import androidx.annotation.ColorRes | |||
| import androidx.core.content.ContextCompat | |||
| import com.suliang.common.util.AppGlobals | |||
| import com.suliang.common.util.ColorUtil | |||
| import com.suliang.common.util.os.ScreenUtil | |||
| import java.util.regex.Pattern | |||
| @@ -47,10 +50,10 @@ class ViewUtil { | |||
| * @param colorId 处理的颜色id color.xml | |||
| * @return Spanned 你好 你为大写 | |||
| */ | |||
| fun literacyToHtmlWord(word : String, @ColorInt colorId : Int) : Spanned { | |||
| fun literacyToHtmlWord(word : String, @ColorRes colorId : Int) : String { | |||
| val m = Pattern.compile("\\([\u4e00-\u9fa5]\\)").matcher(word) | |||
| val builder = StringBuffer() | |||
| val color : String = ColorUtil.getHexWebString(colorId) | |||
| val color : String = ColorUtil.getHexWebString(ContextCompat.getColor(AppGlobals.application,colorId)) | |||
| var isFind = false | |||
| var previousEndPosition = 0 //下次循环开始的位置 | |||
| while (m.find()) { | |||
| @@ -73,8 +76,7 @@ class ViewUtil { | |||
| } else { | |||
| builder.append("<font color=\"").append(color).append("\">").append(word).append("</font>") | |||
| } | |||
| println(builder.toString()) | |||
| return Html.fromHtml(builder.toString()) | |||
| return builder.toString() | |||
| } | |||
| /** | |||
| @@ -100,6 +100,8 @@ | |||
| app:layout_constraintTop_toTopOf="@+id/button_2" | |||
| app:strokeColor="@color/theme_color" | |||
| app:strokeWidth="@dimen/line_height" | |||
| tools:text="@string/start_learn" | |||
| android:visibility="gone" | |||
| /> | |||
| <Button | |||
| @@ -1,5 +1,7 @@ | |||
| package com.suliang.common.util | |||
| import androidx.annotation.ColorInt | |||
| /** | |||
| * author suliang | |||
| * create 2022/4/25 16:29 | |||
| @@ -10,12 +12,12 @@ class ColorUtil { | |||
| companion object{ | |||
| /** | |||
| * 把一个int颜色值转换成String | |||
| * @param color | |||
| * @param color 非直接资源id,而是转换好的资源,getColor or Color.parse | |||
| * @return | |||
| */ | |||
| fun getHexWebString(color : Int) : String { | |||
| fun getHexWebString(@ColorInt color : Int) : String { | |||
| var s = "#" | |||
| val colorStr = color and -0x1000000 or (color and 0x00ff0000) or (color and 0x0000ff00) or (color and 0x000000ff) | |||
| val colorStr = (color and 0xff000000.toInt()) or (color and 0x00ff0000) or (color and 0x0000ff00) or (color and 0x000000ff) | |||
| var s1 = Integer.toHexString(colorStr) | |||
| s1 = s1.substring(2, s1.length) | |||
| s = s + s1 | |||