@@ -31,6 +31,7 @@ | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/progress_center.xml" value="0.287962962962963" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/progress_statistics.xml" value="0.4425925925925926" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/progressbar_countdown_time.xml" value="0.45740740740740743" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/rb_select_white1_theme_bg.xml" value="0.34629629629629627" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/selector_memo_review_bg.xml" value="0.5010416666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/selector_memo_test_bg.xml" value="0.5010416666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shadow_layer.xml" value="0.4876923076923077" /> | |||
@@ -82,7 +83,9 @@ | |||
<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_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.3348694316436252" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_test_score.xml" value="0.31521739130434784" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_test_vocabulary.xml" value="0.18591691995947315" /> | |||
<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/dialog_bottom_auto_play_select.xml" value="0.4979166666666667" /> | |||
@@ -143,7 +146,10 @@ | |||
<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_2.xml" value="0.348731884057971" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_filter.xml" value="0.75" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_score.xml" value="0.33" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_video_adapter.xml" value="0.67" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_vocabulary_level.xml" value="0.23632218844984804" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_xpopup_statistics_choose_subject.xml" value="0.21965579710144928" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_course_progress.xml" value="0.25" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_coursepack.xml" value="0.43500866551126516" /> | |||
@@ -186,6 +192,8 @@ | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_right.xml" value="0.4425925925925926" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_spell.xml" value="0.5061538461538462" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_spoken.xml" value="0.5061538461538462" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_star.xml" value="0.49538461538461537" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_star_1.xml" value="0.49538461538461537" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_up.xml" value="0.503125" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_voice.xml" value="0.5061538461538462" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_wrong.xml" value="0.4425925925925926" /> |
@@ -16,6 +16,13 @@ android { | |||
versionName androidConfig.version_name | |||
multiDexEnabled true //解决64k 分包限制 | |||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | |||
javaCompileOptions { | |||
annotationProcessorOptions { | |||
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] | |||
} | |||
} | |||
} | |||
/*构建类型: 定义Gradle在构建阶段和打包应用时使用的某些属性*/ | |||
buildTypes { | |||
@@ -121,6 +128,16 @@ dependencies { | |||
implementation customDependencies.FlexBoxLayoutManager | |||
//图标 | |||
implementation customDependencies.Chart | |||
//Room | |||
implementation customDependencies.Room_Runtime | |||
kapt customDependencies.Room_Compiler | |||
//Paging | |||
// implementation customDependencies.Paging | |||
//Room_Paging | |||
// implementation(customDependencies.Room_Paging){ | |||
// force = true | |||
// } | |||
// implementation "me.zhanghai.android.materialratingbar:library:1.4.0" | |||
implementation 'com.xl.ratingbar:ratingbar:0.1.1' | |||
} |
@@ -1,7 +1,7 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
package="com.xkl.cdl" > | |||
package="com.xkl.cdl"> | |||
<application | |||
android:name=".module.XKLApplication" | |||
@@ -11,7 +11,13 @@ | |||
android:roundIcon="@mipmap/ic_launcher_round" | |||
android:supportsRtl="true" | |||
android:theme="@style/Theme.XklLocal" | |||
tools:ignore="LockedOrientationActivity" > | |||
tools:ignore="LockedOrientationActivity"> | |||
<activity | |||
android:name=".module.m_service_center.TestVocabularyActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.m_service_center.TestScoreActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.m_statics.CourseStatisticsDetailActivity" | |||
android:exported="true" /> | |||
@@ -54,7 +60,7 @@ | |||
android:configChanges="orientation|keyboardHidden|screenSize" | |||
android:exported="true" | |||
android:screenOrientation="portrait" | |||
android:theme="@style/Theme.Splash" > | |||
android:theme="@style/Theme.Splash"> | |||
<intent-filter> | |||
<action android:name="android.intent.action.MAIN" /> | |||
@@ -0,0 +1,43 @@ | |||
package com.xkl.cdl.adapter | |||
import android.annotation.SuppressLint | |||
import android.view.ViewGroup | |||
import com.google.android.flexbox.FlexboxLayoutManager | |||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||
import com.suliang.common.base.adapter.BaseRVAdapter | |||
import com.suliang.common.base.adapter.BaseRVAdapterVM | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.databinding.ItemTestFilterBinding | |||
import com.xkl.cdl.module.m_service_center.TestScoreViewModel | |||
/** | |||
* author suliang | |||
* create 2022/7/8 14:44 | |||
* Describe: 测试成绩筛选适配器 | |||
*/ | |||
class AdapterTestFilter(vm:TestScoreViewModel) : BaseRVAdapterVM<String,TestScoreViewModel>(vm) { | |||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_test_filter)) | |||
} | |||
@SuppressLint("NotifyDataSetChanged") | |||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||
(holder.binding as ItemTestFilterBinding).rb.run { | |||
text = getItem(position) | |||
isChecked = vm.filterPosition.value == position | |||
click { | |||
if (vm.filterPosition.value != position){ | |||
vm.filterPosition.value = position | |||
notifyDataSetChanged() | |||
} | |||
} | |||
//加上这句话,保证主轴上的子view均分主轴剩余空间 | |||
// if (layoutParams is FlexboxLayoutManager.LayoutParams){ | |||
// (layoutParams as FlexboxLayoutManager.LayoutParams).flexGrow = 1f | |||
// } | |||
} | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
package com.xkl.cdl.adapter | |||
import android.annotation.SuppressLint | |||
import android.view.LayoutInflater | |||
import android.view.ViewGroup | |||
import androidx.databinding.DataBindingUtil | |||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||
import com.suliang.common.base.adapter.BaseRVAdapterVM | |||
import com.suliang.common.databinding.ItemEmptyBinding | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.extension.setHtml | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.exam_record.Exam | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.databinding.ItemTestScoreBinding | |||
import com.xkl.cdl.module.m_service_center.TestScoreViewModel | |||
/** | |||
* author suliang | |||
* create 2022/7/8 10:45 | |||
* Describe: | |||
*/ | |||
class AdapterTestScore(vm : TestScoreViewModel) : BaseRVAdapterVM<Exam,TestScoreViewModel>(vm) { | |||
override fun onBindEmptyViewHolder(holder : BaseAdapterViewHolder) { | |||
(holder.binding as ItemEmptyBinding).apply { | |||
val nullOrEmpty = vm.keyWordSearch.value.isNullOrEmpty() | |||
imgEmpty.setImageResource(if (nullOrEmpty) R.mipmap.empty_nothing else R.mipmap.empty_nothing_search) | |||
tvContent.setText(if (nullOrEmpty) R.string.empty_nothing else R.string.empty_nothing_search) | |||
} | |||
} | |||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.item_test_score,parent,false)) | |||
} | |||
@SuppressLint("SetTextI18n") | |||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||
(holder.binding as ItemTestScoreBinding).run { | |||
tvMarkNumber.text = "${position + 1}" | |||
getItem(position).let { | |||
val split = it.title.split("@@") | |||
if (split.size > 1){ | |||
tvTitle.setHtml("${split[0]}<font color = \'#8A8A99\'><small>(${split[1]})</small></font>") | |||
}else{ | |||
tvTitle.text = it.title | |||
} | |||
tvExamType.text = if (CourseManager.isSpokenAfterDialogueTest(it.examType,it.ext)){ | |||
"口语练习" | |||
}else CourseManager.getExamTypeName(it.examType) | |||
tvCreateTime.text = it.createTime | |||
tvScore.text = if (it.examType == AppConstants.TEST_TYPE_NORMAL){ | |||
if (it.score > 0) it.score.toInt().toString() else "较少" | |||
}else if (CourseManager.isSpokenAfterDialogueTest(it.examType,it.ext)){ | |||
"完成" | |||
}else it.score.toInt().toString() | |||
} | |||
root.click { | |||
if (onItemClickIsInitialized()){ | |||
onItemClick.invoke(it,position,getItem(position)) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/* | |||
class AdapterTestScore(val vm : TestScoreViewModel) : PagingDataAdapter<Exam,BaseAdapterViewHolder>(diffCallback) { | |||
companion object{ | |||
private val diffCallback = object : DiffUtil.ItemCallback<Exam>(){ | |||
override fun areItemsTheSame(oldItem : Exam, newItem : Exam) : Boolean = oldItem.id == newItem.id | |||
override fun areContentsTheSame(oldItem : Exam, newItem : Exam) : Boolean = oldItem == newItem | |||
} | |||
} | |||
@SuppressLint("SetTextI18n") | |||
override fun onBindViewHolder(holder : BaseAdapterViewHolder, position : Int) { | |||
(holder.binding as ItemTestScoreBinding).run { | |||
tvMarkNumber.text = "${position + 1}" | |||
getItem(position)?.let { | |||
val split = it.title.split("@@") | |||
if (split.size > 1){ | |||
tvTitle.setHtml("${split[0]}<font color = \'#8A8A99\'><small>(${split[1]})</small></font>") | |||
}else{ | |||
tvTitle.text = it.title | |||
} | |||
tvExamType.text = if (CourseManager.isSpokenAfterDialogueTest(it.examType,it.ext)){ | |||
"口语练习" | |||
}else CourseManager.getExamTypeName(it.examType) | |||
tvCreateTime.text = it.createTime | |||
tvScore.text = if (it.examType == AppConstants.TEST_TYPE_NORMAL){ | |||
if (it.score > 0) it.score.toInt().toString() else "较少" | |||
}else if (CourseManager.isSpokenAfterDialogueTest(it.examType,it.ext)){ | |||
"完成" | |||
}else it.score.toInt().toString() | |||
} | |||
} | |||
} | |||
override fun onCreateViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.item_test_score,parent,false)) | |||
} | |||
}*/ |
@@ -0,0 +1,8 @@ | |||
package com.xkl.cdl.data.bean | |||
/** | |||
* author suliang | |||
* create 2022/7/13 10:48 | |||
* Describe: | |||
*/ | |||
class VocabularyItem(val icon: Int, val level: String,val level_e: String) |
@@ -0,0 +1,85 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Database | |||
import androidx.room.Room | |||
import androidx.room.RoomDatabase | |||
import com.suliang.common.util.file.FileUtil | |||
import com.xkl.cdl.module.XKLApplication | |||
import mqComsumerV1.Struct | |||
import java.io.File | |||
/** | |||
* author suliang | |||
* create 2022/7/7 16:50 | |||
* Describe: | |||
*/ | |||
@Database(entities = [Exam::class,ExamItem::class],version = 1,exportSchema = true) | |||
abstract class AppDatabase : RoomDatabase() { | |||
abstract fun examDao() : ExamDao | |||
abstract fun examItemDao(): ExamItemDao | |||
abstract fun examMiddleDao(): ExamMiddleDao | |||
companion object{ | |||
private var DATABASE_NAME :String = "${FileUtil.getSaveDirPath("db")}${File.separator}app.db" | |||
val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { | |||
Room.databaseBuilder(XKLApplication.instance(), AppDatabase::class.java, DATABASE_NAME).build() | |||
} | |||
@JvmStatic | |||
fun examBuilderToExamWithDetail(learnExam : Struct.LearnExam) : ExamWithDetail { | |||
val exam = learnExam.run { | |||
Exam(projectId.toInt(), packId, courseId, chapterId, lessonId, title, type.toInt(), score, totalNum.toInt(), | |||
correctNum.toInt(), errorNum.toInt(), unanswerNum.toInt(), typeId, duration, ext, created, coverRate.toInt(), | |||
stage) | |||
} | |||
val examItemList = mutableListOf<ExamItem>().apply { | |||
learnExam.recordList.forEach { | |||
add(ExamItem(it.questionId, it.questionType.toInt(), it.question, it.userAnswer, it.answerStatus.toInt(), | |||
it.duration)) | |||
} | |||
} | |||
return ExamWithDetail(exam, examItemList) | |||
} | |||
@JvmStatic | |||
fun examWithDetailToExamBuild(examWithDetail : ExamWithDetail) : Struct.LearnExam { | |||
val examRecordList = mutableListOf<Struct.ExamRecord>().apply { | |||
examWithDetail.examItemList.forEach { | |||
add(Struct.ExamRecord.newBuilder().apply { | |||
questionId = it.questionId | |||
questionType = it.questionType.toLong() | |||
question = it.question | |||
userAnswer = it.userAnswer | |||
answerStatus = it.answerStatus.toLong() | |||
duration = it.duration | |||
}.build()) | |||
} | |||
} | |||
return Struct.LearnExam.newBuilder().apply { | |||
examWithDetail.exam.let { | |||
projectId = it.projectId.toLong() | |||
packId = it.packId | |||
courseId = it.courseId | |||
chapterId = it.chapterId | |||
lessonId = it.lessonId | |||
title = it.title | |||
type = it.examType.toLong() | |||
score = it.score | |||
totalNum = it.totalNum.toLong() | |||
correctNum = it.correctNum.toLong() | |||
errorNum = it.errorNum.toLong() | |||
unanswerNum = it.unAnswerNum.toLong() | |||
duration = it.duration | |||
ext = it.ext | |||
created = it.createTime | |||
typeId = it.typeId | |||
coverRate = it.coverRate.toFloat() | |||
stage = it.stage | |||
} | |||
addAllRecord(examRecordList) | |||
}.build() | |||
} | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Entity | |||
import androidx.room.PrimaryKey | |||
/** | |||
* author suliang | |||
* create 2022/7/7 15:27 | |||
* Describe: 测试试卷 | |||
*/ | |||
@Entity(tableName = "exam") | |||
data class Exam(val projectId : Int, | |||
val packId : Long, | |||
val courseId : Long, | |||
val chapterId : Long, //章节测试必传 | |||
val lessonId : Long, //课时id | |||
val title : String, //测试试卷名称 | |||
val examType : Int, | |||
val score : Float, | |||
val totalNum : Int, | |||
val correctNum : Int, | |||
val errorNum : Int, | |||
val unAnswerNum : Int, | |||
val typeId : Long, //作文必传,课程类型 | |||
val duration : Long, //测试所用时间 毫秒 | |||
val ext : String, //扩展字段 json | |||
val createTime : String, //创建时间 | |||
val coverRate : Int, // 覆盖率 | |||
//词汇量测试测试阶段) | |||
val stage : String) { | |||
@PrimaryKey(autoGenerate = true) | |||
var id : Long = 0L | |||
} |
@@ -0,0 +1,126 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Dao | |||
import androidx.room.Insert | |||
import androidx.room.Query | |||
import androidx.room.RawQuery | |||
import androidx.sqlite.db.SimpleSQLiteQuery | |||
import androidx.sqlite.db.SupportSQLiteQuery | |||
import com.suliang.common.util.LogUtil | |||
/** | |||
* author suliang | |||
* create 2022/7/7 16:04 | |||
* Describe: | |||
*/ | |||
@Dao | |||
interface ExamDao { | |||
/** | |||
* 插入 | |||
* @param exam Exam | |||
* @return Long | |||
*/ | |||
@Insert | |||
fun insert(exam:Exam) : Long | |||
@RawQuery | |||
fun query(query : SupportSQLiteQuery) : List<Exam> | |||
/** | |||
* 查询,实现拼接查询功能 | |||
* @param isAll Boolean? 是否全部 | |||
* @param examType Long? 测试类型 | |||
* @param projectId Long? 项目查询 | |||
* @param keyWord String? 关键词查询 | |||
* @param lastId Long 最后一条的id,初始默认为0 | |||
* @param pageSize Int 页码查询 | |||
*/ | |||
fun queryS(isAll:Boolean = false , examType:Int? ,projectId:Int? , keyWord_ : String? , lastId: Long?, pageSize : Int = 50 ) : List<Exam>{ | |||
val keyWord = if (keyWord_.isNullOrBlank()) null else keyWord_ | |||
val sql = when{ | |||
isAll -> keyWord ?. let { | |||
lastId?.let { | |||
"SELECT * FROM exam WHERE id < $lastId AND title LIKE %$keyWord% ORDER BY id DESC LIMIT $pageSize" | |||
}?:let { | |||
"SELECT * FROM exam WHERE title LIKE %$keyWord% ORDER BY id DESC LIMIT $pageSize" | |||
} | |||
} ?:let { | |||
lastId?.let { | |||
"SELECT * FROM exam WHERE id < $lastId ORDER BY id DESC LIMIT $pageSize" | |||
}?:let { | |||
"SELECT * FROM exam ORDER BY id DESC LIMIT $pageSize" | |||
} | |||
} | |||
//课程测试的英语测试和作文测试 | |||
examType != null && projectId != null -> keyWord ?. let { | |||
lastId?.let { | |||
"SELECT * FROM exam WHERE id < $lastId AND examType = $examType AND projectId = $projectId AND title LIKE %$keyWord% ORDER BY id DESC LIMIT $pageSize" | |||
}?:let { | |||
"SELECT * FROM exam WHERE examType = $examType AND projectId = $projectId AND title LIKE %$keyWord% ORDER BY id DESC LIMIT $pageSize" | |||
} | |||
} ?:let { | |||
lastId?.let { | |||
"SELECT * FROM exam WHERE id < $lastId AND examType = $examType AND projectId = $projectId ORDER BY id DESC LIMIT $pageSize" | |||
}?:let { | |||
"SELECT * FROM exam WHERE examType = $examType AND projectId = $projectId ORDER BY id DESC LIMIT $pageSize" | |||
} | |||
} | |||
examType != null -> keyWord ?. let { | |||
lastId?.let { | |||
"SELECT * FROM exam WHERE id < $lastId AND examType = $examType AND title LIKE %$keyWord% ORDER BY id DESC LIMIT $pageSize" | |||
}?:let { | |||
"SELECT * FROM exam WHERE examType = $examType AND title LIKE %$keyWord% ORDER BY id DESC LIMIT $pageSize" | |||
} | |||
} ?:let { | |||
lastId?.let { | |||
"SELECT * FROM exam WHERE id < $lastId AND examType = $examType ORDER BY id DESC LIMIT $pageSize" | |||
}?:let { | |||
"SELECT * FROM exam WHERE examType = $examType ORDER BY id DESC LIMIT $pageSize" | |||
} | |||
} | |||
else -> "" | |||
} | |||
LogUtil.e(sql) | |||
return query(SimpleSQLiteQuery(sql)) | |||
} | |||
/* *//** | |||
* 查询所有 | |||
* @param examId Long | |||
* @return List<Exam> | |||
*//* | |||
@Query("SELECT * FROM exam ORDER BY id DESC") | |||
// fun queryAll(): PagingSource<Int,Exam> //分页加载 | |||
fun query(examId: Long): List<Exam> | |||
*//** | |||
* 根据项目id查询 | |||
* @param projectId Int | |||
* @return List<Exam> | |||
*//* | |||
@Query("SELECT * FROM exam WHERE projectId = :projectId") | |||
fun queryWithProjectId(projectId: Int) : List<Exam> | |||
*//** | |||
* 根据测试类型查询 | |||
* @param examType Int | |||
* @return List<Exam> | |||
*//* | |||
@Query("SELECT * FROM exam WHERE examType = :examType") | |||
fun queryWithExamType(examType:Int) : List<Exam> | |||
*//** 关键字模糊查询 | |||
* @param keyWord String 关键字 | |||
* @return List<Exam> | |||
*//* | |||
@Query("SELECT * FROM exam WHERE title LIKE '%' || :keyWord || '%'") | |||
fun queryWithKeyWord(keyWord: String) : List<Exam> | |||
*/ | |||
} |
@@ -0,0 +1,21 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Entity | |||
import androidx.room.PrimaryKey | |||
/** | |||
* author suliang | |||
* create 2022/7/7 15:38 | |||
* Describe: 测试记录的item | |||
*/ | |||
@Entity(tableName = "exam_item") | |||
data class ExamItem( val questionId : Long , | |||
val questionType : Int, | |||
val question : String, //题目和选项答案信息,json | |||
val userAnswer : String, //用户答案 | |||
val answerStatus : Int, //回答状态(1:正确 0:未答 -1:错误) | |||
val duration : Long //用时 | |||
) { | |||
@PrimaryKey(autoGenerate = true) var itemId : Long = 0 | |||
var examId : Long = 0 // 试卷Exam所属id | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Dao | |||
import androidx.room.Insert | |||
/** | |||
* author suliang | |||
* create 2022/7/7 16:48 | |||
* Describe: | |||
*/ | |||
@Dao | |||
interface ExamItemDao { | |||
@Insert | |||
fun insertAll(vararg examItem: ExamItem) | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Dao | |||
import androidx.room.Insert | |||
import androidx.room.Query | |||
import androidx.room.Transaction | |||
import com.xkl.cdl.data.AppConstants | |||
/** | |||
* author suliang | |||
* create 2022/7/7 18:00 | |||
* Describe: 中间数据类 | |||
*/ | |||
@Dao | |||
interface ExamMiddleDao { | |||
@Insert | |||
fun insert(db : AppDatabase,exam:ExamWithDetail){ | |||
val insertId = db.examDao().insert(exam.exam) | |||
if (exam.exam.examType != AppConstants.TEST_TYPE_NORMAL) { | |||
exam.examItemList.forEach { | |||
it.examId = insertId | |||
} | |||
db.examItemDao().insertAll(*exam.examItemList.toTypedArray()) | |||
} | |||
} | |||
/** | |||
* 查询试卷与内容详情 | |||
* @param examId Long exam 存储唯一键id | |||
* @return Exam | |||
*/ | |||
@Transaction | |||
@Query("SELECT * FROM exam WHERE id = :examId") | |||
fun queryDetail(examId : Long): ExamWithDetail | |||
} |
@@ -0,0 +1,13 @@ | |||
package com.xkl.cdl.data.exam_record | |||
import androidx.room.Embedded | |||
import androidx.room.Relation | |||
/** | |||
* author suliang | |||
* create 2022/7/7 16:00 | |||
* Describe: 试卷与试卷题目关联 | |||
*/ | |||
data class ExamWithDetail(@Embedded val exam : Exam, | |||
@Relation(parentColumn = "id", entityColumn = "examId") | |||
val examItemList : List<ExamItem>) |
@@ -1,5 +1,6 @@ | |||
package com.xkl.cdl.data.manager | |||
import android.text.TextUtils | |||
import appApi.AppApi | |||
import com.suliang.common.util.AppGlobals | |||
import com.suliang.common.util.DateUtil | |||
@@ -8,6 +9,7 @@ import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.CoursePack | |||
import com.xkl.cdl.data.bean.course.ExamBean | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import org.json.JSONObject | |||
import java.io.* | |||
import java.lang.Exception | |||
import java.math.BigDecimal | |||
@@ -498,4 +500,24 @@ object CourseManager { | |||
return result | |||
} | |||
/** | |||
* 是否是口语对话练习 | |||
* @param examType Int | |||
* @param ext String | |||
* @return Boolean | |||
*/ | |||
fun isSpokenAfterDialogueTest(examType : Int, ext : String) : Boolean { | |||
if (examType == AppConstants.TEST_TYPE_AFTER && !TextUtils.isEmpty(ext)){ | |||
try { | |||
val jsonObject = JSONObject(ext) | |||
val courseType = jsonObject.getInt("courseType") | |||
val lessonType = if (jsonObject.has("lessonType")) jsonObject.getInt("lessonType") else -1 | |||
return courseType == AppConstants.COURSE_TYPE_ENGLISH_SPOKEN && lessonType == AppConstants.LESSON_TYPE_DIALOGUE | |||
} catch (e : Exception) { | |||
e.printStackTrace() | |||
} | |||
} | |||
return false | |||
} | |||
} |
@@ -12,6 +12,23 @@ import java.io.File | |||
class FilePathManager { | |||
companion object{ | |||
/** | |||
* 获取测词汇量数据所在的地址 | |||
* @return File | |||
*/ | |||
@JvmStatic | |||
fun getVocabularyDbPath(): File{ | |||
return File(getDbRootPath(), "vocabulary.db") | |||
} | |||
/** | |||
* 获取词典数据所在的地址 | |||
* @return File | |||
*/ | |||
@JvmStatic | |||
fun getDictionaryDbPath(): File{ | |||
return File(getDbRootPath(), "dictionary.db") | |||
} | |||
/** | |||
* 获取课程包目录数据所在的地址 | |||
* @return File |
@@ -0,0 +1,48 @@ | |||
package com.xkl.cdl.data.manager.db | |||
import android.widget.Toast | |||
import appApi.AppApi | |||
import com.suliang.common.util.AppGlobals | |||
import com.suliang.common.util.thread.AppExecutors | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.VocabularyItem | |||
import com.xkl.cdl.data.bean.course.ExamBean | |||
import com.xkl.cdl.data.manager.FilePathManager | |||
import net.sqlcipher.database.SQLiteDatabase | |||
/** | |||
* author suliang | |||
* create 2022/7/14 17:28 | |||
* Describe: | |||
*/ | |||
object VocabularyManager { | |||
private var mDataBase : SQLiteDatabase? = null | |||
private fun open() { | |||
synchronized(VocabularyManager) { | |||
if (mDataBase == null) { | |||
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getVocabularyDbPath().path, "", null, SQLiteDatabase.OPEN_READONLY) | |||
} | |||
if (mDataBase == null) { | |||
AppExecutors.mainThread.run { | |||
Toast.makeText(AppGlobals.application, "词汇量测试数据获取失败,请重启应用或联系业务员", Toast.LENGTH_LONG) | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* 查询词汇量测试数据 | |||
* @param level VocabularyItem | |||
* @return List<ExamBean> | |||
*/ | |||
fun queryVocabularyTestData(level : VocabularyItem) : List<ExamBean>{ | |||
open() | |||
val result = mutableListOf<ExamBean>() | |||
val sql = "SELECT * FROM " | |||
} | |||
} |
@@ -9,6 +9,10 @@ import com.suliang.common.util.file.FileUtil | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.course.CourseDetail | |||
import com.xkl.cdl.data.bean.course.Lesson | |||
import com.xkl.cdl.data.exam_record.AppDatabase | |||
import com.xkl.cdl.data.exam_record.Exam | |||
import com.xkl.cdl.data.exam_record.ExamItem | |||
import com.xkl.cdl.data.exam_record.ExamWithDetail | |||
import com.xkl.cdl.data.manager.db.DBCourseManager | |||
import com.xkl.cdl.data.manager.db.DbControlBase | |||
import com.xkl.cdl.module.XKLApplication | |||
@@ -16,40 +20,41 @@ import io.reactivex.rxjava3.core.Observable | |||
import mqComsumerV1.Struct | |||
import java.io.File | |||
import java.io.FileOutputStream | |||
import kotlin.math.sign | |||
/** | |||
* author suliang | |||
* create 2022/3/29 10:24 | |||
* Describe: 数据提供 | |||
*/ | |||
* author suliang | |||
* create 2022/3/29 10:24 | |||
* Describe: 数据提供 | |||
*/ | |||
object DataRepository { | |||
// TODO: 2022/6/1 需自己实现获取课程收藏数据,同时需自己处理保存数据 | |||
/** 获取课程的收藏本 */ | |||
fun getCourseCollect() : Observable<HashMap<String,Long>>{ | |||
return Observable.create{ | |||
fun getCourseCollect() : Observable<HashMap<String, Long>> { | |||
return Observable.create { | |||
it.onNext(hashMapOf()) | |||
it.onComplete() | |||
} | |||
} | |||
/** 获取复习的内容 */ | |||
fun getReviewData(subjectId : Int,coursePackId : Long,courseId : Long) : Observable<ProtocolStringList> { | |||
return Observable.create{ | |||
fun getReviewData(subjectId : Int, coursePackId : Long, courseId : Long) : Observable<ProtocolStringList> { | |||
return Observable.create { | |||
val wordList = XKLApplication.mobileCache.getWordList(subjectId.toLong(), coursePackId, courseId, 2) | |||
val parseFrom = wordList?.let { | |||
AppApi.GetWordListResponse.parseFrom(wordList) | |||
}?: AppApi.GetWordListResponse.newBuilder().build() | |||
} ?: AppApi.GetWordListResponse.newBuilder().build() | |||
it.onNext(parseFrom.wrongList) | |||
it.onComplete() | |||
} | |||
} | |||
/** 获取课程的详情 */ | |||
fun getCourseDetails(subjectId:Int, coursePackId:Long, courseId:Long): Observable<CourseDetail>{ | |||
return Observable.create{ | |||
fun getCourseDetails(subjectId : Int, coursePackId : Long, courseId : Long) : Observable<CourseDetail> { | |||
return Observable.create { | |||
val pbCourseDetail = XKLApplication.mobileCache.courseDetail(subjectId.toLong(), coursePackId, courseId).let { | |||
AppApi.CourseDetailResponse .parseFrom(it).detail | |||
AppApi.CourseDetailResponse.parseFrom(it).detail | |||
} | |||
val courseDetail = CourseDetail().apply { | |||
courseLearnProgress = pbCourseDetail.s //课程学习进度 | |||
@@ -64,7 +69,7 @@ object DataRepository { | |||
exam_w_r_list = HashMap( | |||
pbCourseDetail.examWRListMap) //课程/课时学前测试正确错误列表 key=> {chapter_id}_{lesson_id}_{entity_id} value=>正确 true;错误 false | |||
course_learn_point = pbCourseDetail.lp //课程学习进度点 {chapter_id}_{lesson_id}_{entity_id} | |||
vp = HashMap(pbCourseDetail.vpMap) //视频播放点,记录最新的就行 时间点 key=>video_id value=>{时间点} | |||
ct = pbCourseDetail.ct //课程已学词汇量 | |||
e = pbCourseDetail.e //学习效率 | |||
@@ -80,7 +85,7 @@ object DataRepository { | |||
// rl: Int = 0 //课程重学次数;有值表示是重新学,默认不是重新学习,对应数值表示第几次重学 用于辨音,拼写判断是否解锁, | |||
// chapter_rl: HashMap<String, Long> = hashMapOf() //章节重学次数,key =>{chapter_id}_{lesson_id} value=> relearn times | |||
} | |||
it.onNext(courseDetail) | |||
it.onComplete() | |||
// T这里自己使用的缓存 | |||
@@ -90,14 +95,14 @@ object DataRepository { | |||
// }else{ | |||
// CourseDetail() | |||
// } | |||
} | |||
} | |||
/** 获取课程课时 */ | |||
fun getCourseAllLesson(base: DbControlBase,courseDetail: CourseDetail):Observable<List<Lesson>>{ | |||
return Observable.create{ | |||
it.onNext(DBCourseManager.queryAllLesson(base,courseDetail)) | |||
fun getCourseAllLesson(base : DbControlBase, courseDetail : CourseDetail) : Observable<List<Lesson>> { | |||
return Observable.create { | |||
it.onNext(DBCourseManager.queryAllLesson(base, courseDetail)) | |||
it.onComplete() | |||
} | |||
} | |||
@@ -107,11 +112,11 @@ object DataRepository { | |||
* @param record Builder | |||
* @return Boolean | |||
*/ | |||
fun saveRecord(record : Struct.Record.Builder): Boolean { | |||
fun saveRecord(record : Struct.Record.Builder) : Boolean { | |||
var subjectId : Long = 0 | |||
var coursePackId : Long = 0 | |||
var courseId : Long = 0 | |||
when{ | |||
when { | |||
record.entityCount > 0 -> { | |||
record.getEntity(0).let { | |||
subjectId = it.projectId | |||
@@ -137,15 +142,23 @@ object DataRepository { | |||
LogUtil.e("保存数据 -> \n ${JsonFormat.printToString(record.build())}") | |||
try { | |||
XKLApplication.mobileCache.parseData(record.build().toByteArray()) | |||
if (subjectId != 0L ){ | |||
//如果是测试数据,进行数据转换,并将数据进行保存 | |||
if (record.examCount > 0) { | |||
val examWithDetail = AppDatabase.examBuilderToExamWithDetail(record.getExam(0)) | |||
AppDatabase.instance.examMiddleDao().insert(AppDatabase.instance,examWithDetail) | |||
} | |||
if (subjectId != 0L) { | |||
//计算词汇量和学习效率 | |||
calcCourseVocabularyAndEfficiency(subjectId,coursePackId,courseId) | |||
calcCourseVocabularyAndEfficiency(subjectId, coursePackId, courseId) | |||
} | |||
} catch (e : Exception) { | |||
e.printStackTrace() | |||
return false | |||
} | |||
/*var fileName = "" | |||
//写入文件 | |||
if (record.examCount > 0 ){ //当前为测试 | |||
@@ -180,17 +193,19 @@ object DataRepository { | |||
FileUtil.writeBytesToFile(it,saveByteArrayName,saveArray) | |||
}*/ | |||
return true | |||
return true | |||
} | |||
// TODO: 2022/6/1 计算词汇量和效率可以在需要的时候进行计算后再获取 | |||
/** | |||
* 计算当前词汇量 与 学习效率 | |||
*/ | |||
private fun calcCourseVocabularyAndEfficiency( projectId:Long, packId:Long, courseId:Long) { | |||
private fun calcCourseVocabularyAndEfficiency(projectId : Long, packId : Long, courseId : Long) { | |||
Observable.create<Boolean> { | |||
try { | |||
XKLApplication.mobileCache.calcCurrentVocabulary(projectId) //词汇量 | |||
XKLApplication.mobileCache.calcEfficiency(projectId,packId,courseId) //效率 | |||
XKLApplication.mobileCache.calcEfficiency(projectId, packId, courseId) //效率 | |||
} catch (e : Exception) { | |||
e.printStackTrace() | |||
} | |||
@@ -199,15 +214,15 @@ object DataRepository { | |||
} | |||
/** 获取备忘本可测试的课时 */ | |||
fun queryMemoLesson(base: DbControlBase,memoList: MutableList<String>):Observable<List<Lesson>>{ | |||
return Observable.create{ | |||
it.onNext(DBCourseManager.queryMemoLesson(base,memoList)) | |||
fun queryMemoLesson(base : DbControlBase, memoList : MutableList<String>) : Observable<List<Lesson>> { | |||
return Observable.create { | |||
it.onNext(DBCourseManager.queryMemoLesson(base, memoList)) | |||
it.onComplete() | |||
} | |||
} | |||
/** 获取词条数统计 */ | |||
fun getStatisticsChartData(projectId:Int): Observable<AppApi.EntityCountListResponse> { | |||
fun getStatisticsChartData(projectId : Int) : Observable<AppApi.EntityCountListResponse> { | |||
return Observable.create { | |||
//近90天词条数统计 | |||
val entityCountList = XKLApplication.mobileCache.entityCountList(projectId.toLong(), 0) | |||
@@ -217,4 +232,5 @@ object DataRepository { | |||
} | |||
} | |||
} |
@@ -13,6 +13,7 @@ import net.sqlcipher.database.SQLiteDatabase | |||
import java.io.File | |||
import java.io.IOException | |||
import java.util.* | |||
import kotlin.properties.Delegates | |||
/** | |||
* author suliang | |||
@@ -26,11 +27,14 @@ class XKLApplication : Application() { | |||
val file : String = File(FileUtil.getSaveDirFile("db"), "mydb").absolutePath | |||
Mobile_cache.new_(file) | |||
} | |||
private var instance : XKLApplication by Delegates.notNull() | |||
fun instance() = instance | |||
} | |||
override fun onCreate() { | |||
super.onCreate() | |||
instance = this | |||
SQLiteDatabase.loadLibs(this) | |||
LogUtil.e(UUID.randomUUID().toString().replace("-","")) | |||
//初始MMKV存储 |
@@ -84,10 +84,10 @@ class MemoTestActivity : BaseActivityVM<ActivityMemoTestBinding, MemoTestViewMod | |||
1 -> { //备忘本 | |||
binding.tvCourse.setHtml("当前课程:<font color=\'#5082E6\'>${vm.memoData.course.courseTitle}</font>") | |||
binding.rbMemo.isChecked = true | |||
binding.tvCourse.visibility = View.VISIBLE | |||
} | |||
2 -> { //课程测试 | |||
binding.group1.visibility = View.VISIBLE | |||
binding.tvCourse.visibility = View.GONE | |||
binding.rbLesson.isChecked = true | |||
} | |||
} |
@@ -57,8 +57,8 @@ class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, Main | |||
private fun startTo(position : Int) { | |||
when(position){ | |||
0 -> startActivity(CourseTestActivity::class.java) | |||
1 -> "" | |||
2 -> "" | |||
1 -> startActivity(TestVocabularyActivity::class.java) | |||
2 -> startActivity(TestScoreActivity::class.java) | |||
3 -> "" | |||
} | |||
} |
@@ -2,6 +2,7 @@ package com.xkl.cdl.module.m_service_center | |||
import android.annotation.SuppressLint | |||
import android.os.Bundle | |||
import android.view.View | |||
import androidx.lifecycle.ViewModelProvider | |||
import androidx.recyclerview.widget.LinearLayoutManager | |||
import com.suliang.common.base.activity.BaseActivityVM | |||
@@ -11,6 +12,7 @@ import com.xkl.cdl.adapter.AdapterTestDetail | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.databinding.ActivityTestDetailBinding | |||
import mqComsumerV1.Struct | |||
/** | |||
* author suliang | |||
@@ -25,8 +27,30 @@ class TestDetailActivity : BaseActivityVM<ActivityTestDetailBinding,TestDetailVi | |||
@SuppressLint("SetTextI18n") | |||
override fun initActivity(savedInstanceState : Bundle?) { | |||
// TODO: 2022/6/21 词汇量测试暂未考虑 | |||
//词汇量测试 | |||
if (vm.learnExam.type == AppConstants.TEST_TYPE_NORMAL.toLong()){ | |||
binding.run { | |||
layoutMemoTest.visibility = View.GONE | |||
layoutVocabulary.visibility = View.VISIBLE | |||
tvVocabularyTestTime.text = vm.learnExam.created | |||
if (vm.learnExam.score > 0){ | |||
groupVocabularyLittle.visibility = View.GONE | |||
groupVocabularyNormal.visibility = View.VISIBLE | |||
tvVocabularyCount.text = "${vm.learnExam.score}" | |||
ratingBar.setStar(vm.learnExam.score/20) | |||
tvVocabularyCoverRateStage.setHtml("覆盖率<font color=\'#F7874F\'>${vm.learnExam.coverRate}%</font>\t\t(${vm.learnExam.stage})") | |||
}else{ | |||
groupVocabularyLittle.visibility = View.VISIBLE | |||
groupVocabularyNormal.visibility = View.GONE | |||
tvVocabularyLevel.text = vm.learnExam.stage | |||
} | |||
} | |||
return | |||
} | |||
//正常测试 | |||
binding.run { | |||
layoutMemoTest.visibility = View.VISIBLE | |||
layoutVocabulary.visibility = View.GONE | |||
titleBar.onBackClick = { v -> finish() } | |||
tvCourseName.setHtml(initCourseName()) | |||
tvScore.setHtml(initScore()) | |||
@@ -51,7 +75,7 @@ class TestDetailActivity : BaseActivityVM<ActivityTestDetailBinding,TestDetailVi | |||
private fun initCourseName() : String{ | |||
val split = vm.learnExam.title.split("@@") | |||
return if (split.size > 1){ | |||
"${split[0]}<font color=\'#8A8A99\'>(${split[1]})</font>" | |||
"${split[0]}<font color=\'#8A8A99\'><small>(${split[1]})</small></font>" | |||
}else{ | |||
split[0] | |||
} |
@@ -0,0 +1,172 @@ | |||
package com.xkl.cdl.module.m_service_center | |||
import android.os.Bundle | |||
import android.view.View | |||
import androidx.lifecycle.ViewModelProvider | |||
import androidx.recyclerview.widget.LinearLayoutManager | |||
import com.google.android.flexbox.FlexDirection | |||
import com.google.android.flexbox.FlexWrap | |||
import com.google.android.flexbox.FlexboxLayoutManager | |||
import com.scwang.smart.refresh.layout.api.RefreshLayout | |||
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener | |||
import com.suliang.common.base.activity.BaseActivityVM | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.extension.diskIo2Main | |||
import com.suliang.common.util.DrawableUti | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.adapter.AdapterTestFilter | |||
import com.xkl.cdl.adapter.AdapterTestScore | |||
import com.xkl.cdl.data.DataTransferHolder | |||
import com.xkl.cdl.data.exam_record.AppDatabase | |||
import com.xkl.cdl.databinding.ActivityTestScoreBinding | |||
import com.xkl.cdl.widget.MyFlexboxLayoutManager | |||
import io.reactivex.rxjava3.core.Observable | |||
import io.reactivex.rxjava3.core.ObservableConverter | |||
class TestScoreActivity : BaseActivityVM<ActivityTestScoreBinding, TestScoreViewModel>() { | |||
override fun initViewModel() : TestScoreViewModel { | |||
return ViewModelProvider(this)[TestScoreViewModel::class.java] | |||
} | |||
private lateinit var detailAdapter : AdapterTestScore | |||
private lateinit var filterAdapter : AdapterTestFilter | |||
override fun initActivity(savedInstanceState : Bundle?) { | |||
binding.vm = vm | |||
//标题 | |||
binding.titleBar.run { | |||
setRightSrc(DrawableUti.changeSvgSizeAndColor(resources, R.drawable.ic_search, R.color.main_text_color, 1.33f)) | |||
onBackClick = { | |||
finish() | |||
} | |||
//显示搜索 | |||
onRightClick = { | |||
binding.tvSearchCache.visibility = View.VISIBLE | |||
binding.etSearch.visibility = View.VISIBLE | |||
} | |||
} | |||
//搜索取消 | |||
binding.tvSearchCache.click { | |||
binding.tvSearchCache.visibility = View.GONE | |||
binding.etSearch.visibility = View.GONE | |||
binding.etSearch.setText("") | |||
} | |||
//关键字查询 | |||
vm.keyWordSearch.observe(this) { | |||
binding.rvList.scrollToPosition(0) | |||
binding.smartRefresh.autoRefresh() | |||
} | |||
//筛选rv | |||
filterAdapter = AdapterTestFilter(vm) | |||
binding.rvFilter.apply { | |||
layoutManager = LinearLayoutManager(this@TestScoreActivity, | |||
LinearLayoutManager.HORIZONTAL, false) | |||
adapter = filterAdapter | |||
} | |||
filterAdapter.setData(vm.filterArray) | |||
//筛选的下拉箭头 | |||
binding.ivExtend.click { | |||
vm.downState.value = !vm.downState.value!! | |||
} | |||
binding.vMaskLayer.click { | |||
vm.downState.value = !vm.downState.value!! | |||
} | |||
//列表rv | |||
detailAdapter = AdapterTestScore(vm) | |||
binding.rvList.apply { | |||
layoutManager = LinearLayoutManager(this@TestScoreActivity, LinearLayoutManager.VERTICAL, false) | |||
adapter = detailAdapter.apply { | |||
onItemClick = {_, _, item -> | |||
Observable.fromCallable { | |||
val queryDetail = AppDatabase.instance.examMiddleDao().queryDetail(item.id) | |||
AppDatabase.examWithDetailToExamBuild(queryDetail) | |||
}.compose(diskIo2Main()).subscribe{ | |||
DataTransferHolder.instance.putData(value = it) | |||
startActivity(TestDetailActivity::class.java) | |||
} | |||
} | |||
} | |||
} | |||
binding.smartRefresh.setEnableLoadMore(true) | |||
binding.smartRefresh.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener { | |||
override fun onRefresh(refreshLayout : RefreshLayout) { | |||
binding.smartRefresh.setNoMoreData(false) | |||
vm.loadExam(false) | |||
} | |||
override fun onLoadMore(refreshLayout : RefreshLayout) { | |||
vm.loadExam(true) | |||
} | |||
}) | |||
//筛选item改变 | |||
vm.filterPosition.observe(this) { | |||
binding.smartRefresh.autoRefresh() | |||
} | |||
} | |||
override fun loadData() { | |||
// 设置筛选的item | |||
/*lifecycleScope.launch{ | |||
@OptIn(ExperimentalCoroutinesApi::class) | |||
vm.allExam.collectLatest { | |||
detailAdapter.submitData(it) | |||
} | |||
}*/ | |||
binding.rvFilter.post { | |||
vm.downState.observe(this) { | |||
when { | |||
//展开 | |||
it -> { | |||
binding.ivExtend.setImageResource(R.drawable.ic_up) | |||
binding.rvFilter.layoutManager = MyFlexboxLayoutManager(this, FlexDirection.ROW, FlexWrap.WRAP) | |||
binding.vMaskLayer.visibility = View.VISIBLE | |||
} | |||
//收起 | |||
else -> { | |||
binding.ivExtend.setImageResource(R.drawable.ic_down) | |||
binding.rvFilter.layoutManager = LinearLayoutManager(this@TestScoreActivity, | |||
LinearLayoutManager.HORIZONTAL, false) | |||
binding.rvFilter.scrollToPosition(vm.filterPosition.value!!) | |||
binding.vMaskLayer.visibility = View.GONE | |||
} | |||
} | |||
} | |||
} | |||
/**数据更新*/ | |||
vm.dataLiveData.observe(this) { | |||
when { | |||
//加载更多 | |||
vm.isLoadMore -> { | |||
detailAdapter.addData(it) | |||
if (vm.isHaveNextPage) { | |||
binding.smartRefresh.finishLoadMore() | |||
} else { | |||
binding.smartRefresh.finishLoadMoreWithNoMoreData() | |||
} | |||
} | |||
//刷新 | |||
else -> { | |||
binding.smartRefresh.finishRefresh() | |||
if (it.isNullOrEmpty()){ | |||
detailAdapter.needShowEmptyView = true | |||
} | |||
detailAdapter.setData(it.toMutableList()) | |||
if (!vm.isHaveNextPage) { | |||
binding.smartRefresh.setNoMoreData(true) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
package com.xkl.cdl.module.m_service_center | |||
import androidx.lifecycle.MutableLiveData | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.suliang.common.extension.diskIo2Main | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.exam_record.AppDatabase | |||
import com.xkl.cdl.data.exam_record.Exam | |||
import io.reactivex.rxjava3.core.Observable | |||
class TestScoreViewModel : BaseViewModel() { | |||
/**搜索框: 搜索关键字*/ | |||
val keyWordSearch = MutableLiveData<String>() | |||
/** 筛选数组 */ | |||
val filterArray = mutableListOf("全部", "学前总测试", "学后总测试", "课时学前测试", "课时学后测试", "词汇量测试", "课程测试", "知识点测试", "备忘本测试", "英语课程测试", | |||
"作文课程测试") | |||
//默认选中 | |||
val filterPosition = MutableLiveData(0) | |||
//下拉状态 是否展开 | |||
val downState = MutableLiveData<Boolean>(false) | |||
private val pageSize = 50 //分页数量 | |||
private var totalSize = 0 //总数 | |||
private var lastId : Long? = null //最后一条id | |||
var isHaveNextPage : Boolean = false //是否还有下一页 | |||
//记录当前加载的isLoadMore状态 | |||
var isLoadMore = false | |||
//通知数据有更新 | |||
val dataLiveData = MutableLiveData<List<Exam>>() | |||
fun loadExam(isLoadMore : Boolean) { | |||
this.isLoadMore = isLoadMore | |||
//如果是刷新,lastId为null | |||
if (!isLoadMore) { | |||
isHaveNextPage = true | |||
lastId = null | |||
} | |||
Observable.create<List<Exam>> { | |||
val queryS = AppDatabase.instance.examDao() | |||
.queryS(isAll = isFilterAll(), examType = getExamType(), projectId = getTestProjectId(), | |||
keyWord_ = keyWordSearch.value, lastId, pageSize = pageSize) | |||
it.onNext(queryS) | |||
it.onComplete() | |||
}.compose(diskIo2Main()).subscribe({ | |||
isHaveNextPage = it.size == pageSize | |||
lastId = if (it.isNullOrEmpty()) null else it.last().id | |||
dataLiveData.value = it | |||
}, { | |||
it.printStackTrace() | |||
dataLiveData.value = mutableListOf() | |||
}) | |||
} | |||
/**筛选的是否是全部*/ | |||
private fun isFilterAll() : Boolean { | |||
return filterPosition.value == 0 | |||
} | |||
private fun getExamType() : Int? { | |||
return when (filterPosition.value) { | |||
1 -> AppConstants.TEST_TYPE_BEFORE_TOTAL | |||
2 -> AppConstants.TEST_TYPE_AFTER_TOTAL | |||
3 -> AppConstants.TEST_TYPE_BEFORE | |||
4 -> AppConstants.TEST_TYPE_AFTER | |||
5 -> AppConstants.TEST_TYPE_NORMAL | |||
7 -> AppConstants.TEST_TYPE_COMPOSITION | |||
8 -> AppConstants.TEST_TYPE_MEMO | |||
6, 9, 10 -> AppConstants.TEST_TYPE_SERVICE_CENTER | |||
else -> null | |||
} | |||
} | |||
private fun getTestProjectId() : Int? { | |||
return when (filterPosition.value) { | |||
9 -> AppConstants.SUBJECT_CHINESE | |||
10 -> AppConstants.SUBJECT_CHINESE | |||
else -> null | |||
} | |||
} | |||
// companion object{ | |||
// private const val PAGE_SIZE = 15 | |||
// private const val ENABLE_PLACEHOLDERS = false | |||
// } | |||
// | |||
// val allExam = Pager(PagingConfig(PAGE_SIZE, enablePlaceholders = ENABLE_PLACEHOLDERS,maxSize = 100)){ | |||
// AppDatabase.instance.examDao().queryAll() | |||
// }.flow | |||
} |
@@ -0,0 +1,54 @@ | |||
package com.xkl.cdl.module.m_service_center | |||
import android.os.Bundle | |||
import android.view.ViewGroup | |||
import androidx.lifecycle.ViewModelProvider | |||
import androidx.recyclerview.widget.LinearLayoutManager | |||
import com.suliang.common.base.activity.BaseActivityVM | |||
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.VocabularyItem | |||
import com.xkl.cdl.databinding.ActivityTestVocabularyBinding | |||
import com.xkl.cdl.databinding.ItemVocabularyLevelBinding | |||
class TestVocabularyActivity : BaseActivityVM<ActivityTestVocabularyBinding, TestVocabularyViewModle>() { | |||
override fun initViewModel() : TestVocabularyViewModle { | |||
return ViewModelProvider(this)[TestVocabularyViewModle::class.java] | |||
} | |||
override fun initActivity(savedInstanceState : Bundle?) { | |||
binding.titleBar.onBackClick = {_ -> finish()} | |||
binding.rv.apply { | |||
layoutManager = LinearLayoutManager(this@TestVocabularyActivity,LinearLayoutManager.VERTICAL,false) | |||
setHasFixedSize(true) | |||
adapter = object :BaseRVAdapter<VocabularyItem>(vm.data){ | |||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_vocabulary_level)) | |||
} | |||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||
getItem(position).let { | |||
(holder.binding as ItemVocabularyLevelBinding).run { | |||
iv.setImageResource(it.icon) | |||
tvLevel.text = it.level | |||
tvLevelE.text = it.level_e | |||
root.click { | |||
// vm.queryVocabulary(it) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
override fun loadData() { | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
package com.xkl.cdl.module.m_service_center | |||
import androidx.lifecycle.MutableLiveData | |||
import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.suliang.common.extension.diskIo2Main | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.bean.VocabularyItem | |||
import com.xkl.cdl.data.bean.course.ExamBean | |||
import com.xkl.cdl.data.manager.db.DBCourseManager | |||
import io.reactivex.rxjava3.core.Observable | |||
/** | |||
* author suliang | |||
* create 2022/7/13 10:38 | |||
* Describe: | |||
*/ | |||
class TestVocabularyViewModle : BaseViewModel() { | |||
val data = mutableListOf( | |||
VocabularyItem(R.mipmap.ic_comprehensive_test,"综合测试",""), | |||
VocabularyItem(R.mipmap.ic_primary_school,"小学",""), | |||
VocabularyItem(R.mipmap.ic_junior_school,"初中",""), | |||
VocabularyItem(R.mipmap.ic_high_school,"高中",""), | |||
VocabularyItem(R.mipmap.ic_university_4,"大学四级",""), | |||
VocabularyItem(R.mipmap.ic_university_6,"大学六级",""), | |||
VocabularyItem(R.mipmap.ic_lelts,"雅思",""), | |||
VocabularyItem(R.mipmap.ic_toefl,"托福","") ) | |||
/** | |||
* 查询测试数据 | |||
* @param item VocabularyItem | |||
*/ | |||
fun queryVocabularyTestData(item : VocabularyItem) : MutableLiveData<List<ExamBean>> { | |||
val result = MutableLiveData<List<ExamBean>>() | |||
Observable.create<List<ExamBean>> { | |||
it.onNext(DBCourseManager.queryLearnTest(dbControlBase, testType, lesson)) | |||
it.onComplete() | |||
}.compose(diskIo2Main()).subscribe({ | |||
result.value = it | |||
}, { | |||
it.printStackTrace() | |||
}) | |||
return result | |||
} | |||
} |
@@ -6,14 +6,17 @@ import appApi.AppApi | |||
import com.googlecode.protobuf.format.JsonFormat | |||
import com.suliang.common.base.activity.BaseActivity | |||
import com.suliang.common.util.LogUtil | |||
import com.suliang.common.util.file.FileUtil | |||
import com.suliang.common.util.thread.AppExecutors | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.data.manager.FilePathManager | |||
import com.xkl.cdl.data.manager.db.DbCoursePackManager | |||
import com.xkl.cdl.databinding.ActivitySplashBinding | |||
import com.xkl.cdl.module.XKLApplication | |||
import com.xkl.cdl.module.main.MainActivity | |||
import io.reactivex.rxjava3.core.Observable | |||
import java.io.File | |||
import java.util.* | |||
import java.util.concurrent.TimeUnit | |||
@@ -36,8 +39,6 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() { | |||
showHideLoading(true) | |||
AppExecutors.diskIO.execute { | |||
//读取课程数据 | |||
//用户的sort信息 | |||
@@ -50,6 +51,16 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() { | |||
val parseFrom = AppApi.CourseSortedResponse.parseFrom(value).toBuilder() | |||
CourseManager.mSortInfoList.put(AppConstants.SUBJECT_CHINESE, parseFrom.listBuilderList) | |||
} | |||
//复制词典 和 词汇量测试 | |||
val dictionary = FilePathManager.getDictionaryDbPath() | |||
if (!dictionary.exists()) { | |||
val copyAssetResult = FileUtil.copyAsset("dictionary.db", dictionary) | |||
} | |||
val vocabulary = FilePathManager.getVocabularyDbPath() | |||
if (!dictionary.exists()) { | |||
val copyAssetResult = FileUtil.copyAsset("vocabulary.db", vocabulary) | |||
} | |||
// TODO: 2022/3/22 读取当前app绑定的课程数据, | |||
DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615,516,411") |
@@ -0,0 +1,28 @@ | |||
package com.xkl.cdl.widget | |||
import android.content.Context | |||
import android.util.AttributeSet | |||
import android.view.ViewGroup | |||
import androidx.recyclerview.widget.RecyclerView | |||
import com.google.android.flexbox.FlexboxLayoutManager | |||
/** | |||
* author suliang | |||
* create 2022/7/12 10:56 | |||
* Describe: | |||
*/ | |||
class MyFlexboxLayoutManager : FlexboxLayoutManager { | |||
constructor(context : Context): super(context) | |||
constructor(context : Context,flexDirection : Int): super(context,flexDirection) | |||
constructor(context : Context,flexDirection : Int,flexWrap : Int): super(context,flexDirection,flexWrap) | |||
constructor(context:Context, attrs : AttributeSet, defStyleAttr :Int,defStyleRes: Int) : super(context,attrs,defStyleAttr,defStyleRes) | |||
/** | |||
* 将LayoutParams转换成新的FlexboxLayoutManager.LayoutParams | |||
*/ | |||
override fun generateLayoutParams(lp : ViewGroup.LayoutParams) : RecyclerView.LayoutParams { | |||
return FlexboxLayoutManager.LayoutParams(lp) | |||
} | |||
} |
@@ -0,0 +1,5 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<item android:color="@color/white" android:state_checked="true"/> | |||
<item android:color="@color/gray_2"/> | |||
</selector> |
@@ -0,0 +1,16 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<item android:state_checked="true"> | |||
<shape android:shape="rectangle"> | |||
<corners android:radius="2dp"/> | |||
<solid android:color="@color/theme_color"/> | |||
</shape> | |||
</item> | |||
<item android:state_checked="false"> | |||
<shape android:shape="rectangle"> | |||
<corners android:radius="2dp"/> | |||
<solid android:color="@color/white_1"/> | |||
</shape> | |||
</item> | |||
</selector> |
@@ -10,52 +10,226 @@ | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_service_center.TestDetailActivity" | |||
android:background="@color/white"> | |||
android:background="@color/white" | |||
tools:context=".module.m_service_center.TestDetailActivity"> | |||
<com.suliang.common.widget.TitleBar | |||
android:id="@+id/title_bar" | |||
android:layout_width="0dp" | |||
android:layout_height="@dimen/title_bar_height" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:titleTextValue="测试成绩详情" /> | |||
<View | |||
android:layout_width="0dp" | |||
android:layout_height="@dimen/line_height" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | |||
android:background="@color/gray_1" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" /> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:id="@+id/layout_vocabulary" | |||
android:layout_width="0dp" | |||
android:layout_height="0dp" | |||
android:layout_marginTop="@dimen/line_height" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
android:background="@color/gray_1" /> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | |||
tools:visibility="visible" | |||
> | |||
<TextView | |||
android:id="@+id/tv_vocabulary" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="@dimen/global_spacing" | |||
android:text="学考乐词汇量测试结果" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" /> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_test_time_flag" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="8dp" | |||
android:text="@string/test_time_1" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toStartOf="@+id/tv_vocabulary_test_time" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/tv_vocabulary" | |||
app:layout_constraintHorizontal_chainStyle="packed"/> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_test_time" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_vocabulary_test_time_flag" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toEndOf="@+id/tv_vocabulary_test_time_flag" | |||
tools:text="时间" /> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_count_flag" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="24dp" | |||
android:text="@string/vocabulary" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_vocabulary_test_time_flag" /> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_count" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textColor="@color/red_1" | |||
android:textSize="60dp" | |||
android:textStyle="bold" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_vocabulary_count_flag" | |||
tools:text="1000" /> | |||
<com.xl.ratingbar.MyRatingBar | |||
android:id="@+id/rating_bar" | |||
android:layout_width="wrap_content" | |||
android:layout_height="24dp" | |||
android:layout_marginTop="24dp" | |||
android:clickable="false" | |||
android:gravity="center" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_vocabulary_count" | |||
app:starEmpty="@drawable/ic_star" | |||
app:starFill="@drawable/ic_star_1" | |||
app:starHalf="@drawable/ic_star_1" | |||
app:starCount = "5" | |||
tools:starNum = "2" | |||
app:starImageWidth="24dp" | |||
app:starImageHeight="24dp"/> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_cover_rate_stage" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="8dp" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/rating_bar" | |||
tools:text="覆盖率67%(高中)" /> | |||
<!--少--> | |||
<ImageView | |||
android:id="@+id/iv_little" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="38dp" | |||
android:src="@mipmap/cry" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_vocabulary_test_time" /> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_little" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="24dp" | |||
android:text="@string/little_vocabulary" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
android:textStyle="bold" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/iv_little" /> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_test_level_flag" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="12dp" | |||
android:text="@string/vocabulary_level" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintEnd_toStartOf="@+id/tv_vocabulary_level" | |||
app:layout_constraintHorizontal_chainStyle="packed" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/tv_vocabulary_little" /> | |||
<TextView | |||
android:id="@+id/tv_vocabulary_level" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_vocabulary_test_level_flag" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toEndOf="@+id/tv_vocabulary_test_level_flag" | |||
tools:text="时间" /> | |||
<androidx.constraintlayout.widget.Group | |||
android:id="@+id/group_vocabulary_little" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:constraint_referenced_ids="iv_little,tv_vocabulary_little,tv_vocabulary_test_level_flag,tv_vocabulary_level" | |||
tools:visibility="gone"/> | |||
<androidx.constraintlayout.widget.Group | |||
android:id="@+id/group_vocabulary_normal" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:constraint_referenced_ids="tv_vocabulary_count_flag,tv_vocabulary_count,rating_bar,tv_vocabulary_cover_rate_stage" | |||
tools:visibility="visible"/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
<androidx.core.widget.NestedScrollView | |||
android:id="@+id/layout_memo_test" | |||
android:layout_width="0dp" | |||
android:layout_height="wrap_content" | |||
android:layout_marginTop="@dimen/line_height" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:orientation="vertical" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:orientation="vertical" | |||
app:layout_constraintVertical_bias="0"> | |||
app:layout_constraintVertical_bias="0" | |||
tools:visibility="gone"> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
> | |||
android:layout_height="wrap_content"> | |||
<androidx.appcompat.widget.LinearLayoutCompat | |||
android:id="@+id/layout_title" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:layout_marginEnd="@dimen/global_spacing" | |||
android:gravity="center_vertical" | |||
android:orientation="horizontal" | |||
app:layout_constraintTop_toTopOf="parent" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:layout_marginEnd="@dimen/global_spacing"> | |||
android:paddingTop="8dp" | |||
android:paddingBottom="8dp" | |||
app:layout_constraintTop_toTopOf="parent"> | |||
<TextView | |||
android:id="@+id/tv_course_name" | |||
@@ -81,145 +255,145 @@ | |||
android:id="@+id/tv_type_flag" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toBottomOf="@id/layout_title" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:layout_marginTop="12dp" | |||
android:text="@string/test_type_1" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/gray_2" /> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/layout_title" /> | |||
<TextView | |||
android:id="@+id/tv_type" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toTopOf="@+id/tv_type_flag" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBottom_toBottomOf="@+id/tv_type_flag" | |||
app:layout_constraintStart_toEndOf="@+id/tv_type_flag" | |||
tools:text="@string/test_type_1" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/main_text_color" /> | |||
app:layout_constraintTop_toTopOf="@+id/tv_type_flag" | |||
tools:text="@string/test_type_1" /> | |||
<TextView | |||
android:id="@+id/tv_use_time_flag" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toBottomOf="@id/tv_type_flag" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:layout_marginTop="8dp" | |||
android:text="@string/test_use_time_1" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/gray_2" /> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/tv_type_flag" /> | |||
<TextView | |||
android:id="@+id/tv_use_time" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toTopOf="@+id/tv_use_time_flag" | |||
app:layout_constraintStart_toStartOf="@+id/tv_type" | |||
tools:text="@string/test_type_1" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/main_text_color" /> | |||
app:layout_constraintStart_toStartOf="@+id/tv_type" | |||
app:layout_constraintTop_toTopOf="@+id/tv_use_time_flag" | |||
tools:text="@string/test_type_1" /> | |||
<TextView | |||
android:id="@+id/tv_test_time_flag" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toBottomOf="@id/tv_use_time_flag" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:layout_marginTop="8dp" | |||
android:text="@string/test_time_1" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/gray_2" /> | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@id/tv_use_time_flag" /> | |||
<TextView | |||
android:id="@+id/tv_test_time" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toTopOf="@+id/tv_test_time_flag" | |||
app:layout_constraintStart_toEndOf="@+id/tv_test_time_flag" | |||
tools:text="@string/test_type_1" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/main_text_color" /> | |||
app:layout_constraintStart_toEndOf="@+id/tv_test_time_flag" | |||
app:layout_constraintTop_toTopOf="@+id/tv_test_time_flag" | |||
tools:text="@string/test_type_1" /> | |||
<View | |||
android:id="@+id/v_1" | |||
android:layout_width="0dp" | |||
android:layout_height="36dp" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_test_time_flag" | |||
android:layout_marginTop="@dimen/global_spacing" | |||
android:background="@color/white_1" /> | |||
android:background="@color/white_1" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_test_time_flag" /> | |||
<TextView | |||
android:id="@+id/tv_total_count" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textSize="@dimen/smallSize" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:textColor="@color/gray_2" | |||
tools:text="共50题" | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBottom_toBottomOf="@+id/v_1" | |||
app:layout_constraintStart_toStartOf="parent" | |||
android:layout_marginStart="@dimen/global_spacing" /> | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
tools:text="共50题" /> | |||
<View | |||
android:id="@+id/v_2" | |||
android:layout_width="@dimen/line_height" | |||
android:layout_height="12dp" | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
android:layout_marginStart="8dp" | |||
android:background="@color/gray_1" | |||
app:layout_constraintBottom_toBottomOf="@+id/v_1" | |||
app:layout_constraintStart_toEndOf="@+id/tv_total_count" | |||
android:background="@color/gray_1" | |||
android:layout_marginStart="8dp" /> | |||
app:layout_constraintTop_toTopOf="@+id/v_1" /> | |||
<TextView | |||
android:id="@+id/tv_correct_count" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textSize="@dimen/smallSize" | |||
android:layout_marginStart="8dp" | |||
android:textColor="@color/green_1" | |||
tools:text="正确:共50题" | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBottom_toBottomOf="@+id/v_1" | |||
app:layout_constraintStart_toEndOf="@+id/v_2" | |||
android:layout_marginStart="8dp" /> | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
tools:text="正确:共50题" /> | |||
<View | |||
android:id="@+id/v_3" | |||
android:layout_width="@dimen/line_height" | |||
android:layout_height="12dp" | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
android:layout_marginStart="8dp" | |||
android:background="@color/gray_1" | |||
app:layout_constraintBottom_toBottomOf="@+id/v_1" | |||
app:layout_constraintStart_toEndOf="@+id/tv_correct_count" | |||
android:background="@color/gray_1" | |||
android:layout_marginStart="8dp" /> | |||
app:layout_constraintTop_toTopOf="@+id/v_1" /> | |||
<TextView | |||
android:id="@+id/tv_error_count" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:textSize="@dimen/smallSize" | |||
android:layout_marginStart="8dp" | |||
android:textColor="@color/red_1" | |||
tools:text="错误:共50题" | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
android:textSize="@dimen/smallSize" | |||
app:layout_constraintBottom_toBottomOf="@+id/v_1" | |||
app:layout_constraintStart_toEndOf="@+id/v_3" | |||
android:layout_marginStart="8dp" /> | |||
app:layout_constraintTop_toTopOf="@+id/v_1" | |||
tools:text="错误:共50题" /> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/rv" | |||
android:layout_width="0dp" | |||
android:layout_height="match_parent" | |||
app:layout_constraintTop_toBottomOf="@+id/v_1" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
android:layout_marginTop="1dp" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintVertical_weight="1" | |||
android:layout_marginTop="1dp"/> | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/v_1" | |||
app:layout_constraintVertical_weight="1" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</androidx.core.widget.NestedScrollView> |
@@ -0,0 +1,142 @@ | |||
<?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="vm" | |||
type="com.xkl.cdl.module.m_service_center.TestScoreViewModel" /> | |||
</data> | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_service_center.TestScoreActivity" | |||
android:background="@color/white"> | |||
<com.suliang.common.widget.TitleBar | |||
android:id="@+id/title_bar" | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/title_bar_height" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:titleTextValue="@string/test_score" /> | |||
<View | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/line_height" | |||
android:background="@color/gray_1" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" /> | |||
<TextView | |||
android:id="@+id/tv_search_cache" | |||
android:layout_width="wrap_content" | |||
android:layout_height="0dp" | |||
android:background="@color/white" | |||
android:gravity="center_vertical" | |||
android:paddingStart="12dp" | |||
android:paddingEnd="@dimen/global_spacing" | |||
android:text="@string/cancel" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
android:textStyle="bold" | |||
android:visibility="gone" | |||
app:layout_constraintBottom_toBottomOf="@+id/title_bar" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toTopOf="@+id/title_bar" | |||
tools:visibility="visible" /> | |||
<com.suliang.common.widget.InputSearchEditText | |||
android:id="@+id/et_search" | |||
android:layout_width="0dp" | |||
android:layout_height="36dp" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:background="@drawable/et_search_bg" | |||
android:drawablePadding="4dp" | |||
android:gravity="center_vertical" | |||
android:hint="@string/search_hint_input_key_word" | |||
android:maxLines="1" | |||
android:paddingLeft="16dp" | |||
android:paddingRight="16dp" | |||
android:singleLine="true" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
android:visibility="gone" | |||
app:layout_constraintBottom_toBottomOf="@+id/title_bar" | |||
app:layout_constraintEnd_toStartOf="@+id/tv_search_cache" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="@id/title_bar" | |||
android:text="@={vm.keyWordSearch}" /> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/rv_filter" | |||
android:layout_width="0dp" | |||
android:layout_height="wrap_content" | |||
android:minHeight="42dp" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintEnd_toStartOf="@+id/iv_extend" | |||
android:paddingStart="@dimen/global_spacing" | |||
android:paddingBottom="8dp" | |||
tools:itemCount="10" | |||
tools:listitem="@layout/item_test_filter" | |||
tools:layoutManager="com.google.android.flexbox.FlexboxLayoutManager" | |||
tools:orientation="horizontal"/> | |||
<com.google.android.material.imageview.ShapeableImageView | |||
android:id="@+id/iv_extend" | |||
android:layout_width="30dp" | |||
android:layout_height="30dp" | |||
app:contentPadding="7dp" | |||
android:src="@drawable/ic_down" | |||
app:layout_constraintStart_toEndOf="@+id/rv_filter" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintTop_toTopOf="@+id/rv_filter" | |||
android:layout_marginRight="@dimen/global_spacing" | |||
android:layout_marginTop="6dp"/> | |||
<com.scwang.smart.refresh.layout.SmartRefreshLayout | |||
android:id="@+id/smart_refresh" | |||
android:layout_width="match_parent" | |||
android:layout_height="0dp" | |||
app:layout_constraintTop_toBottomOf="@+id/rv_filter" | |||
app:layout_constraintBottom_toBottomOf="parent"> | |||
<com.xkl.cdl.widget.smartRefresh.XkLRefreshHeader | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content"/> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/rv_list" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:minHeight="42dp"/> | |||
<com.scwang.smart.refresh.footer.ClassicsFooter | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content"/> | |||
</com.scwang.smart.refresh.layout.SmartRefreshLayout> | |||
<View | |||
android:id="@+id/v_mask_layer" | |||
android:layout_width="match_parent" | |||
android:layout_height="0dp" | |||
app:layout_constraintTop_toBottomOf="@+id/rv_filter" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:clickable="true" | |||
android:background="#4D000000" | |||
android:visibility="gone" | |||
tools:visibility="visible"/> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,52 @@ | |||
<?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.appcompat.widget.LinearLayoutCompat | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context=".module.m_service_center.TestVocabularyActivity" | |||
android:background="@color/white" | |||
android:orientation="vertical"> | |||
<com.suliang.common.widget.TitleBar | |||
android:id="@+id/title_bar" | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/title_bar_height" | |||
app:titleTextValue="@string/test_vocabulary"/> | |||
<View | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/line_height" | |||
android:background="@color/gray_1"/> | |||
<TextView | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="请选择你的测试等级" | |||
android:layout_margin="@dimen/global_spacing" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/normalSize" | |||
/> | |||
<View | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/line_height" | |||
android:background="@color/gray_1"/> | |||
<androidx.recyclerview.widget.RecyclerView | |||
android:id="@+id/rv" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:overScrollMode="never" | |||
android:layout_marginTop="12dp" | |||
android:scrollbars="none"/> | |||
</androidx.appcompat.widget.LinearLayoutCompat> | |||
</layout> |
@@ -0,0 +1,32 @@ | |||
<?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.appcompat.widget.LinearLayoutCompat | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content"> | |||
<RadioButton | |||
android:id="@+id/rb" | |||
android:layout_width="wrap_content" | |||
android:layout_height="26dp" | |||
android:layout_marginStart="6dp" | |||
android:layout_marginTop="8dp" | |||
android:layout_marginEnd="6dp" | |||
android:background="@drawable/rb_select_white1_theme_bg" | |||
android:button="@null" | |||
android:checked="true" | |||
android:gravity="center" | |||
android:paddingStart="8dp" | |||
android:paddingEnd="8dp" | |||
android:textColor="@color/rb_select_gray_white" | |||
android:textSize="@dimen/smallSize" | |||
tools:text="全部"/> | |||
</androidx.appcompat.widget.LinearLayoutCompat> | |||
</layout> |
@@ -0,0 +1,89 @@ | |||
<?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:paddingTop="12dp" | |||
android:paddingBottom="12dp" | |||
android:paddingStart="@dimen/global_spacing" | |||
android:paddingEnd="@dimen/global_spacing"> | |||
<TextView | |||
android:id="@+id/tv_mark_number" | |||
android:layout_width="wrap_content" | |||
android:layout_height="0dp" | |||
android:background="@drawable/shape_cicler_24_c3d69b" | |||
android:backgroundTint="#1A5082E6" | |||
android:gravity="center" | |||
android:textColor="@color/theme_color" | |||
android:textSize="@dimen/normalSize" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintDimensionRatio="1:1" | |||
app:layout_constraintHeight_min="24dp" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintWidth_min="24dp" | |||
tools:text="91" /> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
android:layout_width="0dp" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintStart_toEndOf="@+id/tv_mark_number" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toTopOf="@+id/tv_exam_type" | |||
app:layout_constraintEnd_toStartOf="@+id/tv_score" | |||
android:layout_marginStart="12dp" | |||
android:layout_marginEnd="12dp" | |||
android:maxLines="2" | |||
android:ellipsize="end" | |||
android:textSize="@dimen/normalSize" | |||
android:textColor="@color/main_text_color" | |||
tools:text="课程名称名称" /> | |||
<TextView | |||
android:id="@+id/tv_exam_type" | |||
android:layout_width="0dp" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toBottomOf="@+id/tv_title" | |||
app:layout_constraintStart_toStartOf="@+id/tv_title" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/theme_color" | |||
android:layout_marginTop="4dp" | |||
tools:text="测试类型" /> | |||
<TextView | |||
android:id="@+id/tv_create_time" | |||
android:layout_width="0dp" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintStart_toEndOf="@+id/tv_exam_type" | |||
app:layout_constraintBaseline_toBaselineOf="@+id/tv_exam_type" | |||
tools:text="12:12:12" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/gray_2" | |||
android:layout_marginStart="24dp" /> | |||
<TextView | |||
android:id="@+id/tv_score" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintStart_toEndOf="@+id/tv_title" | |||
app:layout_constraintEnd_toEndOf="parent" | |||
android:textSize="26dp" | |||
android:textColor="@color/red_1" | |||
android:textStyle="bold" | |||
tools:text="100" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -0,0 +1,50 @@ | |||
<?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_12_white" | |||
android:padding="@dimen/global_spacing" | |||
android:layout_marginBottom="12dp" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:layout_marginEnd="@dimen/global_spacing"> | |||
<ImageView | |||
android:id="@+id/iv" | |||
android:layout_width="50dp" | |||
android:layout_height="50dp" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toTopOf="parent" | |||
app:layout_constraintBottom_toBottomOf="parent" /> | |||
<TextView | |||
android:id="@+id/tv_level" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintStart_toEndOf="@+id/iv" | |||
app:layout_constraintTop_toTopOf="@+id/iv" | |||
android:layout_marginStart="@dimen/global_spacing" | |||
android:textStyle="bold" | |||
android:textColor="@color/main_text_color" | |||
android:textSize="@dimen/normalSize" | |||
tools:text="综合测试" /> | |||
<TextView | |||
android:id="@+id/tv_level_e" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:layout_constraintStart_toStartOf="@id/tv_level" | |||
app:layout_constraintBottom_toBottomOf="@+id/iv" | |||
android:textColor="@color/gray_2" | |||
android:textSize="@dimen/smallSize" | |||
tools:text="ckkdjkj" /> | |||
</androidx.constraintlayout.widget.ConstraintLayout> | |||
</layout> |
@@ -94,5 +94,10 @@ | |||
<string name="test_time_1">测试时间:</string> | |||
<string name="course_test">课程测试</string> | |||
<string name="next_step">下一步</string> | |||
<string name="test_score">测试成绩</string> | |||
<string name="little_vocabulary">词汇量较少</string> | |||
<string name="vocabulary_level">测试等级:</string> | |||
<string name="vocabulary">词汇量</string> | |||
<string name="test_vocabulary">测词汇量</string> | |||
</resources> |
@@ -0,0 +1,24 @@ | |||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:width="24dp" | |||
android:height="24dp" | |||
android:viewportWidth="24" | |||
android:viewportHeight="24"> | |||
<path | |||
android:pathData="M-232,-268h375v812h-375z" | |||
android:strokeWidth="1" | |||
android:fillColor="#FFFFFF" | |||
android:fillType="evenOdd" | |||
android:strokeColor="#00000000"/> | |||
<path | |||
android:pathData="M11.7729,19.707L7.2406,21.3187C6.6748,21.5199 6.053,21.2243 5.8517,20.6585C5.8068,20.5321 5.7856,20.3984 5.7893,20.2643L5.9215,15.4557C5.9284,15.2057 5.8489,14.961 5.6964,14.7627L2.763,10.9503C2.3968,10.4743 2.4858,9.7916 2.9617,9.4254C3.0681,9.3435 3.1887,9.2821 3.3174,9.2442L7.9314,7.884C8.1713,7.8133 8.3795,7.662 8.5209,7.4557L11.2403,3.4878C11.5798,2.9924 12.2566,2.8661 12.752,3.2056C12.8627,3.2814 12.9584,3.3771 13.0342,3.4878L15.7536,7.4557C15.895,7.662 16.1032,7.8133 16.3431,7.884L20.9572,9.2442C21.5332,9.414 21.8625,10.0186 21.6927,10.5947C21.6548,10.7234 21.5933,10.8439 21.5115,10.9503L18.5781,14.7627C18.4256,14.961 18.3461,15.2057 18.353,15.4557L18.4852,20.2643C18.5017,20.8646 18.0285,21.3646 17.4281,21.3811C17.294,21.3848 17.1603,21.3637 17.0339,21.3187L12.5016,19.707C12.2659,19.6232 12.0086,19.6232 11.7729,19.707Z" | |||
android:strokeWidth="1" | |||
android:fillColor="#D9D9D9" | |||
android:fillType="evenOdd" | |||
android:strokeColor="#00000000"/> | |||
<path | |||
android:pathData="M11.7729,19.707L7.2406,21.3187C6.6748,21.5199 6.053,21.2243 5.8517,20.6585C5.8068,20.5321 5.7856,20.3984 5.7893,20.2643L5.9215,15.4557C5.9284,15.2057 5.8489,14.961 5.6964,14.7627L2.763,10.9503C2.3968,10.4743 2.4858,9.7916 2.9617,9.4254C3.0681,9.3435 3.1887,9.2821 3.3174,9.2442L7.9314,7.884C8.1713,7.8133 8.3795,7.662 8.5209,7.4557L11.2403,3.4878C11.5798,2.9924 12.2566,2.8661 12.752,3.2056C12.8627,3.2814 12.9584,3.3771 13.0342,3.4878L15.7536,7.4557C15.895,7.662 16.1032,7.8133 16.3431,7.884L20.9572,9.2442C21.5332,9.414 21.8625,10.0186 21.6927,10.5947C21.6548,10.7234 21.5933,10.8439 21.5115,10.9503L18.5781,14.7627C18.4256,14.961 18.3461,15.2057 18.353,15.4557L18.4852,20.2643C18.5017,20.8646 18.0285,21.3646 17.4281,21.3811C17.294,21.3848 17.1603,21.3637 17.0339,21.3187L12.5016,19.707C12.2659,19.6232 12.0086,19.6232 11.7729,19.707Z" | |||
android:strokeWidth="1" | |||
android:fillColor="#D9D9D9" | |||
android:fillType="evenOdd" | |||
android:strokeColor="#00000000"/> | |||
</vector> |
@@ -0,0 +1,24 @@ | |||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:width="24dp" | |||
android:height="24dp" | |||
android:viewportWidth="24" | |||
android:viewportHeight="24"> | |||
<path | |||
android:pathData="M-232,-268h375v812h-375z" | |||
android:strokeWidth="1" | |||
android:fillColor="#FFFFFF" | |||
android:fillType="evenOdd" | |||
android:strokeColor="#00000000"/> | |||
<path | |||
android:pathData="M11.7729,19.707L7.2406,21.3187C6.6748,21.5199 6.053,21.2243 5.8517,20.6585C5.8068,20.5321 5.7856,20.3984 5.7893,20.2643L5.9215,15.4557C5.9284,15.2057 5.8489,14.961 5.6964,14.7627L2.763,10.9503C2.3968,10.4743 2.4858,9.7916 2.9617,9.4254C3.0681,9.3435 3.1887,9.2821 3.3174,9.2442L7.9314,7.884C8.1713,7.8133 8.3795,7.662 8.5209,7.4557L11.2403,3.4878C11.5798,2.9924 12.2566,2.8661 12.752,3.2056C12.8627,3.2814 12.9584,3.3771 13.0342,3.4878L15.7536,7.4557C15.895,7.662 16.1032,7.8133 16.3431,7.884L20.9572,9.2442C21.5332,9.414 21.8625,10.0186 21.6927,10.5947C21.6548,10.7234 21.5933,10.8439 21.5115,10.9503L18.5781,14.7627C18.4256,14.961 18.3461,15.2057 18.353,15.4557L18.4852,20.2643C18.5017,20.8646 18.0285,21.3646 17.4281,21.3811C17.294,21.3848 17.1603,21.3637 17.0339,21.3187L12.5016,19.707C12.2659,19.6232 12.0086,19.6232 11.7729,19.707Z" | |||
android:strokeWidth="1" | |||
android:fillColor="#F7874F" | |||
android:fillType="evenOdd" | |||
android:strokeColor="#00000000"/> | |||
<path | |||
android:pathData="M11.7729,19.707L7.2406,21.3187C6.6748,21.5199 6.053,21.2243 5.8517,20.6585C5.8068,20.5321 5.7856,20.3984 5.7893,20.2643L5.9215,15.4557C5.9284,15.2057 5.8489,14.961 5.6964,14.7627L2.763,10.9503C2.3968,10.4743 2.4858,9.7916 2.9617,9.4254C3.0681,9.3435 3.1887,9.2821 3.3174,9.2442L7.9314,7.884C8.1713,7.8133 8.3795,7.662 8.5209,7.4557L11.2403,3.4878C11.5798,2.9924 12.2566,2.8661 12.752,3.2056C12.8627,3.2814 12.9584,3.3771 13.0342,3.4878L15.7536,7.4557C15.895,7.662 16.1032,7.8133 16.3431,7.884L20.9572,9.2442C21.5332,9.414 21.8625,10.0186 21.6927,10.5947C21.6548,10.7234 21.5933,10.8439 21.5115,10.9503L18.5781,14.7627C18.4256,14.961 18.3461,15.2057 18.353,15.4557L18.4852,20.2643C18.5017,20.8646 18.0285,21.3646 17.4281,21.3811C17.294,21.3848 17.1603,21.3637 17.0339,21.3187L12.5016,19.707C12.2659,19.6232 12.0086,19.6232 11.7729,19.707Z" | |||
android:strokeWidth="1" | |||
android:fillColor="#F7874F" | |||
android:fillType="evenOdd" | |||
android:strokeColor="#00000000"/> | |||
</vector> |
@@ -22,7 +22,7 @@ task clean(type: Delete) { | |||
//在项目级别定义某些属性并在所有模块之间共享这些属性 | |||
ext { | |||
android = [ | |||
compile_sdk_version: 31, //使用rootProject.ext.android.compile_sdk_version | |||
compile_sdk_version: 32, //使用rootProject.ext.android.compile_sdk_version | |||
build_tools_version: "30.0.2", | |||
min_sdk_version : 21, | |||
target_sdk_version : 31, | |||
@@ -77,8 +77,9 @@ ext { | |||
//Activity_ktx Activity扩展 | |||
Activity_ktx : "androidx.activity:activity-ktx:1.4.0", | |||
//SqlCipher 需要在application 实现 : SQLiteDatabase.loadLibs(this) | |||
SqlCipher : "net.zetetic:android-database-sqlcipher:4.5.0", | |||
Sqlite : "androidx.sqlite:sqlite:2.0.1", | |||
SqlCipher : "net.zetetic:android-database-sqlcipher:4.5.1", | |||
Sqlite : "androidx.sqlite:sqlite:2.3.0-alpha03", | |||
// Sqlite : "androidx.sqlite:sqlite:2.0.1", | |||
//SmartRefreshLayout | |||
SmartRefreshLayout: "io.github.scwang90:refresh-layout-kernel:2.0.5", | |||
//Lottie | |||
@@ -112,7 +113,16 @@ ext { | |||
//google 流式布局 https://blog.csdn.net/ww897532167/article/details/85952498 https://github.com/google/flexbox-layout | |||
FlexBoxLayoutManager : "com.google.android.flexbox:flexbox:3.0.0", | |||
//图表 | |||
Chart: "com.github.PhilJay:MPAndroidChart:v3.1.0" | |||
Chart: "com.github.PhilJay:MPAndroidChart:v3.1.0", | |||
//数据库 Room | |||
// Room_Runtime : "androidx.room:room-runtime:2.4.2", | |||
// Room_Compiler : "androidx.room:room-compiler:2.4.2", | |||
Room_Runtime : "androidx.room:room-runtime:2.3.0-alpha01", | |||
Room_Compiler : "androidx.room:room-compiler:2.3.0-alpha01", | |||
//Paging | |||
Paging: "androidx.paging:paging-runtime:3.0.0-alpha08", | |||
//room_paging | |||
// Room_Paging : "androidx.room:room-paging:${versions.lifecycle_version}" | |||
] | |||
@@ -10,9 +10,13 @@ import androidx.recyclerview.widget.RecyclerView | |||
import androidx.viewbinding.ViewBinding | |||
import com.suliang.common.R | |||
abstract class BaseRVAdapter<T> : | |||
abstract class BaseRVAdapter<T> constructor() : | |||
RecyclerView.Adapter<BaseAdapterViewHolder>() { | |||
public constructor(data : MutableList<T>): this(){ | |||
this.mData = data | |||
} | |||
companion object{ | |||
const val TYPE_EMPTY = -1 | |||
} |