<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout-v23/include_main_learn_center_course_type_title.xml" value="0.4963768115942029" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout-v23/include_main_learn_center_course_type_title.xml" value="0.4963768115942029" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/_xpopup_ext_time_picker.xml" value="0.23632218844984804" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/_xpopup_ext_time_picker.xml" value="0.23632218844984804" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_course_main.xml" value="0.33" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_course_main.xml" value="0.33" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_course_statistics_detail.xml" value="0.33" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_exam_learn_spell.xml" value="0.47690217391304346" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_exam_learn_spell.xml" value="0.47690217391304346" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_base.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_base.xml" value="0.4979166666666667" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_creading.xml" value="0.4304093567251462" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_creading.xml" value="0.4304093567251462" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_memo_list_detail.xml" value="0.3621621621621622" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_memo_list_detail.xml" value="0.3621621621621622" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_memo_test.xml" value="0.25" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_memo_test.xml" value="0.25" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_splash.xml" value="0.4921875" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_splash.xml" value="0.4921875" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_subject_statistics.xml" value="0.23454913880445796" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_test_detail.xml" value="0.33" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_test_detail.xml" value="0.33" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/custom_marker_view.xml" value="0.23353596757852077" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/custom_marker_view.xml" value="0.23353596757852077" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_pinyin.xml" value="0.67" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_pinyin.xml" value="0.67" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_spell_single_word.xml" value="0.23632218844984804" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_spell_single_word.xml" value="0.23632218844984804" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_statics_for_time.xml" value="0.27717391304347827" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_statics_for_time.xml" value="0.27717391304347827" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_statistics_bottom_course_change.xml" value="0.30842391304347827" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_statistics_course.xml" value="0.33" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_statistics_course_chapter_info.xml" value="0.5" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_task_image.xml" value="0.23353596757852077" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_task_image.xml" value="0.23353596757852077" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail.xml" value="0.348731884057971" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail.xml" value="0.348731884057971" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail_option.xml" value="0.348731884057971" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail_option.xml" value="0.348731884057971" /> |
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||
xmlns:tools="http://schemas.android.com/tools" | xmlns:tools="http://schemas.android.com/tools" | ||||
package="com.xkl.cdl"> | |||||
package="com.xkl.cdl" > | |||||
<application | <application | ||||
android:name=".module.XKLApplication" | android:name=".module.XKLApplication" | ||||
android:roundIcon="@mipmap/ic_launcher_round" | android:roundIcon="@mipmap/ic_launcher_round" | ||||
android:supportsRtl="true" | android:supportsRtl="true" | ||||
android:theme="@style/Theme.XklLocal" | android:theme="@style/Theme.XklLocal" | ||||
tools:ignore="LockedOrientationActivity"> | |||||
tools:ignore="LockedOrientationActivity" > | |||||
<activity | |||||
android:name=".module.m_statics.CourseStatisticsDetailActivity" | |||||
android:exported="true" /> | |||||
<activity | |||||
android:name=".module.m_statics.SubjectStatisticsDetailActivity" | |||||
android:exported="true" /> | |||||
<activity | <activity | ||||
android:name=".module.m_service_center.TestDetailActivity" | android:name=".module.m_service_center.TestDetailActivity" | ||||
android:exported="true" /> | android:exported="true" /> | ||||
android:configChanges="orientation|keyboardHidden|screenSize" | android:configChanges="orientation|keyboardHidden|screenSize" | ||||
android:exported="true" | android:exported="true" | ||||
android:screenOrientation="portrait" | android:screenOrientation="portrait" | ||||
android:theme="@style/Theme.Splash"> | |||||
android:theme="@style/Theme.Splash" > | |||||
<intent-filter> | <intent-filter> | ||||
<action android:name="android.intent.action.MAIN" /> | <action android:name="android.intent.action.MAIN" /> | ||||
package com.xkl.cdl.adapter | |||||
import android.view.View | |||||
import android.view.ViewGroup | |||||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||||
import com.suliang.common.base.adapter.BaseRVAdapter | |||||
import com.suliang.common.databinding.ItemEmptyBinding | |||||
import com.suliang.common.extension.setHtml | |||||
import com.suliang.common.widget.NumberUtils | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.data.bean.course.Lesson | |||||
import com.xkl.cdl.databinding.ItemStatisticsCourseChapterInfoBinding | |||||
/** | |||||
* author suliang | |||||
* create 2022/7/1 10:27 | |||||
* Describe: 统计详情下的章节学习情况 | |||||
*/ | |||||
class AdapterStatisticsCourseChapterInfo : BaseRVAdapter<Lesson>() { | |||||
override fun onBindEmptyViewHolder(holder : BaseAdapterViewHolder) { | |||||
(holder.binding as ItemEmptyBinding).apply { | |||||
imgEmpty.setImageResource(R.mipmap.empty_nothing) | |||||
tvContent.text = "没有课程进度" | |||||
} | |||||
} | |||||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_statistics_course_chapter_info)) | |||||
} | |||||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||||
(holder.binding as ItemStatisticsCourseChapterInfoBinding).apply { | |||||
getItem(position).let { | |||||
when (it.courseType) { | |||||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | |||||
tv1.text = "章节" | |||||
tv1Value.text = it.chapterName | |||||
tv2.text = "学习进度" | |||||
tv2Value.text = "${NumberUtils.formatHalfUp(it.beforeTestScore, "0.#")}%" | |||||
tv3.setHtml( | |||||
"<font color=\"#323232\">条目-</font><font color=\"#40A540\">正确</font>|<font color=\"#F26255\">错误</font>") | |||||
tv3Value.setHtml( | |||||
"<font color=\"#323232\">${it.totalNumber}-</font><font color=\"#40A540\">${it.correctNumber}</font>|<font color=\"#F26255\">${it.errorNumber}</font>") | |||||
tv4.text = "知识点测试" | |||||
if (it.afterTestScore != AppConstants.NOT_DOING) { | |||||
it.afterTestScore.toInt().let { | |||||
p4.progress = it | |||||
tv5Value.text = it.toString() | |||||
} | |||||
} else { | |||||
p4.visibility = View.GONE | |||||
tv4Value.text = "——" | |||||
} | |||||
View.GONE.let { | |||||
v5.visibility = it | |||||
tv5.visibility = it | |||||
tv5Value.visibility = it | |||||
p5.visibility = it | |||||
} | |||||
} | |||||
else -> { | |||||
tv1Value.text = it.lessonName | |||||
tv2.text = "学习进度" | |||||
tv2Value.text = NumberUtils.formatHalfUp( | |||||
it.wordIds.subList(0, it.learnedIndex + 1).size / it.totalNumber.toDouble(), "0.#%") | |||||
tv3.setHtml( | |||||
"<font color=\"#323232\">条目-</font><font color=\"#40A540\">正确</font> | <font color=\"#F26255\">错误</font>") | |||||
tv3Value.setHtml( | |||||
"<font color=\"#323232\">${it.totalNumber}-</font><font color=\"#40A540\">${it.correctNumber}</font> | <font color=\"#F26255\">${it.errorNumber}</font>") | |||||
tv4.text = "课时学前测试" | |||||
tv5.text = "课时学前测试" | |||||
if (it.beforeTestScore != AppConstants.NOT_DOING) { | |||||
it.beforeTestScore.toInt().let { | |||||
p4.progress = it | |||||
tv4Value.text = it.toString() | |||||
} | |||||
} else { | |||||
p4.visibility = View.GONE | |||||
tv4Value.text = "——" | |||||
} | |||||
if (it.afterTestScore != AppConstants.NOT_DOING) { | |||||
it.afterTestScore.toInt().let { | |||||
p5.progress = it | |||||
tv5Value.text = it.toString() | |||||
} | |||||
} else { | |||||
p5.visibility = View.GONE | |||||
tv5Value.text = "——" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
package com.xkl.cdl.adapter | |||||
import android.view.ViewGroup | |||||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||||
import com.suliang.common.base.adapter.BaseRVAdapter | |||||
import com.suliang.common.databinding.ItemEmptyBinding | |||||
import com.suliang.common.extension.click | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.data.bean.StatisticsCourse | |||||
import com.xkl.cdl.data.bean.course.Course | |||||
import com.xkl.cdl.databinding.ItemStatisticsCourseBinding | |||||
/** | |||||
* author suliang | |||||
* create 2022/6/27 14:24 | |||||
* Describe: | |||||
*/ | |||||
class AdapterSubjectCourseStatistics : BaseRVAdapter<StatisticsCourse>() { | |||||
override fun onBindEmptyViewHolder(holder : BaseAdapterViewHolder) { | |||||
(holder.binding as ItemEmptyBinding).apply { | |||||
imgEmpty.setImageResource( R.mipmap.empty_nothing ) | |||||
tvContent.text = "没有可分析的课程" | |||||
} | |||||
} | |||||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||||
return BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_statistics_course)) | |||||
} | |||||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||||
(holder.binding as ItemStatisticsCourseBinding).course = getItem(position) | |||||
holder.binding.root.click { | |||||
if (onItemClickIsInitialized()){ | |||||
onItemClick.invoke(it,position,getItem(position)) | |||||
} | |||||
} | |||||
} | |||||
} |
@Suppress("UNCHECKED_CAST") | @Suppress("UNCHECKED_CAST") | ||||
fun <T> getData(key : String = AppConfig.INTENT_1) : T{ | fun <T> getData(key : String = AppConfig.INTENT_1) : T{ | ||||
return (dataMap[key] as T).also { | return (dataMap[key] as T).also { | ||||
clear() | |||||
dataMap.remove(key) | |||||
} | } | ||||
} | } | ||||
package com.xkl.cdl.data.bean | |||||
import com.xkl.cdl.data.bean.course.Course | |||||
/** | |||||
* author suliang | |||||
* create 2022/6/27 14:42 | |||||
* Describe: 统计课程item | |||||
*/ | |||||
class StatisticsCourse(val course:Course,val cover: ByteArray) { | |||||
} |
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 |
import android.graphics.drawable.Drawable | import android.graphics.drawable.Drawable | ||||
import android.widget.ImageView | import android.widget.ImageView | ||||
import android.widget.ProgressBar | |||||
import android.widget.TextView | import android.widget.TextView | ||||
import androidx.databinding.BindingAdapter | import androidx.databinding.BindingAdapter | ||||
import com.suliang.common.util.DrawableUti | import com.suliang.common.util.DrawableUti | ||||
} | } | ||||
} | } | ||||
/** | |||||
* 统计课程文字显示的进度格式化 | |||||
* @param view TextView | |||||
* @param learnProgress Double | |||||
*/ | |||||
@BindingAdapter("courseStatisticsLearnProgressTextViewFormat") | |||||
@JvmStatic | |||||
fun courseStatisticsLearnProgressTextViewFormat(view: TextView,learnProgress:Double){ | |||||
view.text = when{ | |||||
learnProgress == 0.0 -> "0%" | |||||
learnProgress < 0.1 -> "0.1%" | |||||
learnProgress < 100 -> { | |||||
DecimalFormat("#.#").apply { | |||||
roundingMode = RoundingMode.DOWN | |||||
}.format(learnProgress) + "%" | |||||
} | |||||
else -> "100%" | |||||
} | |||||
} | |||||
/** | |||||
* 课程统计进度条显示时的进度,最大进度值 1000 | |||||
* @param view ProgressBar | |||||
* @param learnProgress Double 默认为百分进度 | |||||
*/ | |||||
@BindingAdapter("courseStatisticsLearnProgressFormat") | |||||
@JvmStatic | |||||
fun courseStatisticsLearnProgressFormat(view: ProgressBar,learnProgress:Double){ | |||||
val p = learnProgress * 10 //进度值改千分进度 | |||||
view.progress = when{ | |||||
p == 0.0 -> 0 | |||||
p < 0.1 -> 1 | |||||
p < 1000 -> p.toInt() | |||||
else -> 1000 | |||||
} | |||||
} | |||||
} | } |
coursePack.childrenCourses.forEach { | coursePack.childrenCourses.forEach { | ||||
//如果是作文,作文需要检查数据库,同时需要检查其下的图片、视频和关键帧 | //如果是作文,作文需要检查数据库,同时需要检查其下的图片、视频和关键帧 | ||||
if (it.subjectId == AppConstants.SUBJECT_CHINESE && it.coursePackType == AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION){ | |||||
if (it.subjectId == AppConstants.SUBJECT_CHINESE && it.coursePackType == AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION) { | |||||
val assetFileName = it.dbPathName.substringBeforeLast(".") + ".zip" | val assetFileName = it.dbPathName.substringBeforeLast(".") + ".zip" | ||||
val inputStream = AppGlobals.application.resources.assets.open(assetFileName) | val inputStream = AppGlobals.application.resources.assets.open(assetFileName) | ||||
val zipInputStream = ZipInputStream(inputStream) | val zipInputStream = ZipInputStream(inputStream) | ||||
var count = 0 | |||||
var count = 0 | |||||
val buffer = ByteArray(5120) | val buffer = ByteArray(5120) | ||||
var nextEntry = zipInputStream.nextEntry | var nextEntry = zipInputStream.nextEntry | ||||
while (nextEntry != null){ | |||||
when{ | |||||
nextEntry.name.endsWith(".mp4.png") -> File(FilePathManager.getMp4PngRootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${nextEntry.name.substringAfterLast("/")}") | |||||
nextEntry.name.endsWith(".mp4") -> File(FilePathManager.getMp4RootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${nextEntry.name.substringAfterLast("/")}") | |||||
nextEntry.name.endsWith(".png") -> File(FilePathManager.getPngRootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${nextEntry.name.substringAfterLast("/")}") | |||||
nextEntry.name.endsWith(".db") -> File(FilePathManager.getDbRootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db") | |||||
while (nextEntry != null) { | |||||
when { | |||||
nextEntry.name.endsWith(".mp4.png") -> File(FilePathManager.getMp4PngRootPath(), | |||||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${ | |||||
nextEntry.name.substringAfterLast("/") | |||||
}") | |||||
nextEntry.name.endsWith(".mp4") -> File(FilePathManager.getMp4RootPath(), | |||||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${ | |||||
nextEntry.name.substringAfterLast("/") | |||||
}") | |||||
nextEntry.name.endsWith(".png") -> File(FilePathManager.getPngRootPath(), | |||||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${ | |||||
nextEntry.name.substringAfterLast("/") | |||||
}") | |||||
nextEntry.name.endsWith(".db") -> File(FilePathManager.getDbRootPath(), | |||||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db") | |||||
else -> null | else -> null | ||||
}?.let { file -> | }?.let { file -> | ||||
//文件不存在 ,复制当前文件进入该文件 | |||||
if (!file.exists()){ | |||||
//文件不存在 ,复制当前文件进入该文件 | |||||
if (!file.exists()) { | |||||
file.parentFile?.let { parentFile -> | file.parentFile?.let { parentFile -> | ||||
if (!parentFile.exists()) parentFile.mkdirs() | if (!parentFile.exists()) parentFile.mkdirs() | ||||
} | } | ||||
val outputStream = BufferedOutputStream(FileOutputStream(file)) | val outputStream = BufferedOutputStream(FileOutputStream(file)) | ||||
while ((zipInputStream.read(buffer).also { count = it }) != -1 ){ | |||||
outputStream.write(buffer,0,count) | |||||
while ((zipInputStream.read(buffer).also { count = it }) != -1) { | |||||
outputStream.write(buffer, 0, count) | |||||
} | } | ||||
outputStream.close() | outputStream.close() | ||||
} | } | ||||
nextEntry = zipInputStream.nextEntry | nextEntry = zipInputStream.nextEntry | ||||
} | } | ||||
}else{ //其他的项目只需要复制和检查数据库 | |||||
val file = File(FilePathManager.getDbRootPath(), "${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db") | |||||
} else { //其他的项目只需要复制和检查数据库 | |||||
val file = File(FilePathManager.getDbRootPath(), | |||||
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db") | |||||
//不存在,复制,存在则不操作 | //不存在,复制,存在则不操作 | ||||
if (!file.exists()) { | if (!file.exists()) { | ||||
FileUtil.copyAsset(it.dbPathName, file) | FileUtil.copyAsset(it.dbPathName, file) | ||||
return totalProgress / chapterTotalSize * 100 | return totalProgress / chapterTotalSize * 100 | ||||
} | } | ||||
/** | |||||
* 作文课程单章节的进度计算 | |||||
* @param allLesson List<Lesson> 章节所有课时 | |||||
*/ | |||||
fun calculateCompositionChapterProgress(allLesson : List<Lesson>) : Double { | |||||
var lessonSize = 0 | |||||
var chapterProgressSize = 0.0 | |||||
//循环 | |||||
allLesson.forEach { | |||||
//单章节内的进度累加 | |||||
if (it.lessonType != AppConstants.LESSON_TYPE_COMPOSITION_TASK) { | |||||
lessonSize += 1 | |||||
//章节添加课时进度 | |||||
chapterProgressSize += if (it.learnIsOver) 1.0 else if (it.lessonType == AppConstants.LESSON_TYPE_COMPOSITION_KNOWLEDGE) { | |||||
//知识点的进度设置,设置该课时总进度为 1 | |||||
if (it.learnedIndex == -1) 0.0 else (it.learnedIndex + 1.0) / it.wordIds.size | |||||
} else 0.0 | |||||
} | |||||
} | |||||
//计算进度 | |||||
return chapterProgressSize / lessonSize * 100 | |||||
} | |||||
/** | /** | ||||
* 口语课程的进度计算 | * 口语课程的进度计算 | ||||
* @param allLesson List<Lesson> | * @param allLesson List<Lesson> | ||||
// TODO: 2022/6/2 时间需改为day 开发期间用于调式,故意设此值 | // TODO: 2022/6/2 时间需改为day 开发期间用于调式,故意设此值 | ||||
//间隔时间单位 | //间隔时间单位 | ||||
private val reviewIntervalUnit = "hour" | private val reviewIntervalUnit = "hour" | ||||
//间隔单位时间 | //间隔单位时间 | ||||
private val reviewTime = IntArray(7){ | |||||
when(it){ | |||||
private val reviewTime = IntArray(7) { | |||||
when (it) { | |||||
0 -> 1 | 0 -> 1 | ||||
1 -> 2 | 1 -> 2 | ||||
2 -> 3 | 2 -> 3 | ||||
* @param currentTime Long 用以计算的当前时间 | * @param currentTime Long 用以计算的当前时间 | ||||
* @return Boolean true:需要复习 false:不需要复习 | * @return Boolean true:需要复习 false:不需要复习 | ||||
*/ | */ | ||||
fun calculateIsNeedInReview(calendar:Calendar,currentReviewNumber : Int, currentReviewTime : String, currentTime : Long) : Boolean { | |||||
fun calculateIsNeedInReview(calendar : Calendar, | |||||
currentReviewNumber : Int, | |||||
currentReviewTime : String, | |||||
currentTime : Long) : Boolean { | |||||
if (currentReviewNumber >= reviewTime.size) return false | if (currentReviewNumber >= reviewTime.size) return false | ||||
try { | try { | ||||
//转换设置当前的复习时间 | //转换设置当前的复习时间 | ||||
calendar.time = DateUtil.format(currentReviewTime,DateUtil.FORMAT_1) | |||||
calendar.time = DateUtil.format(currentReviewTime, DateUtil.FORMAT_1) | |||||
//与当前时间的间隔 | //与当前时间的间隔 | ||||
val intervalTime = currentTime - calendar.timeInMillis | val intervalTime = currentTime - calendar.timeInMillis | ||||
//单位转换 : 给一个提前量的时间,提前一分钟 | //单位转换 : 给一个提前量的时间,提前一分钟 | ||||
return intervalTime >= when(reviewIntervalUnit){ | |||||
return intervalTime >= when (reviewIntervalUnit) { | |||||
"minute" -> reviewTime[currentReviewNumber] * 60000 | "minute" -> reviewTime[currentReviewNumber] * 60000 | ||||
"hour" -> reviewTime[currentReviewNumber] * 60 * 60000 | "hour" -> reviewTime[currentReviewNumber] * 60 * 60000 | ||||
else -> reviewTime[currentReviewNumber] * 24 * 60 * 60000 | |||||
else -> reviewTime[currentReviewNumber] * 24 * 60 * 60000 | |||||
} - 60000 | } - 60000 | ||||
}catch (e:Exception){ | |||||
} catch (e : Exception) { | |||||
e.printStackTrace() | e.printStackTrace() | ||||
} | } | ||||
return false | return false |
correctNumber = detail.right.getOrElse(key, { 0 }).toInt() //正确数 | correctNumber = detail.right.getOrElse(key, { 0 }).toInt() //正确数 | ||||
errorNumber = detail.wrong.getOrElse(key, { 0 }).toInt() //错误数 | errorNumber = detail.wrong.getOrElse(key, { 0 }).toInt() //错误数 | ||||
beforeTestScore = detail.before.getOrElse(key, { AppConstants.NOT_DOING }) //课时学前测试成绩 | beforeTestScore = detail.before.getOrElse(key, { AppConstants.NOT_DOING }) //课时学前测试成绩 | ||||
afterTestScore = detail.after.getOrElse(key, { AppConstants.NOT_DOING }) //课时学后测试成绩 | |||||
afterTestScore = detail.after.getOrElse(key, { AppConstants.NOT_DOING }) //课时学后测试成绩,作文知识点测试时为知识点测试成绩 | |||||
this.lessonType = lessonType | this.lessonType = lessonType | ||||
} | } | ||||
// 学习位置 | // 学习位置 | ||||
// id集合中的学习entity的位置, 作文的视频、知识点测试,不以这个为标准 | // id集合中的学习entity的位置, 作文的视频、知识点测试,不以这个为标准 | ||||
val learnIndex = wordIds.indexOf(detail.lesson_learn_point.getOrElse(key, { -1 })) //学习位置,当前位置为已学 | val learnIndex = wordIds.indexOf(detail.lesson_learn_point.getOrElse(key, { -1 })) //学习位置,当前位置为已学 | ||||
lesson.learnedIndex = learnIndex | |||||
// 注:针对口语对话课时,如果没有学习完,是不会设置进度点的。 todo 分课程类型设置进度点 口语未做判断处理 | // 注:针对口语对话课时,如果没有学习完,是不会设置进度点的。 todo 分课程类型设置进度点 口语未做判断处理 | ||||
lesson.learnIsOver = when (base.coursePackType) { | lesson.learnIsOver = when (base.coursePackType) { | ||||
//作文课时,需要根据课时属性,判断本课时是否学习完成 | //作文课时,需要根据课时属性,判断本课时是否学习完成 | ||||
positionIndex += 1 | positionIndex += 1 | ||||
// TODO: 2022/5/9 对课时数量进行限制,课时太多,开发人员不好进行测试 | // TODO: 2022/5/9 对课时数量进行限制,课时太多,开发人员不好进行测试 | ||||
val needBreak = when (base.coursePackType) { | val needBreak = when (base.coursePackType) { | ||||
AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION -> positionIndex == 6 //保留十个课时 | |||||
AppConstants.COURSEPACK_TYPE_ENGLISH_SPOKEN -> positionIndex == 4 //保留六个课时 | |||||
else -> positionIndex == 1 //保留三个课时 | |||||
AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION -> positionIndex == 10 //保留十个课时 | |||||
AppConstants.COURSEPACK_TYPE_ENGLISH_SPOKEN -> positionIndex == 6 //保留六个课时 | |||||
else -> positionIndex == 3 //保留三个课时 | |||||
} | } | ||||
if (needBreak) { | if (needBreak) { | ||||
break | break |
package com.xkl.cdl.module.m_statics | |||||
import android.annotation.SuppressLint | |||||
import android.graphics.Color | |||||
import android.os.Bundle | |||||
import android.view.View | |||||
import androidx.core.content.ContextCompat | |||||
import androidx.lifecycle.ViewModelProvider | |||||
import androidx.recyclerview.widget.LinearLayoutManager | |||||
import com.github.mikephil.charting.components.XAxis | |||||
import com.github.mikephil.charting.data.BarData | |||||
import com.github.mikephil.charting.data.BarDataSet | |||||
import com.github.mikephil.charting.data.BarEntry | |||||
import com.github.mikephil.charting.formatter.ValueFormatter | |||||
import com.lxj.xpopup.XPopup | |||||
import com.suliang.common.base.activity.BaseActivityVM | |||||
import com.suliang.common.extension.click | |||||
import com.suliang.common.extension.setHtml | |||||
import com.suliang.common.widget.NumberUtils | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.adapter.AdapterStatisticsCourseChapterInfo | |||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.data.bean.course.CourseDetail | |||||
import com.xkl.cdl.databinding.ActivityCourseStatisticsDetailBinding | |||||
import com.xkl.cdl.widget.MyMarkerView | |||||
import com.xkl.cdl.widget.StatisticsICourseChangePopup | |||||
import java.util.* | |||||
import kotlin.collections.ArrayList | |||||
import kotlin.math.abs | |||||
/** | |||||
* author suliang | |||||
* create 2022/6/27 9:42 | |||||
* Describe: 课程的统计详情 | |||||
*/ | |||||
class CourseStatisticsDetailActivity : BaseActivityVM<ActivityCourseStatisticsDetailBinding, CourseStatisticsDetailViewModel>() { | |||||
override fun initViewModel() : CourseStatisticsDetailViewModel { | |||||
return ViewModelProvider(this)[CourseStatisticsDetailViewModel::class.java] | |||||
} | |||||
private lateinit var pupCourseChangeView : StatisticsICourseChangePopup | |||||
override fun initActivity(savedInstanceState : Bundle?) { | |||||
binding.titleBar.onBackClick = { _ -> finish() } | |||||
binding.course = vm.currentStatisCourse | |||||
initChart() | |||||
binding.rvChapterInfo.apply { | |||||
layoutManager = LinearLayoutManager(this@CourseStatisticsDetailActivity,LinearLayoutManager.VERTICAL,false) | |||||
adapter = AdapterStatisticsCourseChapterInfo() | |||||
} | |||||
if (vm.statisticsCourseList.size <= 1){ | |||||
binding.ivChangeCourse.visibility = View.INVISIBLE | |||||
}else{ | |||||
// TODO: 2022/7/1 弹窗实例失败 | |||||
//课程切换弹窗 | |||||
binding.ivChangeCourse.click { | |||||
if (!this::pupCourseChangeView.isInitialized){ | |||||
pupCourseChangeView = StatisticsICourseChangePopup(this).apply { | |||||
data = vm.statisticsCourseList | |||||
checkPostion = vm.checkedPosition | |||||
onAdapterItemClick = { position,item -> | |||||
vm.checkedPosition = position | |||||
vm.currentStatisCourse = item | |||||
loadData() | |||||
} | |||||
} | |||||
} | |||||
XPopup.Builder(this).asCustom(pupCourseChangeView).show() | |||||
} | |||||
} | |||||
vm.courseDetailLiveData.observe(this) { | |||||
when { | |||||
//英语界面显示 | |||||
vm.isShowAsEnglish(vm.dbControlBase.subjectId, vm.dbControlBase.coursePackType) -> { | |||||
//已学课堂练习 进度布局隐藏 | |||||
binding.ranking3.visibility = View.GONE | |||||
//测试成绩对比 | |||||
initTestTotalScore(it.st_before, it.st_after) | |||||
//学习效率初始 | |||||
initEfficient(it.e, it.last_e) | |||||
//学习时长统计 | |||||
initDurationTime(it) | |||||
} | |||||
//作文界面显示 | |||||
else -> { | |||||
binding.layoutTestScore.visibility = View.GONE | |||||
binding.layoutEfficient.visibility = View.GONE | |||||
initDurationTime(it) | |||||
} | |||||
} | |||||
} | |||||
/**课程进度 章节学习情况显示*/ | |||||
vm.courseLessonLiveData.observe(this){ | |||||
when(vm.currentStatisCourse.course.courseType){ | |||||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | |||||
binding.ranking1.setProgressNumber(vm.learnLessonSize / vm.totalLessonSize.toFloat() * 100) | |||||
binding.tvRanking1Flag.text = "已学章节" | |||||
binding.tvRanking1Value.setHtml("<font color=\"#40A540\"><b>${vm.learnLessonSize}</b></font>/${vm.totalLessonSize}") | |||||
binding.ranking2.setProgressNumber(vm.learnWordNumber/vm.totalWordNumber.toFloat() * 100 ) | |||||
binding.tvRanking2Flag.text = "已学知识点" | |||||
binding.tvRanking2Value.setHtml("<font color=\"#5082E6\"><b>${vm.learnWordNumber}</b></font>/${vm.totalWordNumber}") | |||||
binding.ranking3.setProgressNumber(vm.learnRadingSize/vm.totalRadingSize.toFloat() * 100) | |||||
binding.tvRanking3Flag.text = "已学课堂练习" | |||||
binding.tvRanking3Value.setHtml("<font color=\"#8757E6\"><b>${vm.learnRadingSize}</b></font>/${vm.totalRadingSize}") | |||||
} | |||||
else -> { | |||||
binding.ranking1.setProgressNumber(vm.learnLessonSize / vm.totalLessonSize.toFloat() * 100) | |||||
binding.tvRanking1Flag.text = "已学课时" | |||||
binding.tvRanking1Value.setHtml("<font color=\"#40A540\"><b>${vm.learnLessonSize}</b></font>/${vm.totalLessonSize}") | |||||
binding.ranking2.setProgressNumber(vm.learnWordNumber/vm.totalWordNumber.toFloat() * 100) | |||||
binding.tvRanking2Flag.text = "已学词汇量" | |||||
binding.tvRanking2Value.setHtml("<font color=\"#5082E6\"><b>${vm.learnWordNumber}</b></font>/${vm.totalWordNumber}") | |||||
binding.ranking3.visibility = View.GONE | |||||
} | |||||
} | |||||
//根据生成的数据,进行选择器的实现 | |||||
when(vm.chapterList.size){ | |||||
0,1 -> binding.tvChapterChoose.visibility = View.GONE | |||||
else -> binding.tvChapterChoose.visibility = if(vm.chapterList[0].size > 0){ | |||||
binding.tvChapterChoose.text = vm.chapterList[0][0].chapterName | |||||
View.VISIBLE | |||||
}else { | |||||
View.GONE | |||||
} | |||||
} | |||||
//通知刷新列表 | |||||
vm.rvChapterChangeLiveData.value = 0 | |||||
} | |||||
//章节切换 | |||||
vm.rvChapterChangeLiveData.observe(this){ | |||||
if(vm.chapterList.size > it){ | |||||
(binding.rvChapterInfo.adapter as AdapterStatisticsCourseChapterInfo).apply { | |||||
needShowEmptyView = false | |||||
setData(vm.chapterList[it]) | |||||
} | |||||
}else{ | |||||
(binding.rvChapterInfo.adapter as AdapterStatisticsCourseChapterInfo).apply { | |||||
needShowEmptyView = true | |||||
setData(null) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* 初始化数据图 | |||||
*/ | |||||
private fun initChart() { | |||||
binding.barChart.apply { | |||||
description.isEnabled = false | |||||
setMaxVisibleValueCount(40) | |||||
setScaleEnabled(false) //禁止缩放 | |||||
setDrawGridBackground(false) | |||||
setDrawBarShadow(false) | |||||
setDrawValueAboveBar(false) | |||||
isHighlightFullBarEnabled = true | |||||
xAxis.apply { | |||||
isEnabled = true | |||||
setDrawGridLines(false) | |||||
setDrawAxisLine(false) | |||||
//自定义设置x轴显示value | |||||
valueFormatter = object : ValueFormatter() { | |||||
override fun getFormattedValue(value : Float) : String { | |||||
return vm.getTimeNode(value.toInt()) } | |||||
} | |||||
//设置x坐标显示个数 | |||||
granularity = 1f | |||||
textSize = 11f | |||||
textColor = Color.parseColor("#8A8A99") | |||||
position = XAxis.XAxisPosition.BOTTOM_INSIDE | |||||
} | |||||
axisLeft.apply { | |||||
gridColor = Color.parseColor("#E6E2E2") | |||||
textColor = Color.parseColor("#8A8A99") | |||||
setDrawAxisLine(false) | |||||
// granularity = 1f | |||||
setLabelCount(4, false) // force 6 labels | |||||
valueFormatter = object : ValueFormatter() { | |||||
override fun getFormattedValue(value : Float) : String { | |||||
return NumberUtils.formatFloor(value.toDouble(),"0.#") | |||||
} | |||||
} | |||||
} | |||||
axisRight.isEnabled = false | |||||
legend.isEnabled = false | |||||
//标签 | |||||
setDrawMarkers(true) | |||||
val mv = MyMarkerView(this@CourseStatisticsDetailActivity, R.layout.custom_marker_view) | |||||
mv.chartView = this // For bounds control | |||||
this.marker = mv // Set the marker to the chart | |||||
mv.setValueCallback { tv, e -> | |||||
val dataSets = this.data.dataSets | |||||
for (iBarDataSet in dataSets) { | |||||
//设置value框的偏移量 | |||||
mv.offsetX = 240f | |||||
val entryIndex = iBarDataSet.getEntryIndex(e as BarEntry) | |||||
if (entryIndex >= 0) { | |||||
this.setDrawMarkers(true) | |||||
if (e.getX() >= 2) { | |||||
//放左边 | |||||
mv.offsetX = -400f | |||||
} else { | |||||
//放右边 | |||||
mv.offsetX =400f | |||||
} | |||||
//分钟数转换为毫秒 | |||||
val valid = (e.yVals[0] * 60000.0).toLong() | |||||
val review = (e.yVals[1]* 60000.0).toLong() | |||||
val free = (e.yVals[2] * 60000.0).toLong() | |||||
val str : String = "<b><font>${vm.getTimeNode(entryIndex)}<font></b>" + | |||||
"<br><font color=\'#8A8A99\'>有效学习时长:</font> <font color=\'#F7874F\'>${formatTime(valid)}</font><font color=\'#8A8A99\'>${formatTimeUnit(valid)}</font>" + | |||||
"<br><font color=\'#8A8A99\'>有效复习时长:</font> <font color=\'#40A540\'>${formatTime(review)}</font><font color=\'#8A8A99\'>${formatTimeUnit(review)}</font>\n" + | |||||
"<br><font color=\'#8A8A99\'>空闲时长:</font> <font color=\'#5082E6\'> ${formatTime(free)}</font><font color=\'#8A8A99\'>${formatTimeUnit(free)}</font>" | |||||
tv.setHtml(str) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
override fun loadData() { | |||||
vm.getCourseDetailInfo() | |||||
} | |||||
/** | |||||
* 测试成绩对比 | |||||
* @param stBefore Double | |||||
* @param stAfter Double | |||||
*/ | |||||
private fun initTestTotalScore(stBefore : Double, stAfter : Double) { | |||||
var tc = R.color.green_1 //tvTestState文字显示颜色 | |||||
var res = R.drawable.ic_rise //tvTestState前缀图标 | |||||
var tv = "+?" //tvTestState显示文字 | |||||
var ivRes = 0 //ivTestState 背景资源 | |||||
var tvBefore = "" //学前值 | |||||
var tvAfter = "" //学后值 | |||||
when { | |||||
//学前学后总测试都没做 | |||||
stBefore == AppConstants.NOT_DOING && stAfter == AppConstants.NOT_DOING -> { | |||||
ivRes = R.mipmap.statistics_testscore_nodata_chart | |||||
tvBefore = "未测" | |||||
tvAfter = "未测" | |||||
} | |||||
//学前学后总测都做完 | |||||
stBefore != AppConstants.NOT_DOING && stAfter != AppConstants.NOT_DOING -> { | |||||
//差距 | |||||
val instance = stAfter - stBefore | |||||
when { | |||||
instance == 0.0 -> { | |||||
tv = "+0" | |||||
ivRes = R.mipmap.statistics_testscore_equality_chart | |||||
} | |||||
instance > 0 -> { | |||||
tv = "+${NumberUtils.formatFloor(instance, "0.#")}" | |||||
ivRes = R.mipmap.statistics_testscore_up_chart | |||||
} | |||||
else -> { | |||||
tc = R.color.red_1 | |||||
res = R.drawable.ic_decline | |||||
tv = "-${NumberUtils.formatFloor(abs(instance), "0.#")}" | |||||
ivRes = R.mipmap.statistics_testscore_lower_chart | |||||
} | |||||
} | |||||
tvBefore = "${stBefore.toInt()}分" | |||||
tvAfter = "${stAfter.toInt()}分" | |||||
} | |||||
//学前总测做了,学后总测没做 | |||||
stAfter == AppConstants.NOT_DOING -> { | |||||
ivRes = R.mipmap.statistics_testscore_noend_chart | |||||
tvBefore = "${stBefore.toInt()}分" | |||||
tvAfter = "未测" | |||||
} | |||||
} | |||||
binding.ivTestState.setBackgroundResource(ivRes) | |||||
binding.tvTestState.apply { | |||||
setTextColor(ContextCompat.getColor(this@CourseStatisticsDetailActivity, tc)) | |||||
setCompoundDrawablesWithIntrinsicBounds(res, 0, 0, 0) | |||||
text = tv | |||||
} | |||||
binding.tvBeforeTotal.text = tvBefore | |||||
binding.tvAfterTotal.text = tvAfter | |||||
} | |||||
/** | |||||
* 学习效率 | |||||
* @param e Double | |||||
* @param lastE Double | |||||
*/ | |||||
private fun initEfficient(e : Double, lastE : Double) { | |||||
when (vm.currentStatisCourse.course.courseType) { | |||||
//口语隐藏效率 | |||||
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> binding.layoutEfficient.visibility = View.GONE | |||||
else -> { | |||||
binding.rankingEfficient.setProgressNumber(e.toFloat()) | |||||
binding.tvEfficient.text = "${NumberUtils.formatHalfUp(e, "0.##")}%" | |||||
binding.tvEfficientState.apply { | |||||
val instance = lastE - e | |||||
when { | |||||
//增长 | |||||
instance >= 0 -> { | |||||
setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_rise, 0, 0, 0) | |||||
setTextColor(ContextCompat.getColor(this@CourseStatisticsDetailActivity, R.color.green_1)) | |||||
text = "+${NumberUtils.formatHalfUp(instance, "0.##")}%" | |||||
} | |||||
//下降 | |||||
else -> { | |||||
setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_decline, 0, 0, 0) | |||||
setTextColor(ContextCompat.getColor(this@CourseStatisticsDetailActivity, R.color.red_1)) | |||||
text = "-${NumberUtils.formatHalfUp(abs(instance), "0.##")}%" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/**学习时长统计*/ | |||||
@SuppressLint("SetTextI18n") | |||||
private fun initDurationTime(detail : CourseDetail) { | |||||
//总时长趋势 | |||||
val value = "${formatTime(abs(detail.current_week_total_durations))}${ | |||||
formatTimeUnit(abs(detail.current_week_total_durations)) | |||||
}" | |||||
when { | |||||
detail.current_week_total_durations >= 0 -> { | |||||
binding.tvDurationState.apply { | |||||
setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_rise, 0, 0, 0) | |||||
text = "+$value" | |||||
} | |||||
} | |||||
else -> { | |||||
binding.tvDurationState.apply { | |||||
setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_rise, 0, 0, 0) | |||||
text = "-$value" | |||||
} | |||||
} | |||||
} | |||||
var totalTime = 0L | |||||
var validTotalTime = 0L | |||||
var reviewTotalTime = 0L | |||||
val chartValueList = mutableListOf<MutableList<Long>>() | |||||
for (i in 1 until 5L) { | |||||
val total = detail.total.getOrElse(i, { 0 }) | |||||
val valid = detail.valid.getOrElse(i, { 0 }) | |||||
val review = detail.review.getOrElse(i, { 0 }) | |||||
totalTime += total | |||||
validTotalTime += valid | |||||
reviewTotalTime += review | |||||
//图表模型值 | |||||
chartValueList.add(mutableListOf(valid, review, total - valid - review)) | |||||
} | |||||
val freeTotalTime = totalTime - validTotalTime - reviewTotalTime | |||||
//设置时长 | |||||
binding.tvTotalDuration.text = formatTime(totalTime) | |||||
binding.tvTotalDurationUnit.text = formatTimeUnit(totalTime) | |||||
binding.tvValidTime.text = formatTime(validTotalTime) | |||||
binding.tvValidTimeUnit.text = formatTimeUnit(validTotalTime) | |||||
binding.tvReviewTime.text = formatTime(reviewTotalTime) | |||||
binding.tvReviewTimeUnit.text = formatTimeUnit(reviewTotalTime) | |||||
binding.tvFreeTime.text = formatTime(freeTotalTime) | |||||
binding.tvFreeTimeUnit.text = formatTimeUnit(freeTotalTime) | |||||
//更新图表值 | |||||
setChartDate(chartValueList) | |||||
} | |||||
/** 格式化时间值 */ | |||||
private fun formatTime(time : Long) : String { | |||||
val hour_1 = time / 3600000.0 | |||||
val minute_1 = time / 60000.0 | |||||
return when { | |||||
//大于1小时 | |||||
hour_1 > 1 -> "${NumberUtils.formatFloor(hour_1, "0.##")}" | |||||
//大于1分钟 | |||||
minute_1 > 1 -> "${NumberUtils.formatFloor(minute_1, "0.##")}" | |||||
//小于1分钟 秒数 | |||||
else -> "" | |||||
} | |||||
} | |||||
/**格式化单位*/ | |||||
private fun formatTimeUnit(time : Long) : String { | |||||
val hour_1 = time / 3600000.0 | |||||
val minute_1 = time / 60000.0 | |||||
return when { | |||||
//大于1小时 | |||||
hour_1 > 1 -> "小时" | |||||
//大于1分钟 | |||||
minute_1 > 1 -> "分钟" | |||||
//小于1分钟 秒数 | |||||
else -> "不足1分钟" | |||||
} | |||||
} | |||||
/** | |||||
* 设置统计图的数据 | |||||
* @param list | |||||
*/ | |||||
private fun setChartDate(chartValueList : MutableList<MutableList<Long>>) { | |||||
val barChart = binding.barChart | |||||
val values = ArrayList<BarEntry>() | |||||
var max = 0f | |||||
chartValueList.forEachIndexed { i,it -> | |||||
val valid = if (it[0] >= 0) it[0]/60000.0f else 0f | |||||
val review = if (it[1] >= 0) it[1]/60000.0f else 0f | |||||
val free = if (it[2] >= 0) it[2]/60000.0f else 0f | |||||
val sum = valid + review + free | |||||
if (sum > max) { | |||||
max = sum | |||||
} | |||||
//数据由毫秒转换为了分钟数 | |||||
values.add(BarEntry(i.toFloat(), floatArrayOf(valid, review, free), null)) | |||||
} | |||||
if (max <= 0) { | |||||
barChart.setNoDataText("暂无数据") | |||||
barChart.clear() | |||||
return | |||||
} | |||||
val set1 : BarDataSet | |||||
if (barChart.data != null && barChart.data.dataSetCount > 0){ | |||||
set1 = barChart.data.getDataSetByIndex(0) as BarDataSet | |||||
set1.values = values | |||||
barChart.data.notifyDataChanged() | |||||
barChart.notifyDataSetChanged() | |||||
}else{ | |||||
set1 = BarDataSet(values,"") | |||||
set1.setDrawIcons(false) | |||||
set1.setDrawValues(false) | |||||
set1.colors = vm.getColors().toMutableList() | |||||
val data = BarData(set1) | |||||
data.barWidth = 0.5f | |||||
barChart.data = data | |||||
} | |||||
barChart.setFitBars(true) | |||||
barChart.invalidate() | |||||
} | |||||
} |
package com.xkl.cdl.module.m_statics | |||||
import androidx.lifecycle.MutableLiveData | |||||
import com.github.mikephil.charting.utils.ColorTemplate | |||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.base.activity.ToastEvent | |||||
import com.suliang.common.base.viewmodel.BaseViewModel | |||||
import com.suliang.common.util.thread.AppExecutors | |||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.data.DataTransferHolder | |||||
import com.xkl.cdl.data.bean.StatisticsCourse | |||||
import com.xkl.cdl.data.bean.course.Course | |||||
import com.xkl.cdl.data.bean.course.CourseDetail | |||||
import com.xkl.cdl.data.bean.course.Lesson | |||||
import com.xkl.cdl.data.manager.CourseManager | |||||
import com.xkl.cdl.data.manager.db.DBCourseManager | |||||
import com.xkl.cdl.data.manager.db.DbControlBase | |||||
import com.xkl.cdl.data.repository.DataRepository | |||||
import io.reactivex.rxjava3.schedulers.Schedulers | |||||
/** | |||||
* author suliang | |||||
* create 2022/6/28 11:29 | |||||
* Describe: | |||||
*/ | |||||
class CourseStatisticsDetailViewModel : BaseViewModel() { | |||||
//课程列表 | |||||
val statisticsCourseList = DataTransferHolder.instance.getData<MutableList<StatisticsCourse>>(AppConfig.INTENT_1) | |||||
//选择课程 | |||||
var checkedPosition = DataTransferHolder.instance.getData<Int>(AppConfig.INTENT_2) | |||||
//当前操作课程 | |||||
var currentStatisCourse = statisticsCourseList[checkedPosition] | |||||
val dbControlBase : DbControlBase | |||||
get() { | |||||
val course : Course = currentStatisCourse.course | |||||
return DbControlBase(course.subjectId, course.coursePackId, course.coursePackType, course.courseId, course.courseType) | |||||
} | |||||
//当前课程统计信息 | |||||
val courseDetailLiveData = MutableLiveData<CourseDetail>() | |||||
//当前课程课时信息初始结束 | |||||
val courseLessonLiveData = MutableLiveData<Boolean>() | |||||
//rv选择章节position | |||||
val rvChapterChangeLiveData = MutableLiveData<Int>() | |||||
/**获取课程统计详情*/ | |||||
fun getCourseDetailInfo() { | |||||
val course = currentStatisCourse.course | |||||
DataRepository.getCourseDetails(course.subjectId, course.coursePackId, course.courseId).map { | |||||
//测试成绩对比、学习效率 和 学习时长统计中的总时间趋势 | |||||
courseDetailLiveData.postValue(it) | |||||
//获取课时信息 | |||||
DBCourseManager.queryAllLesson(dbControlBase, it) | |||||
}.subscribeOn(Schedulers.from(AppExecutors.diskIO)).subscribe({ | |||||
initLessons(it) | |||||
}, { | |||||
showToast(ToastEvent("数据查询失败")) | |||||
}) | |||||
} | |||||
/**是否显示为英语的界面 | |||||
* 语文的识字、拼音和英语显示是一致的 只有作文显示不一致 | |||||
* */ | |||||
fun isShowAsEnglish(subjectId : Int, coursePackType : Int) : Boolean { | |||||
return subjectId == AppConstants.SUBJECT_ENGLISH || coursePackType != AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION | |||||
} | |||||
/**透过下标获取不同的时间点*/ | |||||
fun getTimeNode(entryIndex : Int) : String { | |||||
return when (entryIndex) { | |||||
0 -> "6:00-12:00" | |||||
1 -> "12:00-18:00" | |||||
2 -> "18:00-24:00" | |||||
else -> "0:00-6:00" | |||||
} | |||||
} | |||||
/*----------------------设置统计图表中需要的一些方法 Start-------------------------------------------------------------------------------------------*/ | |||||
/** | |||||
* 获取最大值 | |||||
* | |||||
* @return | |||||
*/ | |||||
fun getMaxY(max : Int) : Float { | |||||
//设置坐标轴最大值和最小值 | |||||
var temp = max / 5 | |||||
temp = if (temp >= 1000) { | |||||
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000 | |||||
} else if (temp >= 100) { | |||||
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100 | |||||
} else if (temp >= 10) { | |||||
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10 | |||||
} else { | |||||
(temp + if (max % 5 > 0) 1 else 0) * 1 | |||||
} | |||||
return (temp * 5 + temp / 2.0).toFloat() | |||||
} | |||||
/** | |||||
* 获取最小值 | |||||
* | |||||
* @return | |||||
*/ | |||||
fun getMinY(max : Int) : Float { | |||||
//设置坐标轴最大值和最小值 | |||||
var temp = max / 5 | |||||
temp = if (temp >= 1000) { | |||||
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000 | |||||
} else if (temp >= 100) { | |||||
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100 | |||||
} else if (temp >= 10) { | |||||
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10 | |||||
} else { | |||||
(temp + if (max % 5 > 0) 1 else 0) * 1 | |||||
} | |||||
return (-(temp - temp / 2.0) - if (temp / 2.5 == 0.0) 0.3 else temp / 2.5).toFloat() | |||||
} | |||||
val XUEKAOLE_COLORS_STATISTIC = intArrayOf(ColorTemplate.rgb("#F7874F"), ColorTemplate.rgb("#40A540"), | |||||
ColorTemplate.rgb("#5082E6")) | |||||
/** | |||||
* 获取柱状图的颜色 | |||||
* @return | |||||
*/ | |||||
fun getColors() : IntArray { | |||||
// have as many colors as stack-values per entry | |||||
val colors = IntArray(3) | |||||
System.arraycopy(XUEKAOLE_COLORS_STATISTIC, 0, colors, 0, 3) | |||||
return colors | |||||
} | |||||
var learnLessonSize = 0 //已学课时 作文:已学章节数 | |||||
var totalLessonSize = 0 //总课时 作文:总章节数 | |||||
var learnWordNumber = 0 //已学词汇数 作文:已学知识点数量 | |||||
var totalWordNumber = 0 //总词汇量 作文: 总知识点个数 | |||||
var learnRadingSize = 0 //已学课堂练习数 | |||||
var totalRadingSize = 0 //课堂练习总数 | |||||
val chapterList = mutableListOf<MutableList<Lesson>>() //用于显示的章节课时的学习情况 | |||||
private fun initLessons(list : List<Lesson>) { | |||||
learnLessonSize = 0 //已学课时 作文:已学章节数 | |||||
totalLessonSize = 0 //总课时 作文:总章节数 | |||||
learnWordNumber = 0 //已学词汇数 作文:已学知识点数量 | |||||
totalWordNumber = 0 //总词汇量 作文: 总知识点个数 | |||||
learnRadingSize = 0 //已学课堂练习数 | |||||
totalRadingSize = 0 //课堂练习总数 | |||||
chapterList.clear() | |||||
var previousChapterId = -1L //记录上一个章节的id | |||||
var currentChapterList = mutableListOf<Lesson>() //记录一个章节的课时 | |||||
when(dbControlBase.courseType){ | |||||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | |||||
for (i in list.size -1 downTo 0) { | |||||
val lesson = list[i] | |||||
//转换为章节集合 | |||||
when(lesson.chapterId){ | |||||
//同一章节 | |||||
previousChapterId -> { | |||||
currentChapterList.add(lesson) | |||||
} | |||||
//不同章节 | |||||
else -> { | |||||
currentChapterList = mutableListOf() | |||||
currentChapterList.add(lesson) | |||||
chapterList.add(currentChapterList) | |||||
previousChapterId = lesson.chapterId | |||||
} | |||||
} | |||||
} | |||||
//总章节数 | |||||
totalLessonSize = chapterList.size | |||||
val chapterListNew = mutableListOf<Lesson>() | |||||
//组合章节结果, 转换为lesson用于显示 | |||||
chapterList.forEach { | |||||
val lesson = it[0] | |||||
//将课时组装为课时 | |||||
val newLesson = Lesson(lesson.subjectId,lesson.coursePackId,lesson.coursePackType,lesson.courseId,lesson.courseType,lesson.chapterId,lesson.chapterName,lesson.lessonId,lesson.lessonName) | |||||
//计算各种数量 | |||||
it.forEach { | |||||
when(it.lessonType){ | |||||
AppConstants.LESSON_TYPE_COMPOSITION_KNOWLEDGE -> { //知识点学习 | |||||
newLesson.totalNumber = it.totalNumber | |||||
newLesson.errorNumber = it.errorNumber | |||||
newLesson.correctNumber = it.correctNumber | |||||
totalWordNumber += it.totalNumber | |||||
learnWordNumber += if (it.learnIsOver) it.totalNumber else lesson.wordIds.subList(0,lesson.learnedIndex+1).size | |||||
} | |||||
AppConstants.LESSON_TYPE_COMPOSITION_EXAM -> { //知识点测试,成绩在detail的after中 | |||||
newLesson.afterTestScore = it.afterTestScore | |||||
} | |||||
AppConstants.LESSON_TYPE_COMPOSITION_READING -> { //课堂练习 | |||||
totalRadingSize += it.totalNumber | |||||
learnRadingSize += if (it.learnIsOver) it.totalNumber else it.wordIds.subList(0,it.learnedIndex + 1).size //已学数 | |||||
} | |||||
} | |||||
} | |||||
//计算该章节的进度 | |||||
val chapterProgress = CourseManager.calculateCompositionChapterProgress(it) | |||||
if (chapterProgress !=0.0){ | |||||
learnLessonSize += 1 | |||||
newLesson.beforeTestScore = chapterProgress //使用学前测试字段记录 章节进度 | |||||
chapterListNew.add(newLesson) | |||||
} | |||||
} | |||||
chapterList.clear() | |||||
chapterList.addAll(mutableListOf(chapterListNew)) | |||||
} | |||||
//英语 | |||||
else -> { | |||||
totalLessonSize = list.size //总课时数 | |||||
//使用倒叙循环 | |||||
for (i in list.size -1 downTo 0) { | |||||
val lesson = list.get(i) | |||||
if (lesson.lessonType != AppConstants.LESSON_TYPE_DIALOGUE) { //口语对话练习不添加为总数,不添加到列表显示 | |||||
totalWordNumber += lesson.totalNumber //累加总数 | |||||
//做了学前测试,则学习课时+1 | |||||
if (lesson.beforeTestScore != AppConstants.NOT_DOING) { | |||||
learnLessonSize += 1 | |||||
//做了学前测试,才有可能进行了课时单词的学习,计算已学单词数 | |||||
if (lesson.learnedIndex != -1) { | |||||
learnWordNumber += if (lesson.learnIsOver) lesson.totalNumber else lesson.wordIds.subList(0, | |||||
lesson.learnedIndex + 1).size | |||||
} | |||||
//统计已学章节的内容,用于显示章节的学习情况 | |||||
when (lesson.chapterId) { | |||||
//同一章节 | |||||
previousChapterId -> currentChapterList.add(lesson) | |||||
else -> { | |||||
currentChapterList = mutableListOf() | |||||
currentChapterList.add(lesson) | |||||
chapterList.add(currentChapterList) | |||||
previousChapterId = lesson.chapterId | |||||
} | |||||
} | |||||
} | |||||
}else if (lesson.learnIsOver){ //口语对话课时,学习完成,则添加一个已学课时数 | |||||
learnLessonSize += 1 | |||||
} | |||||
} | |||||
} | |||||
} | |||||
//通知更新 | |||||
courseLessonLiveData.postValue(true) | |||||
} | |||||
} |
package com.xkl.cdl.module.m_statics | package com.xkl.cdl.module.m_statics | ||||
import android.graphics.Typeface | import android.graphics.Typeface | ||||
import android.text.Html | |||||
import android.text.SpannableString | import android.text.SpannableString | ||||
import android.text.Spanned | import android.text.Spanned | ||||
import android.text.style.StyleSpan | import android.text.style.StyleSpan | ||||
import androidx.core.content.ContextCompat | import androidx.core.content.ContextCompat | ||||
import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
import androidx.recyclerview.widget.GridLayoutManager | |||||
import appApi.AppApi.EntityCount | |||||
import com.github.mikephil.charting.components.* | import com.github.mikephil.charting.components.* | ||||
import com.github.mikephil.charting.data.Entry | import com.github.mikephil.charting.data.Entry | ||||
import com.github.mikephil.charting.data.LineData | import com.github.mikephil.charting.data.LineData | ||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet | import com.github.mikephil.charting.interfaces.datasets.ILineDataSet | ||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener | import com.github.mikephil.charting.listener.OnChartValueSelectedListener | ||||
import com.github.mikephil.charting.renderer.LineChartRenderer | import com.github.mikephil.charting.renderer.LineChartRenderer | ||||
import com.google.android.material.tabs.TabLayout | |||||
import com.lxj.xpopup.XPopup | import com.lxj.xpopup.XPopup | ||||
import com.lxj.xpopup.enums.PopupPosition | import com.lxj.xpopup.enums.PopupPosition | ||||
import com.suliang.common.base.fragment.BaseFragmentVM | import com.suliang.common.base.fragment.BaseFragmentVM | ||||
import com.suliang.common.extension.loadFragment | import com.suliang.common.extension.loadFragment | ||||
import com.suliang.common.extension.setHtml | import com.suliang.common.extension.setHtml | ||||
import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
import com.xkl.cdl.adapter.AdapterStaticsTime | |||||
import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
import com.xkl.cdl.databinding.FragmentStaticsBinding | import com.xkl.cdl.databinding.FragmentStaticsBinding | ||||
import com.xkl.cdl.widget.MyMarkerView | import com.xkl.cdl.widget.MyMarkerView | ||||
class StaticsFragment : BaseFragmentVM<FragmentStaticsBinding, StaticsFragmentViewModel>() { | |||||
class StaticsFragment : BaseFragmentVM<FragmentStaticsBinding, StatisticsFragmentViewModel>() { | |||||
companion object { | companion object { | ||||
@JvmStatic | @JvmStatic | ||||
} | } | ||||
override fun initViewModel() : StaticsFragmentViewModel { | |||||
return ViewModelProvider(this)[StaticsFragmentViewModel::class.java] | |||||
override fun initViewModel() : StatisticsFragmentViewModel { | |||||
return ViewModelProvider(this)[StatisticsFragmentViewModel::class.java] | |||||
} | } | ||||
override fun initFragment() { | override fun initFragment() { | ||||
//添加碎片 | //添加碎片 | ||||
loadFragment(R.id.fragment_top_time,0,StatisticsTimeTopFragment()) | |||||
loadFragment(R.id.fragment_top_time,0,StatisticsTimeTopFragment.newInstance(0)) | |||||
//detail | //detail | ||||
binding.layoutEnglish.click { | binding.layoutEnglish.click { | ||||
// TODO: 2022/6/24 进入详情 | |||||
SubjectStatisticsDetailActivity.newInstance(requireContext(),AppConstants.SUBJECT_ENGLISH) | |||||
} | |||||
binding.layoutChinese.click { | |||||
SubjectStatisticsDetailActivity.newInstance(requireContext(),AppConstants.SUBJECT_CHINESE) | |||||
} | } | ||||
binding.layoutChinese.click { } | |||||
//chart change | //chart change | ||||
binding.tvChartSubjectChoose.click { | binding.tvChartSubjectChoose.click { | ||||
XPopup.Builder(requireContext()).apply { | XPopup.Builder(requireContext()).apply { | ||||
///设置时间统计的选中项 | ///设置时间统计的选中项 | ||||
childFragmentManager.findFragmentByTag(StatisticsTimeTopFragment::javaClass.name)?.run { | childFragmentManager.findFragmentByTag(StatisticsTimeTopFragment::javaClass.name)?.run { | ||||
//设置时间统计的选中项 | //设置时间统计的选中项 | ||||
(this as StatisticsTimeTopFragment).binding.tabLayoutTime.getTabAt(0)?.select() | |||||
(this as StatisticsTimeTopFragment).loadData() | |||||
} | } | ||||
//图表设置 | //图表设置 | ||||
vm.chartChooseProjectIdLiveData.value = vm.chartChooseProjectIdLiveData.value | vm.chartChooseProjectIdLiveData.value = vm.chartChooseProjectIdLiveData.value |
package com.xkl.cdl.module.m_statics | |||||
import android.graphics.Color | |||||
import androidx.lifecycle.MutableLiveData | |||||
import appApi.AppApi | |||||
import com.github.mikephil.charting.components.YAxis | |||||
import com.github.mikephil.charting.data.Entry | |||||
import com.github.mikephil.charting.data.LineDataSet | |||||
import com.github.mikephil.charting.utils.ColorTemplate | |||||
import com.suliang.common.base.activity.ToastEvent | |||||
import com.suliang.common.base.viewmodel.BaseViewModel | |||||
import com.suliang.common.extension.diskIo2Main | |||||
import com.suliang.common.util.thread.AppExecutors | |||||
import com.suliang.common.widget.NumberUtils | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.data.bean.TimeStatisticItem | |||||
import com.xkl.cdl.data.manager.CourseManager | |||||
import com.xkl.cdl.data.repository.DataRepository | |||||
import com.xkl.cdl.module.XKLApplication | |||||
import io.reactivex.rxjava3.core.Observable | |||||
import io.reactivex.rxjava3.schedulers.Schedulers | |||||
import kotlin.math.abs | |||||
import kotlin.math.max | |||||
class StatisticsFragmentViewModel : BaseViewModel() { | |||||
//chart选中 itemId | |||||
var chartChooseProjectIdLiveData = MutableLiveData<Int>(0) | |||||
//图标初始完成 | |||||
val chartLineInitLiveData = MutableLiveData<Boolean>() | |||||
/**获取词条数据,进行图标数据实例 */ | |||||
fun getStatisticsChartData(projectId:Int) { | |||||
DataRepository.getStatisticsChartData(projectId) | |||||
.subscribeOn(Schedulers.from(AppExecutors.diskIO)) | |||||
.observeOn(Schedulers.from(AppExecutors.io)) | |||||
.subscribe({ | |||||
//进行图标数据处理 | |||||
entityCountList.clear() | |||||
entityCountList.addAll(it.entityCountListList) | |||||
initChartLine(it.entityCountListList) | |||||
},{ | |||||
it.printStackTrace() | |||||
showToast(ToastEvent("统计数据获取失败")) | |||||
}) | |||||
} | |||||
val entityCountList: MutableList<AppApi.EntityCount> = mutableListOf() | |||||
var maxChart = 0L | |||||
var linDataSet_new : LineDataSet? = null //折线1 : 新学词条 | |||||
var linDataSet_review : LineDataSet? = null //折线2 : 复习词条 | |||||
private fun initChartLine(list: List<AppApi.EntityCount>){ | |||||
maxChart = 0L | |||||
linDataSet_new = null | |||||
linDataSet_review = null | |||||
val entrys_new = mutableListOf<Entry>() //新学点集合 | |||||
val entrys_review = mutableListOf<Entry>() //复习点集合 | |||||
list.forEachIndexed { index, it -> | |||||
entrys_new.add(Entry(index.toFloat(),it.n.toFloat())) | |||||
entrys_review.add(Entry(index.toFloat(),it.r.toFloat())) | |||||
maxChart = when{ | |||||
it.n > it.r -> max(maxChart, it.n) | |||||
else -> max(maxChart, it.r) | |||||
} | |||||
} | |||||
if (list.isEmpty()){ | |||||
chartLineInitLiveData.postValue(false) | |||||
return | |||||
} | |||||
linDataSet_new = LineDataSet(entrys_new, "新学词条数").apply { | |||||
axisDependency = YAxis.AxisDependency.RIGHT | |||||
color = Color.parseColor("#5082E6") | |||||
lineWidth = 2f | |||||
circleRadius = 5f | |||||
circleHoleRadius = 3f | |||||
setCircleColor(Color.parseColor("#5082E6")) | |||||
fillAlpha = 65 | |||||
fillColor = ColorTemplate.getHoloBlue() | |||||
highLightColor = Color.parseColor("#1A5082E6") | |||||
highlightLineWidth = 18f | |||||
setDrawCircleHole(true) | |||||
setDrawHorizontalHighlightIndicator(false) | |||||
setDrawVerticalHighlightIndicator(true) | |||||
} | |||||
linDataSet_review = LineDataSet(entrys_review, "复习词条数").apply { | |||||
axisDependency = YAxis.AxisDependency.RIGHT | |||||
color = Color.parseColor("#F25255") | |||||
lineWidth = 2f | |||||
circleRadius = 5f | |||||
circleHoleRadius = 3f | |||||
setCircleColor(Color.parseColor("#F25255")) | |||||
fillAlpha = 65 | |||||
fillColor = Color.RED | |||||
highLightColor = Color.parseColor("#1A5082E6") | |||||
highlightLineWidth = 18f | |||||
setDrawCircleHole(true) | |||||
setDrawHorizontalHighlightIndicator(false) | |||||
} | |||||
chartLineInitLiveData.postValue(true) | |||||
} | |||||
/** 获取y轴的最大值 */ | |||||
fun getMaxY(): Float{ | |||||
//设置坐标轴最大值和最小值 | |||||
var temp : Int = (maxChart / 5).toInt() | |||||
temp = if (temp >= 1000) { | |||||
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000 | |||||
} else if (temp >= 100) { | |||||
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100 | |||||
} else if (temp >= 10) { | |||||
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10 | |||||
} else { | |||||
(temp + if (maxChart % 5 > 0) 1 else 0) * 1 | |||||
} | |||||
return (temp * 5 + temp / 2.0).toFloat() | |||||
} | |||||
/**获取y轴的最小值*/ | |||||
fun getMinY():Float{ | |||||
//设置坐标轴最大值和最小值 | |||||
var temp : Int = (maxChart / 5).toInt() | |||||
temp = if (temp >= 1000) { | |||||
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000 | |||||
} else if (temp >= 100) { | |||||
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100 | |||||
} else if (temp >= 10) { | |||||
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10 | |||||
} else { | |||||
(temp + if (maxChart % 5 > 0) 1 else 0) * 1 | |||||
} | |||||
return (-(temp - temp / 2.0) - if (temp / 2.5 == 0.0) 0.3 else temp / 2.5).toFloat() | |||||
} | |||||
/** 获取为x显示的值 */ | |||||
fun getxAxisValue(value : Float) : String { | |||||
if (entityCountList.size > value){ | |||||
val entity = entityCountList[value.toInt()] | |||||
val split = entity.day.split("-") | |||||
return if (split[2].equals("01")) "${split[1]}月" else split[2] | |||||
} | |||||
return "" | |||||
} | |||||
} |
package com.xkl.cdl.module.m_statics | package com.xkl.cdl.module.m_statics | ||||
import android.os.Bundle | |||||
import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
import androidx.recyclerview.widget.GridLayoutManager | import androidx.recyclerview.widget.GridLayoutManager | ||||
import com.google.android.material.tabs.TabLayout | import com.google.android.material.tabs.TabLayout | ||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.base.fragment.BaseFragmentVM | import com.suliang.common.base.fragment.BaseFragmentVM | ||||
import com.xkl.cdl.adapter.AdapterStaticsTime | import com.xkl.cdl.adapter.AdapterStaticsTime | ||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.databinding.FragmentStatisticsTimeTopBinding | import com.xkl.cdl.databinding.FragmentStatisticsTimeTopBinding | ||||
/** | /** | ||||
* create 2022/6/24 17:24 | * create 2022/6/24 17:24 | ||||
* Describe: | * Describe: | ||||
*/ | */ | ||||
class StatisticsTimeTopFragment : BaseFragmentVM<FragmentStatisticsTimeTopBinding, StaticsFragmentViewModel>() { | |||||
class StatisticsTimeTopFragment : BaseFragmentVM<FragmentStatisticsTimeTopBinding, StatisticsTimeTopFragmentViewModel>() { | |||||
override fun initViewModel() : StaticsFragmentViewModel { | |||||
return ViewModelProvider(requireParentFragment())[StaticsFragmentViewModel::class.java] | |||||
companion object{ | |||||
fun newInstance(projectId : Int) : StatisticsTimeTopFragment { | |||||
val args = Bundle() | |||||
args.putInt(AppConfig.INTENT_1, projectId) | |||||
val fragment = StatisticsTimeTopFragment() | |||||
fragment.arguments = args | |||||
return fragment | |||||
} | |||||
} | |||||
override fun initViewModel() : StatisticsTimeTopFragmentViewModel { | |||||
return ViewModelProvider(this)[StatisticsTimeTopFragmentViewModel::class.java] | |||||
} | } | ||||
override fun initFragment() { | override fun initFragment() { | ||||
vm.projectId = requireArguments().getInt(AppConfig.INTENT_1,0) | |||||
initTabLayout() | initTabLayout() | ||||
//rv | //rv | ||||
binding.rvTime.apply { | binding.rvTime.apply { | ||||
layoutManager = GridLayoutManager(requireContext(), 2) | layoutManager = GridLayoutManager(requireContext(), 2) | ||||
adapter = AdapterStaticsTime() | adapter = AdapterStaticsTime() | ||||
} | } | ||||
} | |||||
override fun loadData() { | |||||
//监听时间选项变化 | //监听时间选项变化 | ||||
vm.timeStatisticsPositionLiveData.observe(this) { position -> | vm.timeStatisticsPositionLiveData.observe(this) { position -> | ||||
if (!vm.isInitStatisticsResponse()) { | if (!vm.isInitStatisticsResponse()) { | ||||
} | } | ||||
} | } | ||||
override fun loadData() { | |||||
//设置选中加载数据 | |||||
vm.timeStatisticsPositionLiveData.value = binding.tabLayoutTime.selectedTabPosition | |||||
} | |||||
private fun initTabLayout() { | private fun initTabLayout() { | ||||
binding.tabLayoutTime.run { | binding.tabLayoutTime.run { | ||||
addTab(this.newTab().setText("全部时间"), false) | |||||
addTab(this.newTab().setText("全部时间"), true) | |||||
addTab(this.newTab().setText("今日"), false) | addTab(this.newTab().setText("今日"), false) | ||||
addTab(this.newTab().setText("本周"), false) | addTab(this.newTab().setText("本周"), false) | ||||
addTab(this.newTab().setText("本月"), false) | addTab(this.newTab().setText("本月"), false) |
package com.xkl.cdl.module.m_statics | package com.xkl.cdl.module.m_statics | ||||
import android.graphics.Color | |||||
import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||
import appApi.AppApi | import appApi.AppApi | ||||
import com.github.mikephil.charting.components.YAxis | |||||
import com.github.mikephil.charting.data.Entry | |||||
import com.github.mikephil.charting.data.LineDataSet | |||||
import com.github.mikephil.charting.utils.ColorTemplate | |||||
import com.suliang.common.base.activity.ToastEvent | import com.suliang.common.base.activity.ToastEvent | ||||
import com.suliang.common.base.viewmodel.BaseViewModel | import com.suliang.common.base.viewmodel.BaseViewModel | ||||
import com.suliang.common.extension.diskIo2Main | import com.suliang.common.extension.diskIo2Main | ||||
import com.suliang.common.util.thread.AppExecutors | |||||
import com.suliang.common.widget.NumberUtils | import com.suliang.common.widget.NumberUtils | ||||
import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
import com.xkl.cdl.data.bean.TimeStatisticItem | import com.xkl.cdl.data.bean.TimeStatisticItem | ||||
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.module.XKLApplication | import com.xkl.cdl.module.XKLApplication | ||||
import io.reactivex.rxjava3.core.Observable | import io.reactivex.rxjava3.core.Observable | ||||
import io.reactivex.rxjava3.schedulers.Schedulers | |||||
import kotlin.math.abs | import kotlin.math.abs | ||||
import kotlin.math.max | |||||
class StaticsFragmentViewModel : BaseViewModel() { | |||||
class StatisticsTimeTopFragmentViewModel : BaseViewModel() { | |||||
/**顶部统计信息*/ | /**顶部统计信息*/ | ||||
/** 时间统计选择位置 */ | /** 时间统计选择位置 */ | ||||
var projectId = 0 //默认全部 | |||||
val timeStatisticsPositionLiveData = MutableLiveData<Int>() | val timeStatisticsPositionLiveData = MutableLiveData<Int>() | ||||
lateinit var statisticsResponse : AppApi.StatisticsCenterResponse | lateinit var statisticsResponse : AppApi.StatisticsCenterResponse | ||||
var timeValuesList : MutableList<MutableList<TimeStatisticItem>> = mutableListOf() | var timeValuesList : MutableList<MutableList<TimeStatisticItem>> = mutableListOf() | ||||
//chart选中 itemId | |||||
var chartChooseProjectIdLiveData = MutableLiveData<Int>(0) | |||||
//图标初始完成 | |||||
val chartLineInitLiveData = MutableLiveData<Boolean>() | |||||
fun isInitStatisticsResponse() : Boolean { | fun isInitStatisticsResponse() : Boolean { | ||||
return this::statisticsResponse.isInitialized | return this::statisticsResponse.isInitialized | ||||
} | } | ||||
fun getStatistics() : MutableLiveData<Boolean> { | fun getStatistics() : MutableLiveData<Boolean> { | ||||
val result = MutableLiveData<Boolean>() | val result = MutableLiveData<Boolean>() | ||||
Observable.fromCallable { | Observable.fromCallable { | ||||
val statisticsCenter = XKLApplication.mobileCache.statisticsCenter(0, 0) | |||||
val statisticsCenter = XKLApplication.mobileCache.statisticsCenter(projectId.toLong(), 0) | |||||
val parseFrom = AppApi.StatisticsCenterResponse.parseFrom(statisticsCenter) | val parseFrom = AppApi.StatisticsCenterResponse.parseFrom(statisticsCenter) | ||||
return@fromCallable parseFrom | return@fromCallable parseFrom | ||||
}.compose(diskIo2Main()).subscribe({ | }.compose(diskIo2Main()).subscribe({ | ||||
} | } | ||||
} | } | ||||
/**获取词条数据,进行图标数据实例 */ | |||||
fun getStatisticsChartData(projectId:Int) { | |||||
DataRepository.getStatisticsChartData(projectId) | |||||
.subscribeOn(Schedulers.from(AppExecutors.diskIO)) | |||||
.observeOn(Schedulers.from(AppExecutors.io)) | |||||
.subscribe({ | |||||
//进行图标数据处理 | |||||
entityCountList.clear() | |||||
entityCountList.addAll(it.entityCountListList) | |||||
initChartLine(it.entityCountListList) | |||||
},{ | |||||
it.printStackTrace() | |||||
showToast(ToastEvent("统计数据获取失败")) | |||||
}) | |||||
} | |||||
val entityCountList: MutableList<AppApi.EntityCount> = mutableListOf() | |||||
var maxChart = 0L | |||||
var linDataSet_new : LineDataSet? = null //折线1 : 新学词条 | |||||
var linDataSet_review : LineDataSet? = null //折线2 : 复习词条 | |||||
private fun initChartLine(list: List<AppApi.EntityCount>){ | |||||
maxChart = 0L | |||||
linDataSet_new = null | |||||
linDataSet_review = null | |||||
val entrys_new = mutableListOf<Entry>() //新学点集合 | |||||
val entrys_review = mutableListOf<Entry>() //复习点集合 | |||||
list.forEachIndexed { index, it -> | |||||
entrys_new.add(Entry(index.toFloat(),it.n.toFloat())) | |||||
entrys_review.add(Entry(index.toFloat(),it.r.toFloat())) | |||||
maxChart = when{ | |||||
it.n > it.r -> max(maxChart, it.n) | |||||
else -> max(maxChart, it.r) | |||||
} | |||||
} | |||||
if (list.isEmpty()){ | |||||
chartLineInitLiveData.postValue(false) | |||||
return | |||||
} | |||||
linDataSet_new = LineDataSet(entrys_new, "新学词条数").apply { | |||||
axisDependency = YAxis.AxisDependency.RIGHT | |||||
color = Color.parseColor("#5082E6") | |||||
lineWidth = 2f | |||||
circleRadius = 5f | |||||
circleHoleRadius = 3f | |||||
setCircleColor(Color.parseColor("#5082E6")) | |||||
fillAlpha = 65 | |||||
fillColor = ColorTemplate.getHoloBlue() | |||||
highLightColor = Color.parseColor("#1A5082E6") | |||||
highlightLineWidth = 18f | |||||
setDrawCircleHole(true) | |||||
setDrawHorizontalHighlightIndicator(false) | |||||
setDrawVerticalHighlightIndicator(true) | |||||
} | |||||
linDataSet_review = LineDataSet(entrys_review, "复习词条数").apply { | |||||
axisDependency = YAxis.AxisDependency.RIGHT | |||||
color = Color.parseColor("#F25255") | |||||
lineWidth = 2f | |||||
circleRadius = 5f | |||||
circleHoleRadius = 3f | |||||
setCircleColor(Color.parseColor("#F25255")) | |||||
fillAlpha = 65 | |||||
fillColor = Color.RED | |||||
highLightColor = Color.parseColor("#1A5082E6") | |||||
highlightLineWidth = 18f | |||||
setDrawCircleHole(true) | |||||
setDrawHorizontalHighlightIndicator(false) | |||||
} | |||||
chartLineInitLiveData.postValue(true) | |||||
} | |||||
/** 获取y轴的最大值 */ | |||||
fun getMaxY(): Float{ | |||||
//设置坐标轴最大值和最小值 | |||||
var temp : Int = (maxChart / 5).toInt() | |||||
temp = if (temp >= 1000) { | |||||
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000 | |||||
} else if (temp >= 100) { | |||||
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100 | |||||
} else if (temp >= 10) { | |||||
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10 | |||||
} else { | |||||
(temp + if (maxChart % 5 > 0) 1 else 0) * 1 | |||||
} | |||||
return (temp * 5 + temp / 2.0).toFloat() | |||||
} | |||||
/**获取y轴的最小值*/ | |||||
fun getMinY():Float{ | |||||
//设置坐标轴最大值和最小值 | |||||
var temp : Int = (maxChart / 5).toInt() | |||||
temp = if (temp >= 1000) { | |||||
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000 | |||||
} else if (temp >= 100) { | |||||
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100 | |||||
} else if (temp >= 10) { | |||||
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10 | |||||
} else { | |||||
(temp + if (maxChart % 5 > 0) 1 else 0) * 1 | |||||
} | |||||
return (-(temp - temp / 2.0) - if (temp / 2.5 == 0.0) 0.3 else temp / 2.5).toFloat() | |||||
} | |||||
/** 获取为x显示的值 */ | |||||
fun getxAxisValue(value : Float) : String { | |||||
if (entityCountList.size > value){ | |||||
val entity = entityCountList[value.toInt()] | |||||
val split = entity.day.split("-") | |||||
return if (split[2].equals("01")) "$split[1]月" else split[2] | |||||
} | |||||
return "" | |||||
} | |||||
} | } |
package com.xkl.cdl.module.m_statics | |||||
import android.content.Context | |||||
import android.content.Intent | |||||
import android.os.Bundle | |||||
import androidx.recyclerview.widget.LinearLayoutManager | |||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.base.activity.BaseActivity | |||||
import com.suliang.common.extension.loadFragment | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.adapter.AdapterSubjectCourseStatistics | |||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.data.DataTransferHolder | |||||
import com.xkl.cdl.data.bean.StatisticsCourse | |||||
import com.xkl.cdl.data.manager.CourseManager | |||||
import com.xkl.cdl.databinding.ActivitySubjectStatisticsBinding | |||||
/** | |||||
* author suliang | |||||
* create 2022/6/27 9:40 | |||||
* Describe: 统计项目下的课程列表详情 | |||||
*/ | |||||
class SubjectStatisticsDetailActivity : BaseActivity<ActivitySubjectStatisticsBinding>() { | |||||
companion object { | |||||
fun newInstance(context : Context, projectId : Int) { | |||||
val intent = Intent(context,SubjectStatisticsDetailActivity::class.java).apply { | |||||
putExtra(AppConfig.INTENT_1,projectId) | |||||
} | |||||
context.startActivity(intent) | |||||
} | |||||
} | |||||
private var projectId = 0 | |||||
private lateinit var adapter: AdapterSubjectCourseStatistics | |||||
private var statisticsCourseList = mutableListOf<StatisticsCourse>() | |||||
override fun initActivity(savedInstanceState : Bundle?) { | |||||
projectId = intent.getIntExtra(AppConfig.INTENT_1,0) | |||||
when(projectId){ | |||||
AppConstants.SUBJECT_ENGLISH -> binding.titleBar.setTitleTextValue("英语统计") | |||||
AppConstants.SUBJECT_CHINESE -> binding.titleBar.setTitleTextValue("语文统计") | |||||
} | |||||
binding.titleBar.onBackClick = { _ -> finish()} | |||||
//添加time统计fragment | |||||
loadFragment(R.id.fragment_top_time,0,StatisticsTimeTopFragment.newInstance(projectId)) | |||||
//实例化课程Rv | |||||
binding.rvCourse.apply { | |||||
layoutManager = LinearLayoutManager(this@SubjectStatisticsDetailActivity,LinearLayoutManager.VERTICAL,false) | |||||
this@SubjectStatisticsDetailActivity.adapter = AdapterSubjectCourseStatistics() | |||||
this.adapter = this@SubjectStatisticsDetailActivity.adapter.apply { | |||||
onItemClick = { _, position,_ -> | |||||
DataTransferHolder.instance.putData(AppConfig.INTENT_1,statisticsCourseList) | |||||
DataTransferHolder.instance.putData(AppConfig.INTENT_2,position) | |||||
startActivity(CourseStatisticsDetailActivity::class.java) | |||||
} | |||||
} | |||||
this@SubjectStatisticsDetailActivity.adapter.needShowEmptyView | |||||
} | |||||
} | |||||
override fun loadData() { | |||||
val coursePackList = CourseManager.subjectWithCoursePackMap.get(projectId) | |||||
if (coursePackList.isNullOrEmpty()){ | |||||
adapter.setData(emptyList<StatisticsCourse>().toMutableList()) | |||||
}else{ | |||||
//组合统计课程实体病设置进度值 | |||||
val courseSortInfo = CourseManager.mSortInfoList.get(projectId) | |||||
coursePackList.forEach { coursePack -> | |||||
coursePack.childrenCourses.forEach { course -> | |||||
statisticsCourseList.add(StatisticsCourse(course,coursePack.cover)) | |||||
run breaking@{ | |||||
courseSortInfo?.forEach { courseInfo -> | |||||
if (course.coursePackId == courseInfo.packId && course.courseId == courseInfo.courseId){ | |||||
course.courseLearnProgress = courseInfo.s | |||||
return@breaking | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
//设置列表数据 | |||||
adapter.setData(statisticsCourseList) | |||||
} | |||||
} | |||||
} |
package com.xkl.cdl.widget | |||||
import android.content.Context | |||||
import android.graphics.Color | |||||
import android.view.ViewGroup | |||||
import android.widget.ImageView | |||||
import android.widget.TextView | |||||
import androidx.core.content.ContextCompat | |||||
import androidx.recyclerview.widget.LinearLayoutManager | |||||
import androidx.recyclerview.widget.RecyclerView | |||||
import androidx.viewpager.widget.ViewPager | |||||
import com.lxj.xpopup.core.BottomPopupView | |||||
import com.lxj.xpopup.util.XPopupUtils | |||||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||||
import com.suliang.common.base.adapter.BaseRVAdapter | |||||
import com.suliang.common.extension.click | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.data.bean.StatisticsCourse | |||||
import com.xkl.cdl.data.binding.BindingAdapter | |||||
import com.xkl.cdl.databinding.ItemStatisticsBottomCourseChangeBinding | |||||
/** | |||||
* author suliang | |||||
* create 2022/7/1 16:41 | |||||
* Describe: | |||||
*/ | |||||
class StatisticsICourseChangePopup(context : Context) : BottomPopupView(context) { | |||||
lateinit var recyclerView: RecyclerView | |||||
var data = mutableListOf<StatisticsCourse>() | |||||
lateinit var onAdapterItemClick : (position:Int,item:StatisticsCourse) -> Unit | |||||
var checkPostion = - 1 | |||||
private lateinit var rvAdapter: Adapter | |||||
override fun getImplLayoutId() : Int { | |||||
return R.layout.dialog_bottom_auto_play_select | |||||
} | |||||
override fun onCreate() { | |||||
super.onCreate() | |||||
findViewById<TextView>(R.id.tv_title).text = "请选择你要查看的课程" | |||||
recyclerView = findViewById(R.id.rv_repeat) | |||||
findViewById<ImageView>(R.id.iv_cancel).click { | |||||
dismiss() | |||||
} | |||||
rvAdapter = Adapter().apply { | |||||
checkPosition = checkPostion | |||||
onItemClick = {_,p,item -> | |||||
if (this@StatisticsICourseChangePopup::onAdapterItemClick.isInitialized){ | |||||
onAdapterItemClick.invoke(p,item) | |||||
} | |||||
} | |||||
} | |||||
recyclerView.apply { | |||||
layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false) | |||||
adapter = rvAdapter | |||||
} | |||||
rvAdapter.setData(data) | |||||
} | |||||
override fun getMaxHeight() : Int { | |||||
return (XPopupUtils.getScreenHeight(context) * .7f).toInt() | |||||
} | |||||
} | |||||
// TODO: 2022/7/1 适配器inflate 失败 | |||||
internal class Adapter : BaseRVAdapter<StatisticsCourse>(){ | |||||
var checkPosition = 0 | |||||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||||
return BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_statistics_bottom_course_change)) | |||||
} | |||||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||||
(holder.binding as ItemStatisticsBottomCourseChangeBinding).run { | |||||
getItem(position).let { | |||||
tvName.text = it.course.courseTitle | |||||
BindingAdapter.courseStatisticsLearnProgressTextViewFormat(tvValue,it.course.courseLearnProgress) | |||||
} | |||||
when(position){ | |||||
checkPosition -> { | |||||
layout.setBackgroundColor(Color.parseColor("0D5082E6")) | |||||
tvName.setTextColor(ContextCompat.getColor(context,R.color.theme_color)) | |||||
tvValue.setTextColor(ContextCompat.getColor(context,R.color.theme_color)) | |||||
} | |||||
else -> { | |||||
layout.setBackgroundColor(ContextCompat.getColor(context,R.color.translation)) | |||||
tvName.setTextColor(ContextCompat.getColor(context,R.color.main_text_color)) | |||||
tvValue.setTextColor(ContextCompat.getColor(context,R.color.gray_2)) | |||||
} | |||||
} | |||||
} | |||||
holder.binding.root.click { | |||||
if (checkPosition != position){ | |||||
notifyDataSetChanged() | |||||
if (onItemClickIsInitialized()){ | |||||
onItemClick.invoke(it,position,getItem(position)) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
<?xml version="1.0" encoding="utf-8"?> | |||||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
xmlns:tools="http://schemas.android.com/tools"> | |||||
<data> | |||||
<variable | |||||
name="course" | |||||
type="com.xkl.cdl.data.bean.StatisticsCourse" /> | |||||
</data> | |||||
<androidx.appcompat.widget.LinearLayoutCompat | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:background="@color/white_1" | |||||
android:orientation="vertical" | |||||
tools:context=".module.m_statics.CourseStatisticsDetailActivity"> | |||||
<com.suliang.common.widget.TitleBar | |||||
android:id="@+id/title_bar" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="@dimen/title_bar_height" | |||||
app:barBackground="@color/white" | |||||
app:titleTextValue="@{course.course.courseTitle}"/> | |||||
<androidx.core.widget.NestedScrollView | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent"> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:layout_margin="@dimen/global_spacing"> | |||||
<!--top title--> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_top" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:padding="12dp" | |||||
app:layout_constraintTop_toTopOf="parent"> | |||||
<com.google.android.material.imageview.ShapeableImageView | |||||
android:id="@+id/img_course" | |||||
android:layout_width="52dp" | |||||
android:layout_height="0dp" | |||||
android:scaleType="fitXY" | |||||
app:imageByteArray="@{course.cover}" | |||||
app:layout_constraintDimensionRatio="52:72" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:shapeAppearance="@style/roundedCornerStyle" | |||||
tools:src="@color/main_text_color" /> | |||||
<ImageView | |||||
android:id="@+id/iv_change_course" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:src="@drawable/ic_change" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<TextView | |||||
android:id="@+id/tv_course_name" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="8dp" | |||||
android:layout_marginTop="4dp" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:ellipsize="end" | |||||
android:maxLines="2" | |||||
android:text="@{course.course.courseTitle}" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintEnd_toStartOf="@+id/iv_change_course" | |||||
app:layout_constraintStart_toEndOf="@+id/img_course" | |||||
app:layout_constraintTop_toTopOf="@+id/img_course" | |||||
tools:text="kjdkjsdkgjaskdlgjsadgjasldgddddffddfdfdffddjsakldgjsdakg" /> | |||||
<ProgressBar | |||||
android:id="@+id/progress_course" | |||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" | |||||
android:layout_width="120dp" | |||||
android:layout_height="4dp" | |||||
android:layout_marginBottom="8dp" | |||||
android:max="1000" | |||||
android:progressDrawable="@drawable/progress_center" | |||||
android:progressTint="@color/theme_color" | |||||
app:courseStatisticsLearnProgressFormat="@{(int)course.course.courseLearnProgress}" | |||||
app:layout_constraintBottom_toBottomOf="@+id/img_course" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_course_name" | |||||
tools:progress="40" /> | |||||
<TextView | |||||
android:id="@+id/tv_progress" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
android:layout_marginBottom="4dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:courseStatisticsLearnProgressTextViewFormat="@{(int)course.course.courseLearnProgress}" | |||||
app:layout_constraintBottom_toBottomOf="@+id/img_course" | |||||
app:layout_constraintStart_toEndOf="@+id/progress_course" | |||||
tools:text="10%" /> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
<!--测试成绩--> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_test_score" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="12dp" | |||||
android:layout_marginEnd="12dp" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:padding="12dp" | |||||
app:layout_constraintEnd_toStartOf="@+id/layout_efficient" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/layout_top" | |||||
app:layout_goneMarginEnd="0dp"> | |||||
<TextView | |||||
android:id="@+id/tv_test_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="测试成绩对比" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/bigSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<ImageView | |||||
android:id="@+id/iv_test_state" | |||||
android:layout_width="60dp" | |||||
android:layout_height="0dp" | |||||
android:layout_marginTop="@dimen/global_spacing" | |||||
app:layout_constraintDimensionRatio="60:92" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_test_flag" /> | |||||
<TextView | |||||
android:id="@+id/tv_test_state" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="8dp" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintStart_toEndOf="@+id/iv_test_state" | |||||
app:layout_constraintTop_toTopOf="@+id/iv_test_state" | |||||
tools:text="+12" /> | |||||
<TextView | |||||
android:id="@+id/tv_before_total_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="学前总测试" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_test_state" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_test_state" /> | |||||
<TextView | |||||
android:id="@+id/tv_before_total" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="12分" | |||||
android:textColor="@color/theme_color" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_before_total_flag" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_before_total_flag" /> | |||||
<TextView | |||||
android:id="@+id/tv_after_total_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="学前总测试" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_before_total" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_before_total" /> | |||||
<TextView | |||||
android:id="@+id/tv_after_total" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="14分" | |||||
android:textColor="@color/red_1" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_after_total_flag" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_after_total_flag" /> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
<!--学习效率--> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_efficient" | |||||
android:layout_width="0dp" | |||||
android:layout_height="0dp" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:padding="12dp" | |||||
app:layout_constraintBottom_toBottomOf="@+id/layout_test_score" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toEndOf="@+id/layout_test_score" | |||||
app:layout_constraintTop_toTopOf="@+id/layout_test_score"> | |||||
<TextView | |||||
android:id="@+id/tv_efficient_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="学习效率" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/bigSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<com.xkl.cdl.widget.MyRankingView | |||||
android:id="@+id/ranking_efficient" | |||||
android:layout_width="80dp" | |||||
android:layout_height="80dp" | |||||
android:gravity="center" | |||||
android:orientation="vertical" | |||||
app:backgroundColor="@color/translation" | |||||
app:borderWidth="4dp" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@id/tv_efficient_flag" | |||||
app:normalColor="@color/gray_1" | |||||
app:progressColor="@color/red_2" | |||||
tools:progressNumber="20"> | |||||
<TextView | |||||
android:id="@+id/tv_efficient" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
tools:text="12%" /> | |||||
<TextView | |||||
android:id="@+id/tv_efficient_state" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:gravity="center" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
tools:drawableStart="@drawable/ic_rise" | |||||
tools:text="+3.4%" /> | |||||
</com.xkl.cdl.widget.MyRankingView> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
<!--学习时长分析--> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_duration" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="12dp" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:padding="12dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/layout_test_score"> | |||||
<TextView | |||||
android:id="@+id/tv_duration_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="学习时长分析" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/bigSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<TextView | |||||
android:id="@+id/tv_duration_flag_1" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="12dp" | |||||
android:text="总学习时长" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_duration_flag" /> | |||||
<!--总学习时长--> | |||||
<TextView | |||||
android:id="@+id/tv_total_duration" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="36dp" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_duration_flag_1" | |||||
tools:text="12.1" /> | |||||
<TextView | |||||
android:id="@+id/tv_total_duration_unit" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="4dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/normalSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_total_duration" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_total_duration" | |||||
tools:text="小时" /> | |||||
<TextView | |||||
android:id="@+id/tv_duration_state" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="8dp" | |||||
android:gravity="center" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/normalSize" | |||||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_total_duration_unit" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_total_duration_unit" | |||||
tools:drawableStart="@drawable/ic_rise" | |||||
tools:text="+3.4%" /> | |||||
<TextView | |||||
android:id="@+id/tv_duration_range" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="8dp" | |||||
android:gravity="center" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_duration_state" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_duration_state" | |||||
android:text="(本周)" /> | |||||
<TextView | |||||
android:id="@+id/tv_valid_time_flag" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="20dp" | |||||
android:text="有效学习时长" | |||||
android:textColor="@color/red_2" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_review_time_flag" | |||||
app:layout_constraintHorizontal_chainStyle="spread" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_total_duration" /> | |||||
<TextView | |||||
android:id="@+id/tv_review_time_flag" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:text="有效复习时长" | |||||
android:textColor="@color/green_1" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_free_time_flag" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_valid_time_flag" | |||||
app:layout_constraintTop_toTopOf="@+id/tv_valid_time_flag" /> | |||||
<TextView | |||||
android:id="@+id/tv_free_time_flag" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:text="空闲时长" | |||||
android:textColor="@color/theme_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_review_time_flag" | |||||
app:layout_constraintTop_toTopOf="@+id/tv_valid_time_flag" /> | |||||
<TextView | |||||
android:id="@+id/tv_valid_time" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/red_2" | |||||
android:textSize="22dp" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_valid_time_flag" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_valid_time_flag" | |||||
tools:text="12.1" /> | |||||
<TextView | |||||
android:id="@+id/tv_valid_time_unit" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="4dp" | |||||
android:textColor="@color/red_2" | |||||
android:textSize="@dimen/smallerSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_valid_time" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_valid_time" | |||||
tools:text="小时" /> | |||||
<TextView | |||||
android:id="@+id/tv_review_time" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/green_1" | |||||
android:textSize="22dp" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_review_time_flag" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_review_time_flag" | |||||
tools:text="12.1" /> | |||||
<TextView | |||||
android:id="@+id/tv_review_time_unit" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="4dp" | |||||
android:textColor="@color/green_1" | |||||
android:textSize="@dimen/smallerSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_review_time" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_review_time" | |||||
tools:text="小时" /> | |||||
<TextView | |||||
android:id="@+id/tv_free_time" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/theme_color" | |||||
android:textSize="22dp" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_free_time_flag" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_free_time_flag" | |||||
tools:text="12.1" /> | |||||
<TextView | |||||
android:id="@+id/tv_free_time_unit" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="4dp" | |||||
android:textColor="@color/theme_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_free_time" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_free_time" | |||||
tools:text="小时" /> | |||||
<com.github.mikephil.charting.charts.BarChart | |||||
android:id="@+id/bar_chart" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="0dp" | |||||
app:layout_constraintDimensionRatio="343:200" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_valid_time" | |||||
android:layout_marginTop="10dp"/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
<!--课程进度--> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_course_progress" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="12dp" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:padding="12dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/layout_duration"> | |||||
<TextView | |||||
android:id="@+id/tv_course_progress_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="课程进度" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/bigSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:paddingTop="20dp" | |||||
android:paddingBottom="20dp" | |||||
android:layout_marginTop="12dp" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_course_progress_flag" | |||||
android:background="@drawable/shape_rounder_8_stroke_gray1" | |||||
> | |||||
<com.xkl.cdl.widget.MyRankingView | |||||
android:id="@+id/ranking_1" | |||||
android:layout_width="80dp" | |||||
android:layout_height="80dp" | |||||
android:gravity="center" | |||||
android:orientation="vertical" | |||||
app:backgroundColor="@color/translation" | |||||
app:borderWidth="4dp" | |||||
app:normalColor="@color/gray_1" | |||||
app:progressColor="@color/green_1" | |||||
tools:progressNumber="20" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toStartOf="@+id/ranking_2"> | |||||
<TextView | |||||
android:id="@+id/tv_ranking_1_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="11dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
android:text="已学章节" /> | |||||
<TextView | |||||
android:id="@+id/tv_ranking_1_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:gravity="center" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="11dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
tools:text="1/12" /> | |||||
</com.xkl.cdl.widget.MyRankingView> | |||||
<com.xkl.cdl.widget.MyRankingView | |||||
android:id="@+id/ranking_2" | |||||
android:layout_width="80dp" | |||||
android:layout_height="80dp" | |||||
android:gravity="center" | |||||
android:orientation="vertical" | |||||
app:backgroundColor="@color/translation" | |||||
app:borderWidth="4dp" | |||||
app:normalColor="@color/gray_1" | |||||
app:progressColor="@color/theme_color" | |||||
tools:progressNumber="20" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintStart_toEndOf="@+id/ranking_1" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toStartOf="@+id/ranking_3"> | |||||
<TextView | |||||
android:id="@+id/tv_ranking_2_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="11dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
tools:text="已学词汇量/已学知识点" /> | |||||
<TextView | |||||
android:id="@+id/tv_ranking_2_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:gravity="center" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="11dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
tools:text="1/12" /> | |||||
</com.xkl.cdl.widget.MyRankingView> | |||||
<com.xkl.cdl.widget.MyRankingView | |||||
android:id="@+id/ranking_3" | |||||
android:layout_width="80dp" | |||||
android:layout_height="80dp" | |||||
android:gravity="center" | |||||
android:orientation="vertical" | |||||
app:backgroundColor="@color/translation" | |||||
app:borderWidth="4dp" | |||||
app:normalColor="@color/gray_1" | |||||
app:progressColor="#8757E6" | |||||
tools:progressNumber="20" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintStart_toEndOf="@+id/ranking_2" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent"> | |||||
<TextView | |||||
android:id="@+id/tv_ranking_3_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="11dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
android:text="已学课堂练习" /> | |||||
<TextView | |||||
android:id="@+id/tv_ranking_3_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:gravity="center" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="11dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
tools:text="1/12" /> | |||||
</com.xkl.cdl.widget.MyRankingView> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
<!--章节学习情况--> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_chapter_info" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="12dp" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:padding="12dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/layout_course_progress"> | |||||
<TextView | |||||
android:id="@+id/tv_chapter_info_flag" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="章节学习情况" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/bigSize" | |||||
android:textStyle="bold" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<com.google.android.material.button.MaterialButton | |||||
android:id="@+id/tv_chapter_choose" | |||||
style="@style/Widget.MaterialComponents.Button.UnelevatedButton" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="24dp" | |||||
android:drawableEnd="@drawable/ic_down" | |||||
android:gravity="center" | |||||
android:insetTop="0dp" | |||||
android:insetBottom="0dp" | |||||
android:minWidth="124dp" | |||||
tools:text="第一章" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintBottom_toBottomOf="@+id/tv_chapter_info_flag" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toTopOf="@+id/tv_chapter_info_flag" | |||||
app:strokeColor="@color/gray_1" | |||||
app:strokeWidth="@dimen/line_height" | |||||
app:cornerRadius="4dp"/> | |||||
<androidx.recyclerview.widget.RecyclerView | |||||
android:id="@+id/rv_chapter_info" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_info_flag" | |||||
android:layout_marginTop="6dp"/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</androidx.core.widget.NestedScrollView> | |||||
</androidx.appcompat.widget.LinearLayoutCompat> | |||||
</layout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
xmlns:tools="http://schemas.android.com/tools" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:background="@color/white_1" | |||||
android:orientation="vertical" | |||||
tools:context=".module.m_statics.SubjectStatisticsDetailActivity"> | |||||
<com.suliang.common.widget.TitleBar | |||||
android:id="@+id/title_bar" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="@dimen/title_bar_height" | |||||
app:barBackground="@color/white"/> | |||||
<androidx.core.widget.NestedScrollView | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:background="@color/white_1"> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent"> | |||||
<androidx.fragment.app.FragmentContainerView | |||||
android:id="@+id/fragment_top_time" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="0dp" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginTop="@dimen/global_spacing" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
app:layout_constraintDimensionRatio="343:275" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<androidx.appcompat.widget.LinearLayoutCompat | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:layout_margin="@dimen/global_spacing" | |||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:orientation="vertical" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/fragment_top_time"> | |||||
<TextView | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:layout_margin="12dp" | |||||
android:text="课程综合分析" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/bigSize" | |||||
android:textStyle="bold" /> | |||||
<androidx.recyclerview.widget.RecyclerView | |||||
android:id="@+id/rv_course" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="0dp" | |||||
android:layout_weight="1" /> | |||||
</androidx.appcompat.widget.LinearLayoutCompat> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</androidx.core.widget.NestedScrollView> | |||||
</androidx.appcompat.widget.LinearLayoutCompat> | |||||
android:layout_marginStart="@dimen/global_spacing" | android:layout_marginStart="@dimen/global_spacing" | ||||
android:layout_marginTop="@dimen/global_spacing" | android:layout_marginTop="@dimen/global_spacing" | ||||
android:layout_marginEnd="@dimen/global_spacing" | android:layout_marginEnd="@dimen/global_spacing" | ||||
app:layout_constraintDimensionRatio="h,343:275" | |||||
app:layout_constraintDimensionRatio="343:275" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_title" /> | app:layout_constraintTop_toBottomOf="@+id/tv_title" /> | ||||
<!-- android:name="com.xkl.cdl.module.m_statics.StatisticsTimeTopFragment"--> | <!-- android:name="com.xkl.cdl.module.m_statics.StatisticsTimeTopFragment"--> | ||||
android:layout_marginEnd="@dimen/global_spacing" | android:layout_marginEnd="@dimen/global_spacing" | ||||
android:background="@drawable/shape_rounder_12_white" | android:background="@drawable/shape_rounder_12_white" | ||||
android:padding="12dp" | android:padding="12dp" | ||||
app:layout_constraintDimensionRatio="h,343:243" | |||||
app:layout_constraintDimensionRatio="343:243" | |||||
app:layout_constraintEnd_toEndOf="parent" | app:layout_constraintEnd_toEndOf="parent" | ||||
app:layout_constraintStart_toStartOf="parent" | app:layout_constraintStart_toStartOf="parent" | ||||
app:layout_constraintTop_toBottomOf="@+id/layout_english"> | app:layout_constraintTop_toBottomOf="@+id/layout_english"> | ||||
android:insetTop="0dp" | android:insetTop="0dp" | ||||
android:insetBottom="0dp" | android:insetBottom="0dp" | ||||
android:minWidth="124dp" | android:minWidth="124dp" | ||||
android:text="全部科目" | |||||
android:text="全部项目" | |||||
android:textColor="@color/main_text_color" | android:textColor="@color/main_text_color" | ||||
android:textSize="@dimen/smallerSize" | android:textSize="@dimen/smallerSize" | ||||
app:layout_constraintBottom_toBottomOf="@+id/chart_title" | app:layout_constraintBottom_toBottomOf="@+id/chart_title" | ||||
app:layout_constraintEnd_toEndOf="parent" | app:layout_constraintEnd_toEndOf="parent" | ||||
app:layout_constraintTop_toTopOf="@+id/chart_title" | app:layout_constraintTop_toTopOf="@+id/chart_title" | ||||
app:strokeColor="@color/gray_1" | app:strokeColor="@color/gray_1" | ||||
app:strokeWidth="@dimen/line_height" /> | |||||
app:strokeWidth="@dimen/line_height" | |||||
app:cornerRadius="4dp"/> | |||||
<com.github.mikephil.charting.charts.LineChart | <com.github.mikephil.charting.charts.LineChart | ||||
android:id="@+id/chart" | android:id="@+id/chart" |
app:layout_constraintHeight_min="128dp" | app:layout_constraintHeight_min="128dp" | ||||
android:layout_marginEnd="8dp" | android:layout_marginEnd="8dp" | ||||
android:scaleType="centerCrop" | android:scaleType="centerCrop" | ||||
app:layout_constraintDimensionRatio="h,102:136" | |||||
app:layout_constraintDimensionRatio="102:136" | |||||
app:layout_constraintEnd_toStartOf="@+id/barrier" | app:layout_constraintEnd_toStartOf="@+id/barrier" | ||||
app:layout_constraintStart_toStartOf="parent" | app:layout_constraintStart_toStartOf="parent" | ||||
app:layout_constraintTop_toTopOf="parent" /> | app:layout_constraintTop_toTopOf="parent" /> |
android:layout_height="0dp" | android:layout_height="0dp" | ||||
android:orientation="vertical" | android:orientation="vertical" | ||||
android:paddingStart="12dp" | android:paddingStart="12dp" | ||||
app:layout_constraintDimensionRatio="h,154:100" | |||||
app:layout_constraintDimensionRatio="154:100" | |||||
app:layout_constraintTop_toTopOf="parent"> | app:layout_constraintTop_toTopOf="parent"> | ||||
<TextView | <TextView |
<?xml version="1.0" encoding="utf-8"?> | |||||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:tools="http://schemas.android.com/tools" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto"> | |||||
<data> | |||||
</data> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="48dp" | |||||
android:paddingStart="@dimen/global_spacing" | |||||
android:paddingEnd="@dimen/global_spacing"> | |||||
<TextView | |||||
android:id="@+id/tv_name" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:textSize="@dimen/normalSize" | |||||
android:textColor="@color/main_text_color" | |||||
tools:text="课程名称" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_value" /> | |||||
<TextView | |||||
android:id="@+id/tv_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textSize="@dimen/normalSize" | |||||
android:textColor="@color/gray_2" | |||||
tools:text="12%" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" /> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</layout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
xmlns:tools="http://schemas.android.com/tools"> | |||||
<data> | |||||
<variable | |||||
name="course" | |||||
type="com.xkl.cdl.data.bean.StatisticsCourse" /> | |||||
</data> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="12dp"> | |||||
<com.google.android.material.imageview.ShapeableImageView | |||||
android:id="@+id/img_course" | |||||
android:layout_width="54dp" | |||||
android:layout_height="0dp" | |||||
app:layout_constraintDimensionRatio="54:72" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
android:layout_marginStart="14dp" | |||||
android:scaleType="fitXY" | |||||
tools:src="@color/main_text_color" | |||||
app:shapeAppearance="@style/roundedCornerStyle" | |||||
app:imageByteArray="@{course.cover}"/> | |||||
<androidx.constraintlayout.utils.widget.ImageFilterView | |||||
android:id="@+id/iv_arrow" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:src="@drawable/ic_arrow_right" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
android:layout_marginEnd="12dp" /> | |||||
<TextView | |||||
android:id="@+id/tv_course_name" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:maxLines="2" | |||||
android:ellipsize="end" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textColor="@color/main_text_color" | |||||
app:layout_constraintTop_toTopOf="@+id/img_course" | |||||
app:layout_constraintStart_toEndOf="@+id/img_course" | |||||
app:layout_constraintEnd_toStartOf="@+id/iv_arrow" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:layout_marginTop="4dp" | |||||
android:layout_marginStart="8dp" | |||||
tools:text="kjdkjsdkgjaskdlgjsadgjasldgddddffddfdfdffddjsakldgjsdakg" | |||||
android:text="@{course.course.courseTitle}"/> | |||||
<ProgressBar | |||||
android:id="@+id/progress_course" | |||||
android:layout_width="120dp" | |||||
android:layout_height="4dp" | |||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" | |||||
android:progressDrawable="@drawable/progress_center" | |||||
android:progressTint="@color/theme_color" | |||||
android:max="1000" | |||||
tools:progress="40" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_course_name" | |||||
app:layout_constraintBottom_toBottomOf="@+id/img_course" | |||||
android:layout_marginBottom="8dp" | |||||
app:courseStatisticsLearnProgressFormat="@{(int)course.course.courseLearnProgress}"/> | |||||
<TextView | |||||
android:id="@+id/tv_progress" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
app:layout_constraintBottom_toBottomOf="@+id/img_course" | |||||
app:layout_constraintStart_toEndOf="@+id/progress_course" | |||||
android:textSize="@dimen/smallerSize" | |||||
android:textColor="@color/main_text_color" | |||||
android:layout_marginStart="12dp" | |||||
android:layout_marginBottom="4dp" | |||||
tools:text="10%" | |||||
app:courseStatisticsLearnProgressTextViewFormat="@{(int)course.course.courseLearnProgress}"/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</layout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
xmlns:tools="http://schemas.android.com/tools"> | |||||
<data> | |||||
</data> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:background="@drawable/shape_rounder_8_stroke_gray1"> | |||||
<View | |||||
android:id="@+id/v_1" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="38dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<View | |||||
android:id="@+id/v_2" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="38dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/v_1" /> | |||||
<View | |||||
android:id="@+id/v_3" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="38dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/v_2" /> | |||||
<View | |||||
android:id="@+id/v_4" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="38dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/v_3" /> | |||||
<View | |||||
android:id="@+id/v_5" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="38dp" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/v_4" /> | |||||
<TextView | |||||
android:id="@+id/tv_1" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
android:text="课时" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@+id/v_1" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_1_value" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="@+id/v_1" /> | |||||
<TextView | |||||
android:id="@+id/tv_2" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
tools:text="课时" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@+id/v_2" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="@+id/v_2" /> | |||||
<TextView | |||||
android:id="@+id/tv_3" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
tools:text="课时" | |||||
tools:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@+id/v_3" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="@+id/v_3" /> | |||||
<TextView | |||||
android:id="@+id/tv_4" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
tools:text="课时" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@+id/v_4" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="@+id/v_4" /> | |||||
<TextView | |||||
android:id="@+id/tv_5" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
tools:text="课时" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@+id/v_5" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="@+id/v_5" /> | |||||
<TextView | |||||
android:id="@+id/tv_1_value" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginEnd="12dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_1" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_1" | |||||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||||
tools:text="课时名称" /> | |||||
<TextView | |||||
android:id="@+id/tv_2_value" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginEnd="12dp" | |||||
android:textColor="@color/theme_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_2" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="@id/tv_1_value" | |||||
app:layout_constraintTop_toTopOf="@+id/v_2" | |||||
tools:text="课时名称" /> | |||||
<TextView | |||||
android:id="@+id/tv_3_value" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginEnd="12dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_3" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="@id/tv_1_value" | |||||
app:layout_constraintTop_toTopOf="@+id/v_3" | |||||
tools:text="课时名称" /> | |||||
<ProgressBar | |||||
android:id="@+id/p_4" | |||||
android:layout_width="100dp" | |||||
android:layout_height="4dp" | |||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" | |||||
android:progressDrawable="@drawable/progress_center" | |||||
android:progressTint="@color/red_2" | |||||
android:max="100" | |||||
tools:progress="80" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_4" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_4_value" | |||||
app:layout_constraintStart_toStartOf="@id/tv_1_value" | |||||
app:layout_constraintTop_toTopOf="@+id/v_4" /> | |||||
<TextView | |||||
android:id="@+id/tv_4_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
app:layout_goneMarginStart="0dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_4" | |||||
app:layout_constraintStart_toEndOf="@+id/p_4" | |||||
app:layout_constraintTop_toTopOf="@+id/v_4" | |||||
tools:text="20" /> | |||||
<ProgressBar | |||||
android:id="@+id/p_5" | |||||
android:layout_width="100dp" | |||||
android:layout_height="4dp" | |||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" | |||||
android:progressDrawable="@drawable/progress_center" | |||||
android:progressTint="@color/theme_color" | |||||
android:max="100" | |||||
tools:progress="80" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_5" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_5_value" | |||||
app:layout_constraintStart_toStartOf="@id/tv_1_value" | |||||
app:layout_constraintTop_toTopOf="@+id/v_5" /> | |||||
<TextView | |||||
android:id="@+id/tv_5_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="12dp" | |||||
app:layout_goneMarginStart="0dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintBottom_toBottomOf="@id/v_5" | |||||
app:layout_constraintStart_toEndOf="@+id/p_5" | |||||
app:layout_constraintTop_toTopOf="@+id/v_5" | |||||
tools:text="20" /> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</layout> |
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:width="20dp" | |||||
android:height="20dp" | |||||
android:viewportWidth="20" | |||||
android:viewportHeight="20"> | |||||
<path | |||||
android:pathData="M0,0h20v20h-20z" | |||||
android:strokeAlpha="0" | |||||
android:strokeWidth="1" | |||||
android:fillColor="#000000" | |||||
android:fillType="nonZero" | |||||
android:strokeColor="#00000000" | |||||
android:fillAlpha="0"/> | |||||
<path | |||||
android:pathData="M16.6251,11.9417L3.3749,11.9417C2.9836,11.9417 2.6667,12.2586 2.6667,12.6499C2.6667,12.7986 2.7127,12.9367 2.7906,13.05C2.8242,13.1297 2.8756,13.204 2.9393,13.2695L6.0607,16.3891C6.1988,16.5272 6.3794,16.5963 6.5617,16.5963C6.7441,16.5963 6.9247,16.5272 7.0628,16.3891C7.339,16.1129 7.339,15.665 7.0628,15.387L5.0303,13.3581L16.6234,13.3581C17.0146,13.3581 17.3316,13.0411 17.3316,12.6499C17.3316,12.2586 17.0164,11.9417 16.6251,11.9417L16.6251,11.9417ZM3.3749,8.6557L16.6251,8.6557C17.0164,8.6557 17.3333,8.3387 17.3333,7.9475C17.3333,7.7987 17.2873,7.6606 17.2094,7.5473C17.1846,7.4889 17.1492,7.4323 17.1067,7.3791L14.5537,4.2595C14.3058,3.9568 13.8596,3.9125 13.5569,4.1604C13.2541,4.4083 13.2099,4.8544 13.4578,5.1572L15.1627,7.2393L3.3749,7.2393C2.9836,7.2393 2.6667,7.5562 2.6667,7.9475C2.6667,8.3387 2.9836,8.6557 3.3749,8.6557L3.3749,8.6557Z" | |||||
android:strokeWidth="1" | |||||
android:fillColor="#323233" | |||||
android:fillType="evenOdd" | |||||
android:strokeColor="#00000000"/> | |||||
</vector> |