<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_course_statistics_detail.xml" value="0.33" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_course_test.xml" value="0.31567028985507245" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_course_test.xml" value="0.31567028985507245" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_dictionary.xml" value="0.5" /> | |||||
<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/dialog_common.xml" value="0.30978260869565216" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_common.xml" value="0.30978260869565216" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_item_select_repeat.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_item_select_repeat.xml" value="0.4979166666666667" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_lesson_learn.xml" value="0.4144927536231884" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_lesson_learn.xml" value="0.4144927536231884" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_vocabulary.xml" value="0.370018115942029" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_lesson.xml" value="0.33" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_lesson.xml" value="0.33" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_main.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_main.xml" value="0.4979166666666667" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_pack.xml" value="0.34427083333333336" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_pack.xml" value="0.34427083333333336" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/include_title_bar.xml" value="0.25052083333333336" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/include_title_bar.xml" value="0.25052083333333336" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_checkbox.xml" value="1.0" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_checkbox.xml" value="1.0" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_course_lesson.xml" value="0.4785615491009682" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_course_lesson.xml" value="0.4785615491009682" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_dic_detail_chinese.xml" value="0.33242753623188404" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_dic_detail_chinese_for_english_item.xml" value="0.75" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_dic_detail_english.xml" value="0.5" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_dic_history_chinese.xml" value="0.23632218844984804" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_dic_history_english.xml" value="0.23632218844984804" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_dic_search.xml" value="0.75" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_empty.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_empty.xml" value="0.4979166666666667" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_historical_route.xml" value="0.4859375" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_historical_route.xml" value="0.4859375" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo.xml" value="0.67" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo.xml" value="0.67" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_for_literacy.xml" value="0.67" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_for_literacy.xml" value="0.67" /> | ||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_literacy.xml" value="0.5" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_literacy.xml" value="0.5" /> | ||||
<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_service_center_item.xml" value="0.717816683831102" /> | |||||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_service_center_item.xml" value="0.6604774535809018" /> | |||||
<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_bottom_course_change.xml" value="0.30842391304347827" /> |
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_service_center.DictionaryActivity" | |||||
android:exported="true" /> | |||||
<activity | <activity | ||||
android:name=".module.m_service_center.TestVocabularyActivity" | android:name=".module.m_service_center.TestVocabularyActivity" | ||||
android:exported="true" /> | android:exported="true" /> |
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | ||||
return BaseAdapterViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.item_test_score,parent,false)) | |||||
return BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_test_score)) | |||||
} | } | ||||
@SuppressLint("SetTextI18n") | @SuppressLint("SetTextI18n") |
package com.xkl.cdl.adapter | |||||
import android.view.ViewGroup | |||||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||||
import com.suliang.common.base.adapter.BaseRVAdapterVM | |||||
import com.suliang.common.databinding.ItemEmptyBinding | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.data.bean.DictionaryItem | |||||
import com.xkl.cdl.module.m_service_center.DictionaryViewModel | |||||
/** | |||||
* author suliang | |||||
* create 2022/8/4 10:41 | |||||
* Describe: | |||||
*/ | |||||
class DictionaryAdapter(vm:DictionaryViewModel) : BaseRVAdapterVM<DictionaryItem,DictionaryViewModel>(vm) { | |||||
override fun getItemCount() : Int { | |||||
//历史记录,不显示空状态 | |||||
return if (vm.detailState == 1) { | |||||
//大于页数显示的总数量,则显示指定数量,否则显示全部 | |||||
val showCount = vm.histroyShowPage * vm.historyPageSize | |||||
if (getData().size >= showCount){ | |||||
showCount | |||||
}else{ | |||||
getData().size | |||||
} | |||||
}else if (needShowEmptyView && getData().isEmpty()) 1 else getData().size | |||||
} | |||||
override fun onBindEmptyViewHolder(holder : BaseAdapterViewHolder) { | |||||
(holder.binding as ItemEmptyBinding).run { | |||||
//根据监听,显示具体的内容 | |||||
vm.etSearchLiveData.value?.let { | |||||
if (it.isNotEmpty()) { | |||||
imgEmpty.setImageResource(R.mipmap.empty_nothing_search) | |||||
tvContent.text = "没有搜索到任何内容" | |||||
} else { | |||||
imgEmpty.setImageResource(R.mipmap.empty_nothing) | |||||
tvContent.text = "没有数据" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
override fun getItemViewType(position : Int) : Int { | |||||
return when{ | |||||
enableEmptyPosition(position) -> TYPE_EMPTY | |||||
//单条详情 | |||||
vm.searchItemDetailAble -> { | |||||
val item = getItem(position) | |||||
item.form //1英文 2 中文 | |||||
} | |||||
//多条记录 | |||||
else -> 3 | |||||
} | |||||
} | |||||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | |||||
return when(viewType){ | |||||
1 -> BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_dic_detail_english)) //英文搜索结果详情 | |||||
2 -> BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_dic_detail_chinese)) //中文搜索结果详情 | |||||
else -> BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_dic_search)) //记录列表 历史和搜索记录列表 | |||||
} | |||||
} | |||||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||||
val itemViewType = getItemViewType(position) | |||||
when(itemViewType){ | |||||
1 -> { | |||||
} | |||||
2 -> { | |||||
} | |||||
3 -> { | |||||
} | |||||
} | |||||
} | |||||
} |
package com.xkl.cdl.data.bean | |||||
/** | |||||
* author suliang | |||||
* create 2022/8/4 10:47 | |||||
* Describe: | |||||
*/ | |||||
open class DictionaryBean() { | |||||
var id : Long = 0 | |||||
var word : String? = null | |||||
var form : Int = 0 // 1 英文 2中文 | |||||
var pre_index : String? = null //前缀 | |||||
var phonetic_uk : String? = null | |||||
var phonectic_us : String? = null | |||||
var phonectic_cn : String? = null | |||||
var basic_explaination : String? = null | |||||
var all_explaination : String? = null | |||||
var phrase : String? = null | |||||
var example : String? = null | |||||
var reference : String? = null | |||||
} |
package com.xkl.cdl.data.bean | |||||
import androidx.room.Entity | |||||
import androidx.room.Ignore | |||||
import androidx.room.PrimaryKey | |||||
/** | |||||
* author suliang | |||||
* create 2022/8/4 10:42 | |||||
* Describe: | |||||
*/ | |||||
@Entity(tableName = "dic_history",primaryKeys = ["word"]) | |||||
class DictionaryItem : DictionaryBean() { | |||||
//课程查询时的课程id | |||||
var courseId : Long = 0 | |||||
//查询时间 | |||||
var queryTime: Long = 0 | |||||
//词典联想结果判断其是否在历史记录中,如果在历史记录中,则进行时间重排序 | |||||
@Ignore | |||||
var inHistory : Boolean = false | |||||
} |
* create 2022/7/13 10:48 | * create 2022/7/13 10:48 | ||||
* Describe: | * Describe: | ||||
*/ | */ | ||||
class VocabularyItem(val icon: Int, val level: String,val level_e: String) | |||||
class VocabularyItem(val icon: Int, val level: String,val level_e: String,val stage : Int,val size:Int) |
package com.xkl.cdl.data.bean.intentdata | package com.xkl.cdl.data.bean.intentdata | ||||
import com.xkl.cdl.data.bean.VocabularyItem | |||||
import com.xkl.cdl.data.bean.course.ExamBean | import com.xkl.cdl.data.bean.course.ExamBean | ||||
import com.xkl.cdl.data.bean.course.Lesson | import com.xkl.cdl.data.bean.course.Lesson | ||||
* | * | ||||
* 课时学后测: coursePackType, courseType, testData ,lesson. | * 课时学后测: coursePackType, courseType, testData ,lesson. | ||||
* | * | ||||
* 词汇量测试: testData, vocabularyItem | |||||
*/ | */ | ||||
data class ExamData( | data class ExamData( | ||||
val subjectId : Int, //项目类型 | val subjectId : Int, //项目类型 | ||||
// 课程/课时学前测试正确错误列表 key=> {chapter_id}_{lesson_id}_{entity_id} value=>正确 true;错误 false | // 课程/课时学前测试正确错误列表 key=> {chapter_id}_{lesson_id}_{entity_id} value=>正确 true;错误 false | ||||
var mExamWRMap : HashMap<String, Boolean>? = null | var mExamWRMap : HashMap<String, Boolean>? = null | ||||
//测词汇量item | |||||
var vocabularyItem : VocabularyItem? = null | |||||
} | } |
abstract fun examDao() : ExamDao | abstract fun examDao() : ExamDao | ||||
abstract fun examItemDao(): ExamItemDao | abstract fun examItemDao(): ExamItemDao | ||||
abstract fun examMiddleDao(): ExamMiddleDao | abstract fun examMiddleDao(): ExamMiddleDao | ||||
abstract fun dictionaryDao(): DictionaryDao | |||||
companion object{ | companion object{ | ||||
private var DATABASE_NAME :String = "${FileUtil.getSaveDirPath("db")}${File.separator}app.db" | private var DATABASE_NAME :String = "${FileUtil.getSaveDirPath("db")}${File.separator}app.db" |
package com.xkl.cdl.data.exam_record | |||||
import androidx.room.Dao | |||||
import androidx.room.Insert | |||||
import androidx.room.OnConflictStrategy | |||||
import androidx.room.Query | |||||
import com.xkl.cdl.data.bean.DictionaryItem | |||||
@Dao | |||||
interface DictionaryDao { | |||||
@Insert(onConflict = OnConflictStrategy.REPLACE) | |||||
fun insert(item:DictionaryItem) | |||||
@Query("SELECT * FROM dic_history WHERE courseId = :courseId ORDER BY queryTime DESC LIMIT 30") | |||||
fun query(courseId : Long): MutableList<DictionaryItem> | |||||
@Query("DELETE FROM dic_history WHERE courseId = :courseId") | |||||
fun clear(courseId: Long) | |||||
} |
package com.xkl.cdl.data.manager.db | |||||
import android.widget.Toast | |||||
import com.google.common.base.Joiner | |||||
import com.suliang.common.util.AppGlobals | |||||
import com.suliang.common.util.LogUtil | |||||
import com.suliang.common.util.thread.AppExecutors | |||||
import com.xkl.cdl.data.bean.DictionaryItem | |||||
import com.xkl.cdl.data.manager.FilePathManager | |||||
import net.sqlcipher.database.SQLiteDatabase | |||||
import java.lang.StringBuilder | |||||
import java.util.* | |||||
/** | |||||
* author suliang | |||||
* create 2022/7/14 17:28 | |||||
* Describe: | |||||
*/ | |||||
object DictionaryManager { | |||||
private var mDataBase : SQLiteDatabase? = null | |||||
private var pwd : String = "XKL_XECD_DICT_DATA_KEY" | |||||
private const val DATA_DICT = "dict" | |||||
private const val MAX_COUNT = 50 | |||||
private fun open() { | |||||
synchronized(DictionaryManager) { | |||||
if (mDataBase == null) { | |||||
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getDictionaryDbPath().path, pwd, null, SQLiteDatabase.OPEN_READONLY) | |||||
} | |||||
if (mDataBase == null) { | |||||
AppExecutors.mainThread.run { | |||||
Toast.makeText(AppGlobals.application, "词典数据获取失败,请重启应用或联系业务员", Toast.LENGTH_LONG) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
//避免进行多次的查询 | |||||
private var count: Int = 0 | |||||
/** | |||||
* 简单版词典联想查询 | |||||
* @param keyWord 关键字 | |||||
* @param courseId 课程id,用于课程查询时用以记录历史记录的的courseId | |||||
* @return 查询结果 | |||||
*/ | |||||
fun queryKeyWordLikeMatchSimple(keyWord : String, courseId : Long = 0) : MutableList<DictionaryItem> { | |||||
//打开数据库 | |||||
open() | |||||
val currentCount : Int = count | |||||
LogUtil.e("开始查询 $count") | |||||
count++ | |||||
//1、完全匹配 | |||||
//2 、完全包含步变形匹配 | |||||
//3 、完全包含的变形完整匹配 | |||||
//4 、非完全包含的匹配 | |||||
val result : MutableList<DictionaryItem> = mutableListOf() | |||||
val titleMap : MutableMap<String, Int> = mutableMapOf() | |||||
var sql = "" | |||||
//1: wor | |||||
sql = "SELECT word FROM $DATA_DICT WHERE word = $keyWord" | |||||
query(sql, titleMap) | |||||
//2: wor% %wor% | |||||
sql = "SELECT word FROM $DATA_DICT WHERE word LIKE $keyWord || '%' LIMIT $MAX_COUNT" //完全匹配搜索:以关键字开头的搜索 | |||||
query(sql, titleMap) | |||||
if (titleMap.size < MAX_COUNT) { | |||||
sql = "SELECT word FROM $DATA_DICT WHERE word LIKE '%' || $keyWord || '%' LIMIT $MAX_COUNT" //查找任意位置包含keyword的值 | |||||
query(sql, titleMap) | |||||
if (titleMap.size < MAX_COUNT) { | |||||
//3:% w % o % r % | |||||
var newKeyWord : String = insertPercent(keyWord) | |||||
val length = keyWord.length | |||||
for (i in 0 until length - 1) { | |||||
val max : Int = MAX_COUNT - titleMap.size | |||||
newKeyWord = substringEnd(newKeyWord) | |||||
sql = "SELECT word FROM $DATA_DICT WHERE word LIKE \"$newKeyWord\" LIMIT $max" | |||||
query(sql, titleMap) | |||||
if (titleMap.size >= MAX_COUNT) break | |||||
} | |||||
} | |||||
} | |||||
//查询最终结果 | |||||
val list = ArrayList(titleMap.entries) | |||||
list.sortedWith{ o1, o2 -> o1.value.compareTo(o2.value) } | |||||
for (i in list.indices) { | |||||
if (count - currentCount != 1) break | |||||
query(list[i].key,courseId)?.let { | |||||
result.add(it) | |||||
} | |||||
} | |||||
LogUtil.e("结束查询 $count") | |||||
return result | |||||
} | |||||
/** | |||||
* 联想查询,仅查询title,并将title放入hashmap中 | |||||
* @param sql 查询数据 | |||||
* @param hashMap | |||||
*/ | |||||
private fun query(sql : String, hashMap : MutableMap<String, Int>) { | |||||
mDataBase?.rawQuery(sql, null)?.let { | |||||
while (it.moveToNext()) { | |||||
if (hashMap.size == MAX_COUNT) break //数量15则打断 | |||||
val title = it.getString(0) | |||||
if (hashMap[title] == null) { | |||||
hashMap[title] = hashMap.size + 1 | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private val builder = StringBuilder() | |||||
/** | |||||
* 字符串添加% | |||||
* @param value 字符串 | |||||
* @return | |||||
*/ | |||||
private fun insertPercent(value : String) : String { | |||||
val length = value.length | |||||
if (length == 0) { | |||||
return "" | |||||
} | |||||
builder.setLength(0) | |||||
builder.append("%") | |||||
for (i in 0 until length) { | |||||
builder.append(value[i]).append("%") | |||||
} | |||||
return builder.toString() | |||||
} | |||||
/** | |||||
* 去掉字符串最后一位 | |||||
* @param value 字符串 | |||||
* @return | |||||
*/ | |||||
private fun substringEnd(value : String) : String { | |||||
val length = value.length | |||||
return if (length == 0) { | |||||
"" | |||||
} else value.substring(0, length - 1) | |||||
} | |||||
/** | |||||
* 查询返回数据 精准匹配 | |||||
* @param word | |||||
* @return | |||||
*/ | |||||
fun query(keyWord : String,courseId : Long) : DictionaryItem?{ | |||||
var mDictionaryItem : DictionaryItem? = null | |||||
val sql = "SELECT * FROM $DATA_DICT WHERE word = \"$keyWord\"" | |||||
open() | |||||
mDataBase?.rawQuery(sql,null)?.let { | |||||
if (it.count > 0) { | |||||
it.moveToNext() | |||||
mDictionaryItem = DictionaryItem().apply { | |||||
this.courseId = courseId | |||||
id = it.getLong(0) //id | |||||
word = it.getString(1) //单词 | |||||
form = it.getInt(2) | |||||
pre_index = it.getString(3) | |||||
phonetic_uk = it.getString(4) | |||||
phonectic_us = it.getString(5) | |||||
phonectic_cn = it.getString(6) | |||||
// setPhoto(it.getString(7)) | |||||
// setAudio(it.getString(8)) | |||||
// setDifficulty(it.getInt(9)) | |||||
basic_explaination = it.getString(10) | |||||
all_explaination = it.getString(11) | |||||
phrase = it.getString(12) | |||||
example = it.getString(13) | |||||
reference = it.getString(14) | |||||
// setVersion(it.getInt(15)) //version版本 | |||||
} | |||||
} | |||||
it.close() | |||||
} | |||||
return mDictionaryItem | |||||
} | |||||
/** | |||||
* 查询返回数据 批量精准匹配 | |||||
* @param words | |||||
* @param courseId 课程查询的courseId | |||||
* @return | |||||
*/ | |||||
fun querys(words : List<String>,courseId : Long = 0 ) : List<DictionaryItem> { | |||||
val list : MutableList<DictionaryItem> = ArrayList<DictionaryItem>() | |||||
val sql = "SELECT * FROM " + DATA_DICT + " WHERE word IN (" + Joiner.on(",").join(words) + ")" | |||||
open() | |||||
mDataBase?.rawQuery(sql, null)?.let { | |||||
while (it.moveToNext()) { | |||||
val mDictionaryItem = DictionaryItem().apply { | |||||
this.courseId = courseId | |||||
id = it.getLong(0) //id | |||||
word = it.getString(1) //单词 | |||||
form = it.getInt(2) | |||||
pre_index = it.getString(3) | |||||
phonetic_uk = it.getString(4) | |||||
phonectic_us = it.getString(5) | |||||
phonectic_cn = it.getString(6) | |||||
// setPhoto(it.getString(7)) | |||||
// setAudio(it.getString(8)) | |||||
// setDifficulty(it.getInt(9)) | |||||
basic_explaination = it.getString(10) | |||||
all_explaination = it.getString(11) | |||||
phrase = it.getString(12) | |||||
example = it.getString(13) | |||||
reference = it.getString(14) | |||||
} | |||||
list.add(mDictionaryItem) | |||||
} | |||||
it.close() | |||||
} | |||||
//去重 排序 | |||||
return list.distinctBy { it.word }.sortedBy { | |||||
words.indexOf(it.word) | |||||
} | |||||
} | |||||
} |
package com.xkl.cdl.data.manager.db | package com.xkl.cdl.data.manager.db | ||||
import android.widget.Toast | import android.widget.Toast | ||||
import androidx.core.database.getBlobOrNull | |||||
import appApi.AppApi | import appApi.AppApi | ||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.util.AppGlobals | import com.suliang.common.util.AppGlobals | ||||
import com.suliang.common.util.file.FileUtil | |||||
import com.suliang.common.util.thread.AppExecutors | import com.suliang.common.util.thread.AppExecutors | ||||
import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
import com.xkl.cdl.data.bean.VocabularyItem | import com.xkl.cdl.data.bean.VocabularyItem | ||||
import com.xkl.cdl.data.bean.course.ExamBean | import com.xkl.cdl.data.bean.course.ExamBean | ||||
import com.xkl.cdl.data.manager.FilePathManager | import com.xkl.cdl.data.manager.FilePathManager | ||||
import net.sqlcipher.database.SQLiteDatabase | import net.sqlcipher.database.SQLiteDatabase | ||||
import java.io.File | |||||
/** | /** | ||||
* author suliang | * author suliang | ||||
*/ | */ | ||||
object VocabularyManager { | object VocabularyManager { | ||||
private var mDataBase : SQLiteDatabase? = null | |||||
private var mDataBase : SQLiteDatabase? = null | |||||
private var pwd : String = "XKL_VOCABULARY_DATA_KEY" //https://cdn.xuekaole.com/dict/vocabulary.db | |||||
// XKL_XECD_DICT_DATA_KEY https://cdn.xuekaole.com/dict/xecd_dict.db | |||||
private fun open() { | private fun open() { | ||||
synchronized(VocabularyManager) { | synchronized(VocabularyManager) { | ||||
if (mDataBase == null) { | if (mDataBase == null) { | ||||
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getVocabularyDbPath().path, "", null, SQLiteDatabase.OPEN_READONLY) | |||||
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getVocabularyDbPath().path, pwd, null, | |||||
SQLiteDatabase.OPEN_READONLY) | |||||
} | } | ||||
if (mDataBase == null) { | if (mDataBase == null) { | ||||
AppExecutors.mainThread.run { | AppExecutors.mainThread.run { | ||||
* @param level VocabularyItem | * @param level VocabularyItem | ||||
* @return List<ExamBean> | * @return List<ExamBean> | ||||
*/ | */ | ||||
fun queryVocabularyTestData(level : VocabularyItem) : List<ExamBean>{ | |||||
fun queryVocabularyTestData(level : VocabularyItem) : List<ExamBean> { | |||||
open() | open() | ||||
val result = mutableListOf<ExamBean>() | val result = mutableListOf<ExamBean>() | ||||
val sql = "SELECT * FROM " | |||||
val sql = "SELECT * FROM exam WHERE stage <= ${level.stage} ORDER BY random() LIMIT 100" | |||||
mDataBase?.rawQuery(sql, null)?.let { | |||||
while (it.moveToNext()) { | |||||
result.add(ExamBean().apply { | |||||
id = it.getLong(0) | |||||
word_id = it.getLong(1) | |||||
word = it.getString(2) | |||||
correct = it.getString(3) | |||||
error1 = it.getString(4) | |||||
error2 = it.getString(5) | |||||
error3 = it.getString(6) | |||||
}) | |||||
} | |||||
it.close() | |||||
} | |||||
return result; | |||||
} | } | ||||
/** | |||||
* 查询单词的发音音频 | |||||
* @param base DbControlBase | |||||
* @param wordId Long 查询单词 | |||||
* @param soundWay Int 发音方式 | |||||
* @return String 发音保存的文件名称 要不为空,要不为文件地址, 为空,则表明没有发音文件,如果是英美发音方式,则表示英美都没有发音内容 | |||||
*/ | |||||
fun queryAudio(wordId : Long, soundWay : Int) : String? { | |||||
val sql = "SELECT audio_us,audio_uk FROM exam WHERE word_id = $wordId" | |||||
var audio_us : ByteArray? = null | |||||
var audio_uk : ByteArray? = null | |||||
open() | |||||
mDataBase?.rawQuery(sql, null)?.let { | |||||
while (it.moveToNext()) { | |||||
//写入文件 | |||||
audio_us = it.getBlobOrNull(0) | |||||
audio_uk = it.getBlobOrNull(1) | |||||
} | |||||
it.close() | |||||
} | |||||
//不为空,写入本身,如果为空,用另外的发音方式写入 | |||||
val parentPath = FileUtil.getSaveDirPath(AppConfig.VOICE) | |||||
val audio_us_file_path = audio_us?.let { | |||||
val audioFileNameUS = "${wordId}_${AppConstants.SOUND_TYPE_US}" | |||||
val file = File(parentPath, audioFileNameUS) | |||||
FileUtil.writeBytesToFile(file, it) | |||||
file.path | |||||
} ?: audio_uk?.let { | |||||
val audioFileNameUS = "${wordId}_${AppConstants.SOUND_TYPE_US}" | |||||
val file = File(parentPath, audioFileNameUS) | |||||
FileUtil.writeBytesToFile(file, it) | |||||
file.path | |||||
} | |||||
//不为空,写入本身,如果为空,用另外的发音方式写入 | |||||
val audio_uk_file_path = audio_uk?.let { | |||||
val audioFileNameUk = "${wordId}_${AppConstants.SOUND_TYPE_UK}" | |||||
val file = File(parentPath, audioFileNameUk) | |||||
FileUtil.writeBytesToFile(file, it) | |||||
file.path | |||||
} ?: audio_us?.let { | |||||
val audioFileNameUk = "${wordId}_${AppConstants.SOUND_TYPE_UK}" | |||||
val file = File(parentPath, audioFileNameUk) | |||||
FileUtil.writeBytesToFile(file, it) | |||||
file.path | |||||
} | |||||
return if (soundWay == AppConstants.SOUND_TYPE_UK) audio_uk_file_path else audio_us_file_path | |||||
} | |||||
} | } |
import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
import com.xkl.cdl.data.manager.db.DBCourseManager | import com.xkl.cdl.data.manager.db.DBCourseManager | ||||
import com.xkl.cdl.data.manager.db.DbControlBase | import com.xkl.cdl.data.manager.db.DbControlBase | ||||
import com.xkl.cdl.data.manager.db.VocabularyManager | |||||
import io.reactivex.rxjava3.core.Observable | import io.reactivex.rxjava3.core.Observable | ||||
import java.io.File | import java.io.File | ||||
import java.util.* | import java.util.* | ||||
} | } | ||||
return lruCache[fileName] | return lruCache[fileName] | ||||
} | } | ||||
fun getVocabulary(wordId : Long,soundWay : Int){ | |||||
//父文件路劲 | |||||
val parentPath = FileUtil.getSaveDirPath(AppConfig.VOICE) | |||||
//先查对应的文件路径 : 项目id_课程包id_课程id_单词id_发音方式 | |||||
val defaultKey = "${wordId}_$soundWay" | |||||
Observable.fromCallable { | |||||
//不为空,直接取值 | |||||
if (lruCache.get(defaultKey) == null){ | |||||
//为空 查文件 | |||||
val file = File(parentPath, defaultKey) | |||||
when { | |||||
file.exists() -> lruCache.put(defaultKey, file.path) //文件存在,则表示以前进行过数据库查询,且进行了保存文件,英美发音本地都有文件 | |||||
else -> { //文件不存在,则查询数据库进行查询,返回的为保存的文件地址 | |||||
val filePath = VocabularyManager.queryAudio(wordId, soundWay) | |||||
filePath?.also { | |||||
when(soundWay){ | |||||
AppConstants.SOUND_TYPE_UK -> { | |||||
lruCache.put(defaultKey, it) //保存路径 | |||||
val audioFileNameUS = "${wordId}_${AppConstants.SOUND_TYPE_US}" | |||||
lruCache.put(audioFileNameUS, File(parentPath,audioFileNameUS).path) //保存路径 | |||||
} | |||||
AppConstants.SOUND_TYPE_US -> { | |||||
lruCache.put(defaultKey, it) //保存路径 | |||||
val audioFileNameUS = "${wordId}_${AppConstants.SOUND_TYPE_UK}" | |||||
lruCache.put(audioFileNameUS, File(parentPath,audioFileNameUS).path) //保存路径 | |||||
} | |||||
else -> lruCache.put(defaultKey, it) //保存路径 | |||||
} | |||||
} //如果查询返回路径为空,则说明,没有发音内容 | |||||
} | |||||
} | |||||
} | |||||
return@fromCallable lruCache.get(defaultKey) ?: "" | |||||
}.compose(diskIo2Main()).subscribe { | |||||
if (this::audioLiveData.isInitialized) | |||||
audioLiveData.value = it | |||||
} | |||||
} | |||||
} | } |
} | } | ||||
override fun resizeDialog(){} | |||||
} | } |
//备忘本测试 课程测试 | //备忘本测试 课程测试 | ||||
AppConstants.TEST_TYPE_SERVICE_CENTER, | AppConstants.TEST_TYPE_SERVICE_CENTER, | ||||
AppConstants.TEST_TYPE_MEMO -> initMemoTestOver() | AppConstants.TEST_TYPE_MEMO -> initMemoTestOver() | ||||
//词汇量测试结束 | |||||
} | } | ||||
//学习结束弹窗 | //学习结束弹窗 | ||||
AppConstants.DIALOG_TYPE_LEARNING_OVER -> initLessonLearningOver(false) | AppConstants.DIALOG_TYPE_LEARNING_OVER -> initLessonLearningOver(false) | ||||
} | } | ||||
} | } | ||||
override fun onStart() { | |||||
super.onStart() | |||||
//设置dialog位置 | |||||
requireDialog().window?.let { | |||||
it.attributes.run { | |||||
y = ScreenUtil.getScreenHeight() / 5 | |||||
it.attributes = this | |||||
} | |||||
it.setGravity(Gravity.TOP) | |||||
} | |||||
} | |||||
/** 初始化分数 */ | /** 初始化分数 */ | ||||
private fun initScore() { | private fun initScore() { | ||||
//插画 | //插画 |
package com.xkl.cdl.dialog | |||||
import android.annotation.SuppressLint | |||||
import android.os.Bundle | |||||
import android.view.Gravity | |||||
import android.view.View | |||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.base.BaseDialogFragment | |||||
import com.suliang.common.extension.click | |||||
import com.suliang.common.extension.setHtml | |||||
import com.suliang.common.util.os.ScreenUtil | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.databinding.DialogVocabularyBinding | |||||
/** | |||||
* author suliang | |||||
* create 2022/4/2 15:47 | |||||
* Describe: 词汇量测试结束弹窗 | |||||
*/ | |||||
class VocabularyDialog private constructor() : BaseDialogFragment<DialogVocabularyBinding>() { | |||||
companion object { | |||||
/** | |||||
* @param levelName String 测试级别 | |||||
* @param testTime String 测试时间 | |||||
* @param testCount Int 词汇量 | |||||
* @param coverRange Int 覆盖率 | |||||
* @return VocabularyDialog | |||||
*/ | |||||
fun newInstance( levelName:String, testTime : String, testCount: Int, coverRange:Int) : VocabularyDialog { | |||||
val args = Bundle() | |||||
args.putString(AppConfig.INTENT_1, levelName) | |||||
args.putString(AppConfig.INTENT_2, testTime) | |||||
args.putInt(AppConfig.INTENT_3, testCount) | |||||
args.putInt(AppConfig.INTENT_4, coverRange) | |||||
val fragment = VocabularyDialog() | |||||
fragment.arguments = args | |||||
return fragment | |||||
} | |||||
} | |||||
/** 事件动作 */ | |||||
lateinit var onDialogListener : (action : Int, dialog : VocabularyDialog) -> Unit | |||||
@SuppressLint("SetTextI18n") | |||||
override fun initFragment() { | |||||
val levelName = requireArguments().getString(AppConfig.INTENT_1) | |||||
val testTime = requireArguments().getString(AppConfig.INTENT_2) | |||||
val testCount = requireArguments().getInt(AppConfig.INTENT_3) | |||||
val coverRange = requireArguments().getInt(AppConfig.INTENT_4) | |||||
binding.tvVocabulary.text = "学考乐词汇量测试:$levelName" | |||||
binding.tvVocabularyTestTime.text = testTime | |||||
when(testCount){ | |||||
0 -> { | |||||
binding.groupVocabularyNormal.visibility = View.GONE | |||||
binding.tvVocabularyLittle.visibility = View.VISIBLE | |||||
binding.tvLeft.apply { | |||||
text = getString(R.string.done) | |||||
click { | |||||
onDialogListener(AppConstants.DIALOG_OVER,this@VocabularyDialog) | |||||
} | |||||
} | |||||
binding.tvRight.apply { | |||||
text = getString(R.string.test_again) | |||||
click { | |||||
onDialogListener(AppConstants.DIALOG_START_TEST,this@VocabularyDialog) | |||||
} | |||||
} | |||||
} | |||||
else -> { | |||||
binding.groupVocabularyNormal.visibility = View.VISIBLE | |||||
binding.tvVocabularyLittle.visibility = View.GONE | |||||
binding.tvVocabularyCount.text = "$testCount" | |||||
binding.ratingBar.setStar(coverRange / 20f) | |||||
binding.tvVocabularyCoverRateStage.setHtml("覆盖率<font color = \'#F7874F\'>${coverRange}%</font>($levelName)") | |||||
binding.tvLeft.apply { | |||||
text = getString(R.string.test_again) | |||||
click { | |||||
onDialogListener(AppConstants.DIALOG_START_TEST,this@VocabularyDialog) | |||||
} | |||||
} | |||||
binding.tvRight.apply { | |||||
text = getString(R.string.done) | |||||
click { | |||||
onDialogListener(AppConstants.DIALOG_OVER,this@VocabularyDialog) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
import com.xkl.cdl.data.AppConstants | import com.xkl.cdl.data.AppConstants | ||||
import com.xkl.cdl.data.DataTransferHolder | import com.xkl.cdl.data.DataTransferHolder | ||||
import com.xkl.cdl.data.bean.LearnDialogBean | import com.xkl.cdl.data.bean.LearnDialogBean | ||||
import com.xkl.cdl.data.bean.VocabularyItem | |||||
import com.xkl.cdl.data.bean.course.ExamBean | import com.xkl.cdl.data.bean.course.ExamBean | ||||
import com.xkl.cdl.data.event.LearnEventData | import com.xkl.cdl.data.event.LearnEventData | ||||
import com.xkl.cdl.data.manager.CourseManager | import com.xkl.cdl.data.manager.CourseManager | ||||
import com.xkl.cdl.dialog.CommonDialog | import com.xkl.cdl.dialog.CommonDialog | ||||
import com.xkl.cdl.dialog.CommonDialogBean | import com.xkl.cdl.dialog.CommonDialogBean | ||||
import com.xkl.cdl.dialog.LearnDialog | import com.xkl.cdl.dialog.LearnDialog | ||||
import com.xkl.cdl.dialog.VocabularyDialog | |||||
import com.xkl.cdl.module.m_service_center.TestDetailActivity | import com.xkl.cdl.module.m_service_center.TestDetailActivity | ||||
/** | /** | ||||
/** 新单词来了的发音事件 */ | /** 新单词来了的发音事件 */ | ||||
private fun initNewWordRead(it : ExamBean) { | private fun initNewWordRead(it : ExamBean) { | ||||
//词汇量测试,新单词发音 | |||||
if (vm.intentData.examType == AppConstants.TEST_TYPE_NORMAL){ | |||||
wordChooseBinding.ivVoice.performClick() | |||||
return | |||||
} | |||||
when (vm.intentData.courseType) { | when (vm.intentData.courseType) { | ||||
//拼写初始不发音,作文不发音, 音标课程测试不发音 | //拼写初始不发音,作文不发音, 音标课程测试不发音 | ||||
AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_ENGLISH_SPELL, AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_ENGLISH_SPELL, AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | ||||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | ||||
wordChooseBinding.ivVoice.performClick() | wordChooseBinding.ivVoice.performClick() | ||||
} | } | ||||
} | } | ||||
} | } | ||||
private fun initStatistics() { | private fun initStatistics() { | ||||
binding.incStatistics.run { | binding.incStatistics.run { | ||||
progressTestNumber.max = vm.testData.size | progressTestNumber.max = vm.testData.size | ||||
tvTestTypeName.text = CourseManager.getExamTypeName(vm.intentData.examType) | |||||
//测试类型 | |||||
tvTestTypeName.text = when (vm.intentData.examType) { | |||||
AppConstants.TEST_TYPE_NORMAL -> vm.intentData.vocabularyItem?.level | |||||
else -> CourseManager.getExamTypeName(vm.intentData.examType) | |||||
} | |||||
//监听总时间的改变 | //监听总时间的改变 | ||||
vm.totalUseTime.observe(this@LearnExamActivity) { | vm.totalUseTime.observe(this@LearnExamActivity) { | ||||
tvTestTime.text = DateUtil.formatGMT(it, DateUtil.FORMAT_2) | tvTestTime.text = DateUtil.formatGMT(it, DateUtil.FORMAT_2) | ||||
vm.errorLiveData.observe(this@LearnExamActivity) { | vm.errorLiveData.observe(this@LearnExamActivity) { | ||||
tvErrorNumber.text = "错误: $it" | tvErrorNumber.text = "错误: $it" | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} ?: let { //取消事件 | |||||
} ?: let { //取消选项答案选择事件,设置选项发音事件 | |||||
vm.optionList.forEachIndexed { index, optionItemBinding -> | vm.optionList.forEachIndexed { index, optionItemBinding -> | ||||
optionItemBinding.root.click(null) | optionItemBinding.root.click(null) | ||||
optionItemBinding.tvOption.click { optionItemBinding.ivOption.performClick() } | optionItemBinding.tvOption.click { optionItemBinding.ivOption.performClick() } | ||||
//口语的音频,有问题,与选项 直接获取其tag获取音频 | //口语的音频,有问题,与选项 直接获取其tag获取音频 | ||||
currentPlayView?.cancelAnimation() | currentPlayView?.cancelAnimation() | ||||
if (view is LottieAnimationView && view.visibility == View.VISIBLE) currentPlayView = view | if (view is LottieAnimationView && view.visibility == View.VISIBLE) currentPlayView = view | ||||
if (isSpokenTotalTest()) { | |||||
//口语课程学前学后总的点击事件取tag | |||||
AudioCache.get(view.tag as String) | |||||
} else { | |||||
AudioCache.get(vm.dbBaseControl, it.word_id, vm.defaultSoundWay) | |||||
when{ | |||||
//词汇量测试 | |||||
vm.intentData.examType == AppConstants.TEST_TYPE_NORMAL -> AudioCache.getVocabulary(it.word_id,vm.defaultSoundWay) | |||||
//口语 | |||||
isSpokenTotalTest() -> AudioCache.get(view.tag as String) | |||||
//测试 | |||||
else -> AudioCache.get(vm.dbBaseControl, it.word_id, vm.defaultSoundWay) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/** 测试完成 : 弹窗显示 */ | /** 测试完成 : 弹窗显示 */ | ||||
private fun testOver() { | private fun testOver() { | ||||
if (vm.intentData.examType == AppConstants.TEST_TYPE_NORMAL){ | |||||
vm.intentData.vocabularyItem?.let { | |||||
val createTime = DateUtil.format(System.currentTimeMillis(), DateUtil.FORMAT_1) | |||||
VocabularyDialog.newInstance(it.level,createTime,vm.scoreValue,vm.vocabularyCoverange).apply { | |||||
onDialogListener = { action, dialog -> | |||||
when(action){ | |||||
//完成 | |||||
AppConstants.DIALOG_OVER -> { | |||||
dialog.dismissAllowingStateLoss() | |||||
finish() | |||||
} | |||||
//再测一次 | |||||
AppConstants.DIALOG_START_TEST -> { | |||||
dialog.dismissAllowingStateLoss() | |||||
finish() | |||||
LiveEventBus.get<VocabularyItem>("vocabulary_test").post(vm.intentData.vocabularyItem) | |||||
} | |||||
} | |||||
} | |||||
}.show(supportFragmentManager,"vocabulary") | |||||
} | |||||
return | |||||
} | |||||
//对话框信息实体 | //对话框信息实体 | ||||
val learnDialogBean = LearnDialogBean(AppConstants.DIALOG_TYPE_EXAM_OVER).apply { | val learnDialogBean = LearnDialogBean(AppConstants.DIALOG_TYPE_EXAM_OVER).apply { | ||||
examType = vm.intentData.examType | examType = vm.intentData.examType | ||||
score = vm.scoreValue | score = vm.scoreValue | ||||
correctNumber = vm.correctLiveData.value!! | correctNumber = vm.correctLiveData.value!! | ||||
errorNumber = vm.errorLiveData.value!! | errorNumber = vm.errorLiveData.value!! | ||||
//备忘本需要显示课程名称 | |||||
if (examType == AppConstants.TEST_TYPE_MEMO || examType == AppConstants.TEST_TYPE_SERVICE_CENTER){ | |||||
//备忘本、课程测试需要显示课程名称 | |||||
if (examType == AppConstants.TEST_TYPE_MEMO || examType == AppConstants.TEST_TYPE_SERVICE_CENTER) { | |||||
showTimeCount = vm.intentData.showTitle | showTimeCount = vm.intentData.showTitle | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
//备忘本测试 | //备忘本测试 | ||||
AppConstants.TEST_TYPE_SERVICE_CENTER, | |||||
AppConstants.TEST_TYPE_MEMO -> when(action){ | |||||
AppConstants.TEST_TYPE_SERVICE_CENTER, AppConstants.TEST_TYPE_MEMO -> when (action) { | |||||
//完成 | //完成 | ||||
AppConstants.DIALOG_OVER -> { | AppConstants.DIALOG_OVER -> { | ||||
dialog.dismissAllowingStateLoss() | dialog.dismissAllowingStateLoss() |
createErrorRecord() | createErrorRecord() | ||||
} | } | ||||
} | } | ||||
//添加到记录集合 | |||||
mExamRecordList.add(currentExamRecord!!.build()) | |||||
//添加到记录集合 词汇量测试不添加记录 | |||||
if (intentData.examType != AppConstants.TEST_TYPE_NORMAL) { | |||||
mExamRecordList.add(currentExamRecord!!.build()) | |||||
} | |||||
currentChooseResultLiveData.value = chooseResult | currentChooseResultLiveData.value = chooseResult | ||||
} | } | ||||
//分数 与 覆盖率 只有测试成功才进行计算 | //分数 与 覆盖率 只有测试成功才进行计算 | ||||
if (isVocablularySuccess) { | if (isVocablularySuccess) { | ||||
val converange = (calculateCorrectNumber - 25) / 75 //被测试题的占比重 | val converange = (calculateCorrectNumber - 25) / 75 //被测试题的占比重 | ||||
// TODO: 2022/4/14 16000应该为该词汇量测试对应的词汇数 | |||||
scoreValue = (16000 * converange).toInt() | |||||
// 用了了100只是预防取值错误时不好看 | |||||
scoreValue = ( intentData.vocabularyItem?.size ?: 100 * converange).toInt() | |||||
vocabularyCoverange = (converange * 100).toInt() //测试类型的覆盖率 | vocabularyCoverange = (converange * 100).toInt() //测试类型的覆盖率 | ||||
} | } | ||||
} | } | ||||
stage = "小学" | stage = "小学" | ||||
coverRate = vocabularyCoverange.toFloat() | coverRate = vocabularyCoverange.toFloat() | ||||
} | } | ||||
//添加测试题 | |||||
addAllRecord(mExamRecordList) | |||||
//添加测试题 词汇量测试不添加测试题 | |||||
if (intentData.examType != AppConstants.TEST_TYPE_NORMAL) { | |||||
addAllRecord(mExamRecordList) | |||||
} | |||||
} | } | ||||
// //是否完成 | |||||
// if (examType == SyncStateContract.Constants.TEST_TYPE_AFTER_TOTAL && mData.getScore() >= SyncStateContract.Constants.SCORE_1 && !mData.isCourseFinished()) { | |||||
// learnExam.setIsFinished(true) | |||||
// } | |||||
//最终上传数据 | //最终上传数据 | ||||
record.addExam(learnExam) //测试试卷 | record.addExam(learnExam) //测试试卷 | ||||
//时间 学习中心的测试需要添加为学习时间 | //时间 学习中心的测试需要添加为学习时间 |
package com.xkl.cdl.module.m_service_center | |||||
import android.annotation.SuppressLint | |||||
import android.content.Context | |||||
import android.content.Intent | |||||
import android.os.Bundle | |||||
import android.view.View | |||||
import androidx.lifecycle.ViewModelProvider | |||||
import androidx.recyclerview.widget.LinearLayoutManager | |||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.base.activity.BaseActivityVM | |||||
import com.suliang.common.extension.click | |||||
import com.xkl.cdl.R | |||||
import com.xkl.cdl.databinding.ActivityDictionaryBinding | |||||
import com.xkl.cdl.dialog.CommonDialog | |||||
import com.xkl.cdl.dialog.CommonDialogBean | |||||
import com.xkl.cdl.module.m_service_center.DictionaryViewModel.Companion.STATE_HISTROY | |||||
import com.xkl.cdl.module.m_service_center.DictionaryViewModel.Companion.STATE_SEARCH | |||||
class DictionaryActivity : BaseActivityVM<ActivityDictionaryBinding, DictionaryViewModel>() { | |||||
companion object { | |||||
fun newInstance(context : Context, courseId : Long = 0) { | |||||
val intent = Intent(context, DictionaryActivity::class.java) | |||||
intent.putExtra(AppConfig.INTENT_1, courseId) | |||||
context.startActivity(intent) | |||||
} | |||||
} | |||||
override fun initViewModel() : DictionaryViewModel { | |||||
return ViewModelProvider(this)[DictionaryViewModel::class.java] | |||||
} | |||||
@SuppressLint("NotifyDataSetChanged") | |||||
override fun initActivity(savedInstanceState : Bundle?) { | |||||
vm.courseId = intent.getLongExtra(AppConfig.INTENT_1, 0) | |||||
initHistoryRecyclerView() | |||||
//点击 查看更多 | |||||
binding.tvSeeMore.click { | |||||
when (vm.detailState) { | |||||
STATE_HISTROY -> { | |||||
//显示页面加1, 列表更新 | |||||
vm.histroyShowPage++ | |||||
vm.adapter.notifyDataSetChanged() | |||||
//根据数量判断,是否还要显示 | |||||
binding.tvSeeMore.visibility = if (vm.historyList.size > vm.histroyShowPage * vm.historyPageSize) View.VISIBLE else View.GONE | |||||
} | |||||
STATE_SEARCH -> { | |||||
//显示页面加1, 列表更新 | |||||
vm.searchShowPage++ | |||||
vm.adapter.notifyDataSetChanged() | |||||
//根据数量判断,是否还要显示 | |||||
binding.tvSeeMore.visibility = if (vm.searchDetailList.size > vm.searchShowPage * vm.historyPageSize) View.VISIBLE else View.GONE | |||||
} | |||||
} | |||||
} | |||||
//删除历史记录,弹窗提示 | |||||
binding.ivDelete.click { | |||||
val commonDialogBean = CommonDialogBean(titleText = R.string.dialog_delete_history, leftText = R.string.delete, | |||||
rightText = R.string.cancel) | |||||
CommonDialog.newInstance(commonDialogBean).apply { | |||||
onCommonDialogButtonClickListener = { dialog : CommonDialog, isRightClick : Boolean -> | |||||
if (!isRightClick) { //删除 | |||||
vm.clearHistory() | |||||
} | |||||
dialog.dismissAllowingStateLoss() | |||||
} | |||||
}.show(supportFragmentManager, javaClass.name) | |||||
} | |||||
} | |||||
private fun initHistoryRecyclerView() { | |||||
binding.rv.apply { | |||||
layoutManager = LinearLayoutManager(this@DictionaryActivity, LinearLayoutManager.VERTICAL, false) | |||||
adapter = vm.adapter | |||||
} | |||||
} | |||||
@SuppressLint("NotifyDataSetChanged") | |||||
override fun loadData() { | |||||
//更新历史记录适配器 | |||||
vm.updateHistoryAdapterLiveData.observe(this) { | |||||
when { | |||||
//历史记录 | |||||
!it -> vm.adapter.apply { | |||||
//如果非历史列表记录,则更新列表布局的状态 | |||||
if (vm.detailState != STATE_HISTROY) { | |||||
vm.detailState = STATE_HISTROY | |||||
binding.apply { | |||||
tvHistoryTitle.visibility = View.VISIBLE | |||||
ivDelete.visibility = View.VISIBLE | |||||
} | |||||
} | |||||
binding.layoutDetail.visibility = if (vm.historyList.isEmpty()) View.GONE else View.VISIBLE | |||||
binding.tvSeeMore.visibility = if (vm.historyList.size > vm.histroyShowPage * vm.historyPageSize) View.VISIBLE else View.GONE | |||||
//更新值 | |||||
needShowEmptyView = false | |||||
setData(vm.historyList) | |||||
} | |||||
//搜索结果 | |||||
else -> vm.adapter.apply { | |||||
if (vm.detailState != STATE_SEARCH) { | |||||
vm.detailState = STATE_SEARCH | |||||
binding.apply { | |||||
tvHistoryTitle.visibility = View.GONE | |||||
ivDelete.visibility = View.GONE | |||||
} | |||||
} | |||||
binding.layoutDetail.visibility = View.VISIBLE | |||||
binding.tvSeeMore.visibility = if (vm.searchDetailList.size > vm.searchShowPage * vm.historyPageSize) View.VISIBLE else View.GONE | |||||
needShowEmptyView = vm.searchDetailList.size == 0 | |||||
setData(vm.searchDetailList) | |||||
} | |||||
} | |||||
} | |||||
/**搜索监听*/ | |||||
vm.etSearchLiveData.observe(this) { | |||||
when { | |||||
//直接历史记录更新 | |||||
it.isNullOrEmpty() -> vm.updateHistoryAdapterLiveData.value = false | |||||
//历史记录的详情 | |||||
vm.searchItemDetailAble -> { | |||||
} | |||||
//关键字搜索 | |||||
else -> vm.searchKeyWord(it) | |||||
} | |||||
} | |||||
//查询历史记录 | |||||
vm.loadHistory() | |||||
} | |||||
/** | |||||
* 详情中的状态 | |||||
* @param state Int 1历史记录 2搜索详情 | |||||
*/ | |||||
private fun initLayoutDetailState(state : Int) { | |||||
when (state) { | |||||
//历史布局 | |||||
STATE_HISTROY -> binding.apply { | |||||
tvHistoryTitle.visibility = View.VISIBLE | |||||
ivDelete.visibility = View.VISIBLE | |||||
} | |||||
//查询详情 | |||||
STATE_SEARCH -> binding.apply { | |||||
tvHistoryTitle.visibility = View.GONE | |||||
ivDelete.visibility = View.GONE | |||||
} | |||||
} | |||||
binding.tvSeeMore.visibility = View.GONE | |||||
} | |||||
} |
package com.xkl.cdl.module.m_service_center | |||||
import android.os.Handler | |||||
import android.os.Looper | |||||
import androidx.lifecycle.MutableLiveData | |||||
import com.suliang.common.base.viewmodel.BaseViewModel | |||||
import com.suliang.common.util.thread.AppExecutors | |||||
import com.xkl.cdl.adapter.DictionaryAdapter | |||||
import com.xkl.cdl.data.bean.DictionaryItem | |||||
import com.xkl.cdl.data.exam_record.AppDatabase | |||||
import com.xkl.cdl.data.manager.db.DictionaryManager | |||||
import io.reactivex.rxjava3.core.Observable | |||||
import io.reactivex.rxjava3.schedulers.Schedulers | |||||
class DictionaryViewModel : BaseViewModel() { | |||||
//courseId 记录为是否为课程查询,课程历史记录为课程,否则为0词典查询 | |||||
var courseId : Long = 0 | |||||
//记录状态 | |||||
companion object { | |||||
const val STATE_HISTROY = 1 | |||||
const val STATE_SEARCH = 2 | |||||
} | |||||
//适配器 | |||||
val adapter = DictionaryAdapter(this) | |||||
//输入框监听 | |||||
val etSearchLiveData = MutableLiveData<String>() | |||||
//状态 : 默认历史记录 | |||||
var detailState = STATE_HISTROY | |||||
//历史记录集合 | |||||
val historyList = mutableListOf<DictionaryItem>() | |||||
//更新详情适配器 false:历史记录 true:联想搜索结果 | |||||
val updateHistoryAdapterLiveData = MutableLiveData<Boolean>() | |||||
//历史记录,显示的页数 | |||||
var histroyShowPage = 1 | |||||
var searchShowPage = 1 | |||||
//一页显示的历史记录个数,最多历史记录显示30个 | |||||
val historyPageSize = 10 | |||||
//搜索结果,做多匹配显示50个 | |||||
//是否显示搜索单词的详情 true:显示单条记录的详情 false:搜索显示的为搜索结果的列表详情 | |||||
var searchItemDetailAble = false | |||||
//搜索结果 多条为联想结果 单条基本为搜索的详情结果 | |||||
var searchDetailList = mutableListOf<DictionaryItem>() | |||||
val handler : Handler = Handler(Looper.getMainLooper()) | |||||
//记录联想结果中为历史记录的位置 | |||||
val searchListForHistoryPositionMap = mutableMapOf<Int,Int>() | |||||
/** | |||||
* 查询搜索历史 | |||||
*/ | |||||
fun loadHistory() { | |||||
Observable.fromCallable { | |||||
val history = AppDatabase.instance.dictionaryDao().query(courseId) | |||||
historyList.addAll(history) | |||||
updateHistoryAdapterLiveData.postValue(false) | |||||
}.observeOn(Schedulers.from(AppExecutors.io)).subscribe() | |||||
} | |||||
/**清空历史记录*/ | |||||
fun clearHistory() { | |||||
Observable.fromCallable { | |||||
historyList.clear() | |||||
updateHistoryAdapterLiveData.postValue(false) | |||||
AppDatabase.instance.dictionaryDao().clear(courseId) | |||||
}.observeOn(Schedulers.from(AppExecutors.io)).subscribe() | |||||
} | |||||
/** | |||||
* 关键字搜索 | |||||
* @param keyWord String | |||||
*/ | |||||
fun searchKeyWord(keyWord : String) { | |||||
handler.removeCallbacksAndMessages(null) | |||||
handler.postDelayed({ | |||||
Observable.fromCallable { | |||||
//清空位置对应信息 | |||||
searchListForHistoryPositionMap.clear() | |||||
//联想查询结果 | |||||
searchDetailList = DictionaryManager.queryKeyWordLikeMatchSimple(keyWord) | |||||
//搜索记录中获取历史记录位置 需要判断是否有历史记录 | |||||
if (historyList.isNotEmpty() && searchDetailList.isNotEmpty()) { | |||||
historyList.forEachIndexed { historyIndex, historyItem -> | |||||
searchDetailList.forEachIndexed { searchIndex, searchItem -> | |||||
if (historyItem.word == searchItem.word) { | |||||
searchItem.inHistory = true | |||||
searchListForHistoryPositionMap.put(searchIndex, historyIndex) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
//更新搜索结果 | |||||
updateHistoryAdapterLiveData.postValue(true) | |||||
}.observeOn(Schedulers.from(AppExecutors.io)).subscribe() | |||||
}, 300) | |||||
} | |||||
} |
import com.suliang.common.base.fragment.BaseFragmentVM | import com.suliang.common.base.fragment.BaseFragmentVM | ||||
import com.suliang.common.extension.click | import com.suliang.common.extension.click | ||||
import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
import com.xkl.cdl.adapter.DictionaryAdapter | |||||
import com.xkl.cdl.databinding.FragmentMyBinding | import com.xkl.cdl.databinding.FragmentMyBinding | ||||
import com.xkl.cdl.databinding.ItemServiceCenterItemBinding | import com.xkl.cdl.databinding.ItemServiceCenterItemBinding | ||||
import com.xkl.cdl.databinding.ServiceCenterFragmentBinding | import com.xkl.cdl.databinding.ServiceCenterFragmentBinding | ||||
import com.xkl.cdl.module.main.MainActivityViewModel | import com.xkl.cdl.module.main.MainActivityViewModel | ||||
class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, MainActivityViewModel>() { | |||||
class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, MainActivityViewModel>() { | |||||
companion object { | companion object { | ||||
@JvmStatic | @JvmStatic | ||||
fun newInstance() = ServiceCenterFragment() | fun newInstance() = ServiceCenterFragment() | ||||
override fun initFragment() { | override fun initFragment() { | ||||
val items = mutableListOf(Item("课程测试", R.drawable.ic_test_course, Color.parseColor("#1A58D4DB")), | val items = mutableListOf(Item("课程测试", R.drawable.ic_test_course, Color.parseColor("#1A58D4DB")), | ||||
Item("测词汇量", R.drawable.ic_test_count, Color.parseColor("#1AFF8B52")), | |||||
Item("测试成绩", R.drawable.ic_test_score, Color.parseColor("#1AF26255")), | |||||
Item("词典", R.drawable.ic_dictionary, Color.parseColor("#1A52CC52"))) | |||||
Item("测词汇量", R.drawable.ic_test_count, Color.parseColor("#1AFF8B52")), | |||||
Item("测试成绩", R.drawable.ic_test_score, Color.parseColor("#1AF26255")), | |||||
Item("词典", R.drawable.ic_dictionary, Color.parseColor("#1A52CC52"))) | |||||
binding.rv.apply { | binding.rv.apply { | ||||
layoutManager = GridLayoutManager(requireContext(),2,GridLayoutManager.VERTICAL,false) | |||||
layoutManager = GridLayoutManager(requireContext(), 2, GridLayoutManager.VERTICAL, false) | |||||
setHasFixedSize(true) | setHasFixedSize(true) | ||||
adapter = object : BaseRVAdapter<Item>() { | adapter = object : BaseRVAdapter<Item>() { | ||||
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder { | ||||
return BaseAdapterViewHolder(inflateBinding(parent,R.layout.item_service_center_item)) | |||||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_service_center_item)) | |||||
} | } | ||||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | ||||
val item = getItem(position) | val item = getItem(position) | ||||
(holder.binding as ItemServiceCenterItemBinding).apply { | (holder.binding as ItemServiceCenterItemBinding).apply { | ||||
} | } | ||||
private fun startTo(position : Int) { | private fun startTo(position : Int) { | ||||
when(position){ | |||||
0 -> startActivity(CourseTestActivity::class.java) | |||||
1 -> startActivity(TestVocabularyActivity::class.java) | |||||
2 -> startActivity(TestScoreActivity::class.java) | |||||
3 -> "" | |||||
context?.let { | |||||
when (position) { | |||||
0 -> startActivity(CourseTestActivity::class.java) | |||||
1 -> startActivity(TestVocabularyActivity::class.java) | |||||
2 -> startActivity(TestScoreActivity::class.java) | |||||
3 -> DictionaryActivity.newInstance(it) | |||||
} | |||||
} | } | ||||
} | } | ||||
override fun loadData() { | override fun loadData() { | ||||
} | } | ||||
override fun initViewModel(): MainActivityViewModel { | |||||
override fun initViewModel() : MainActivityViewModel { | |||||
return ViewModelProvider(requireActivity())[MainActivityViewModel::class.java] | return ViewModelProvider(requireActivity())[MainActivityViewModel::class.java] | ||||
} | } | ||||
data class Item(val name : String, val icon : Int, val backgroundColor:Int) | |||||
data class Item(val name : String, val icon : Int, val backgroundColor : Int) | |||||
} | } |
if (vm.learnExam.score > 0){ | if (vm.learnExam.score > 0){ | ||||
groupVocabularyLittle.visibility = View.GONE | groupVocabularyLittle.visibility = View.GONE | ||||
groupVocabularyNormal.visibility = View.VISIBLE | groupVocabularyNormal.visibility = View.VISIBLE | ||||
tvVocabularyCount.text = "${vm.learnExam.score}" | |||||
tvVocabularyCount.text = "${vm.learnExam.score.toInt()}" | |||||
ratingBar.setStar(vm.learnExam.score/20) | ratingBar.setStar(vm.learnExam.score/20) | ||||
tvVocabularyCoverRateStage.setHtml("覆盖率<font color=\'#F7874F\'>${vm.learnExam.coverRate}%</font>\t\t(${vm.learnExam.stage})") | tvVocabularyCoverRateStage.setHtml("覆盖率<font color=\'#F7874F\'>${vm.learnExam.coverRate}%</font>\t\t(${vm.learnExam.stage})") | ||||
}else{ | }else{ |
import android.view.ViewGroup | import android.view.ViewGroup | ||||
import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
import androidx.recyclerview.widget.LinearLayoutManager | import androidx.recyclerview.widget.LinearLayoutManager | ||||
import com.jeremyliao.liveeventbus.LiveEventBus | |||||
import com.suliang.common.AppConfig | |||||
import com.suliang.common.base.activity.BaseActivityVM | import com.suliang.common.base.activity.BaseActivityVM | ||||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | import com.suliang.common.base.adapter.BaseAdapterViewHolder | ||||
import com.suliang.common.base.adapter.BaseRVAdapter | import com.suliang.common.base.adapter.BaseRVAdapter | ||||
import com.suliang.common.extension.click | import com.suliang.common.extension.click | ||||
import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
import com.xkl.cdl.data.AppConstants | |||||
import com.xkl.cdl.data.DataTransferHolder | |||||
import com.xkl.cdl.data.bean.VocabularyItem | import com.xkl.cdl.data.bean.VocabularyItem | ||||
import com.xkl.cdl.data.bean.intentdata.ExamData | |||||
import com.xkl.cdl.databinding.ActivityTestVocabularyBinding | import com.xkl.cdl.databinding.ActivityTestVocabularyBinding | ||||
import com.xkl.cdl.databinding.ItemVocabularyLevelBinding | import com.xkl.cdl.databinding.ItemVocabularyLevelBinding | ||||
import com.xkl.cdl.module.learn.LearnExamActivity | |||||
class TestVocabularyActivity : BaseActivityVM<ActivityTestVocabularyBinding, TestVocabularyViewModle>() { | class TestVocabularyActivity : BaseActivityVM<ActivityTestVocabularyBinding, TestVocabularyViewModle>() { | ||||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_vocabulary_level)) | return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_vocabulary_level)) | ||||
} | } | ||||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | ||||
getItem(position).let { | |||||
getItem(position).let { item -> | |||||
(holder.binding as ItemVocabularyLevelBinding).run { | (holder.binding as ItemVocabularyLevelBinding).run { | ||||
iv.setImageResource(it.icon) | |||||
tvLevel.text = it.level | |||||
tvLevelE.text = it.level_e | |||||
root.click { | |||||
// vm.queryVocabulary(it) | |||||
iv.setImageResource(item.icon) | |||||
tvLevel.text = item.level | |||||
tvLevelE.text = item.level_e | |||||
root.click { v -> | |||||
startTest(item) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
override fun loadData() { | override fun loadData() { | ||||
LiveEventBus.get<VocabularyItem>("vocabulary_test").observe(this){ | |||||
it?.let { | |||||
startTest(it) | |||||
} | |||||
} | |||||
} | } | ||||
/** | |||||
* 开始测试 | |||||
* @param item VocabularyItem | |||||
*/ | |||||
private fun startTest(item:VocabularyItem){ | |||||
vm.queryVocabularyTestData(item).observe(this@TestVocabularyActivity){ list -> | |||||
val examData = ExamData(AppConstants.SUBJECT_ENGLISH,AppConstants.TEST_TYPE_NORMAL,"词汇量测试","词汇量测试:${item.level}").apply { | |||||
testData = list | |||||
vocabularyItem = item | |||||
} | |||||
DataTransferHolder.instance.putData(key = AppConfig.INTENT_1,examData) | |||||
startActivity(LearnExamActivity::class.java) | |||||
} | |||||
} | |||||
} | } |
import com.xkl.cdl.data.bean.VocabularyItem | import com.xkl.cdl.data.bean.VocabularyItem | ||||
import com.xkl.cdl.data.bean.course.ExamBean | import com.xkl.cdl.data.bean.course.ExamBean | ||||
import com.xkl.cdl.data.manager.db.DBCourseManager | import com.xkl.cdl.data.manager.db.DBCourseManager | ||||
import com.xkl.cdl.data.manager.db.VocabularyManager | |||||
import io.reactivex.rxjava3.core.Observable | import io.reactivex.rxjava3.core.Observable | ||||
/** | /** | ||||
* Describe: | * Describe: | ||||
*/ | */ | ||||
class TestVocabularyViewModle : BaseViewModel() { | class TestVocabularyViewModle : BaseViewModel() { | ||||
// VOCABULARY":"{\"list\": | |||||
// [{\"id\":10,\"title\":\"综合测试\",\"title_en\":\"Comprehensive test\",\"vocabulary\":13000,}, | |||||
// {\"id\":2,\"title\":\"小学\",\"title_en\":\"Primary school\",\"vocabulary\":1000,}, | |||||
// {\"id\":3,\"title\":\"初中\",\"title_en\":\"Junior high school\",\"vocabulary\":2100,}, | |||||
// {\"id\":4,\"title\":\"高中\",\"title_en\":\"Senior high school\",\"vocabulary\":3500,}, | |||||
// {\"id\":5,\"title\":\"大学四级\",\"title_en\":\"College English Test Band 4\",\"vocabulary\":4200,}, | |||||
// {\"id\":6,\"title\":\"大学六级\",\"title_en\":\"College English Test Band 6\",\"vocabulary\":6000,}, | |||||
// {\"id\":7,\"title\":\"雅思\",\"title_en\":\"Lelts\",\"vocabulary\":7500,}, | |||||
// {\"id\":8,\"title\":\"托福\",\"title_en\":\"Toefl\",\"vocabulary\":8000,], | |||||
val data = mutableListOf( | 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,"托福","") ) | |||||
VocabularyItem(R.mipmap.ic_comprehensive_test,"综合测试","Comprehensive test",10,13000), | |||||
VocabularyItem(R.mipmap.ic_primary_school,"小学","Primary school",2,1000), | |||||
VocabularyItem(R.mipmap.ic_junior_school,"初中","Junior high school",3,2100), | |||||
VocabularyItem(R.mipmap.ic_high_school,"高中","Senior high school",4,3500), | |||||
VocabularyItem(R.mipmap.ic_university_4,"大学四级","College English Test Band 4",5,4200), | |||||
VocabularyItem(R.mipmap.ic_university_6,"大学六级","College English Test Band 6",6,6000), | |||||
VocabularyItem(R.mipmap.ic_lelts,"雅思","Lelts",7,7500), | |||||
VocabularyItem(R.mipmap.ic_toefl,"托福","Toefl",8,8000) ) | |||||
/** | /** | ||||
* 查询测试数据 | * 查询测试数据 | ||||
fun queryVocabularyTestData(item : VocabularyItem) : MutableLiveData<List<ExamBean>> { | fun queryVocabularyTestData(item : VocabularyItem) : MutableLiveData<List<ExamBean>> { | ||||
val result = MutableLiveData<List<ExamBean>>() | val result = MutableLiveData<List<ExamBean>>() | ||||
Observable.create<List<ExamBean>> { | Observable.create<List<ExamBean>> { | ||||
it.onNext(DBCourseManager.queryLearnTest(dbControlBase, testType, lesson)) | |||||
it.onNext(VocabularyManager.queryVocabularyTestData(item)) | |||||
it.onComplete() | it.onComplete() | ||||
}.compose(diskIo2Main()).subscribe({ | }.compose(diskIo2Main()).subscribe({ | ||||
result.value = it | result.value = it |
//复制词典 和 词汇量测试 | //复制词典 和 词汇量测试 | ||||
val dictionary = FilePathManager.getDictionaryDbPath() | val dictionary = FilePathManager.getDictionaryDbPath() | ||||
if (!dictionary.exists()) { | if (!dictionary.exists()) { | ||||
val copyAssetResult = FileUtil.copyAsset("dictionary.db", dictionary) | |||||
FileUtil.copyAsset("dictionary.db", dictionary) | |||||
} | } | ||||
val vocabulary = FilePathManager.getVocabularyDbPath() | val vocabulary = FilePathManager.getVocabularyDbPath() | ||||
if (!dictionary.exists()) { | |||||
val copyAssetResult = FileUtil.copyAsset("vocabulary.db", vocabulary) | |||||
if (!vocabulary.exists()) { | |||||
FileUtil.copyAsset("vocabulary.db", vocabulary) | |||||
} | } | ||||
// TODO: 2022/3/22 读取当前app绑定的课程数据, | // TODO: 2022/3/22 读取当前app绑定的课程数据, |
<?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.DictionaryViewModel" /> | |||||
</data> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
tools:context=".module.m_service_center.DictionaryActivity" | |||||
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_constraintTop_toTopOf="parent" /> | |||||
<com.google.android.material.imageview.ShapeableImageView | |||||
android:id="@+id/iv" | |||||
android:layout_width="72dp" | |||||
android:layout_height="72dp" | |||||
android:src="@drawable/ic_dictionary" | |||||
android:background="#1A58D4DB" | |||||
app:shapeAppearance="@style/CircleStyle" | |||||
app:contentPadding="@dimen/global_spacing" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/title_bar" /> | |||||
<TextView | |||||
android:id="@+id/tv_title" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="@string/xkl_dictionary" | |||||
app:layout_constraintTop_toBottomOf="@+id/iv" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
android:textSize="22dp" | |||||
android:textColor="@color/main_text_color" | |||||
android:textStyle="bold" | |||||
android:layout_marginTop="12dp" /> | |||||
<com.suliang.common.widget.InputSearchEditText | |||||
android:id="@+id/et_search" | |||||
android:layout_width="0dp" | |||||
android:layout_height="40dp" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_title" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
android:layout_marginTop="24dp" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:background="@drawable/shape_rounder_8_stroke_gray1" | |||||
android:paddingStart="@dimen/global_spacing" | |||||
android:paddingEnd="@dimen/global_spacing" | |||||
android:drawablePadding="4dp" | |||||
android:textSize="@dimen/smallSize" | |||||
android:gravity="center_vertical" | |||||
android:hint="输入你要搜索的内容…" | |||||
android:text="@{vm.etSearchLiveData}"/> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_detail" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/et_search" | |||||
android:layout_marginTop="12dp" | |||||
android:background="@drawable/shape_rounder_8_solid_green1" | |||||
android:backgroundTint="@color/gray_3" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginEnd="@dimen/global_spacing"> | |||||
<View | |||||
android:id="@+id/v_line" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="@dimen/line_height" | |||||
android:background="@color/gray_1" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
android:layout_marginTop="40dp" /> | |||||
<TextView | |||||
android:id="@+id/tv_history_title" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textColor="@color/gray_2" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintBottom_toTopOf="@+id/v_line" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
android:text="历史搜索记录" | |||||
android:layout_marginStart="@dimen/global_spacing" /> | |||||
<ImageView | |||||
android:id="@+id/iv_delete" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="0dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintBottom_toTopOf="@+id/v_line" | |||||
android:paddingEnd="8dp" | |||||
android:paddingStart="8dp" | |||||
android:layout_marginEnd="4dp" | |||||
android:src="@drawable/ic_rubbish" /> | |||||
<androidx.recyclerview.widget.RecyclerView | |||||
android:id="@+id/rv" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
app:layout_constraintTop_toBottomOf="@+id/v_line" /> | |||||
<TextView | |||||
android:id="@+id/tv_see_more" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="40dp" | |||||
android:textSize="@dimen/smallerSize" | |||||
android:textColor="@color/gray_2" | |||||
app:layout_constraintTop_toBottomOf="@+id/rv" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
android:text="查看更多" | |||||
android:drawableEnd="@drawable/ic_down" | |||||
android:drawableTint="@color/gray_2" | |||||
android:gravity="center_vertical" | |||||
android:drawablePadding="4dp" /> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</layout> |
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/title_bar" | app:layout_constraintTop_toBottomOf="@+id/title_bar" | ||||
android:visibility="gone" | |||||
tools:visibility="visible" | tools:visibility="visible" | ||||
> | > | ||||
app:layout_constraintStart_toStartOf="parent" | app:layout_constraintStart_toStartOf="parent" | ||||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | app:layout_constraintTop_toBottomOf="@+id/title_bar" | ||||
app:layout_constraintVertical_bias="0" | app:layout_constraintVertical_bias="0" | ||||
android:visibility="gone" | |||||
tools:visibility="gone"> | tools:visibility="gone"> | ||||
<androidx.constraintlayout.widget.ConstraintLayout | <androidx.constraintlayout.widget.ConstraintLayout |
android:layout_height="@dimen/title_bar_height" | android:layout_height="@dimen/title_bar_height" | ||||
app:titleTextValue="@string/test_vocabulary"/> | app:titleTextValue="@string/test_vocabulary"/> | ||||
<View | |||||
android:layout_width="match_parent" | |||||
android:layout_height="@dimen/line_height" | |||||
android:background="@color/gray_1"/> | |||||
<TextView | <TextView | ||||
android:layout_width="wrap_content" | android:layout_width="wrap_content" |
<?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> | |||||
<LinearLayout | |||||
android:layout_width="300dp" | |||||
android:layout_height="wrap_content" | |||||
android:orientation="vertical"> | |||||
<androidx.constraintlayout.widget.ConstraintLayout | |||||
android:id="@+id/layout_vocabulary" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:background="@drawable/shape_rounder_12_white"> | |||||
<TextView | |||||
android:id="@+id/tv_vocabulary" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="32dp" | |||||
tools:text="学考乐词汇量测试:小学" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
android:textStyle="bold"/> | |||||
<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="12dp" | |||||
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%(高中)"/> | |||||
<TextView | |||||
android:id="@+id/tv_vocabulary_little" | |||||
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" | |||||
android:drawableTop="@mipmap/cry" | |||||
android:drawablePadding="12dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@id/tv_vocabulary_test_time" | |||||
android:visibility="gone" | |||||
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" | |||||
android:visibility="gone" | |||||
tools:visibility="visible"/> | |||||
<androidx.constraintlayout.widget.Barrier | |||||
android:id="@+id/barrier" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
app:barrierDirection="bottom" | |||||
app:barrierMargin="@dimen/smallerSize" | |||||
app:constraint_referenced_ids="tv_vocabulary_cover_rate_stage,tv_vocabulary_little"/> | |||||
<View | |||||
android:id="@+id/bottom_top_line" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="1dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
android:background="@color/gray_3" | |||||
app:layout_constraintTop_toBottomOf="@+id/barrier" | |||||
android:layout_marginTop="@dimen/global_spacing"/> | |||||
<TextView | |||||
android:id="@+id/tv_right" | |||||
android:layout_width="0dp" | |||||
android:layout_height="40dp" | |||||
android:gravity="center" | |||||
android:text="@string/test_again" | |||||
android:textColor="@color/theme_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/bottom_top_line" | |||||
app:layout_constraintStart_toEndOf="@id/vSplit" | |||||
/> | |||||
<View | |||||
android:id="@+id/vSplit" | |||||
android:layout_width="1dp" | |||||
android:layout_height="0dp" | |||||
app:layout_constraintEnd_toStartOf="@+id/tv_right" | |||||
app:layout_constraintStart_toEndOf="@+id/tv_left" | |||||
android:background="@color/gray_3" | |||||
app:layout_constraintTop_toTopOf="@+id/tv_right" | |||||
app:layout_constraintBottom_toBottomOf="@+id/tv_right"/> | |||||
<!--左边按钮--> | |||||
<TextView | |||||
android:id="@+id/tv_left" | |||||
android:layout_width="0dp" | |||||
android:layout_height="40dp" | |||||
android:gravity="center" | |||||
android:text="@string/done" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toStartOf="@+id/vSplit" | |||||
app:layout_constraintTop_toTopOf="@+id/vSplit" | |||||
app:layout_constraintBottom_toBottomOf="@+id/vSplit" | |||||
/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> | |||||
</LinearLayout> | |||||
</layout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
xmlns:tools="http://schemas.android.com/tools"> | |||||
<TextView | |||||
android:id="@+id/tv_word" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginTop="16dp" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:text="jaapjaapjaap" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="22dp" | |||||
android:textStyle="bold" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintHorizontal_bias="0.0" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<TextView | |||||
android:id="@+id/tv_phonetic" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:gravity="center_vertical" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallerSize" | |||||
app:layout_constraintEnd_toEndOf="@+id/tv_word" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_word" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_word" | |||||
tools:text="[gud:bai] " | |||||
app:layout_constraintHorizontal_bias="0" | |||||
android:layout_marginTop="8dp"/> | |||||
<androidx.recyclerview.widget.RecyclerView | |||||
android:id="@+id/recyclerView" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_phonetic" | |||||
/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
xmlns:tools="http://schemas.android.com/tools" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
android:orientation="horizontal" | |||||
android:gravity="center_vertical"> | |||||
<TextView | |||||
android:id="@+id/tv_word" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:singleLine="true" | |||||
tools:text="introduction" | |||||
android:textSize="@dimen/normalSize" | |||||
android:textColor="@color/main_text_color" | |||||
android:layout_marginTop="8dp" | |||||
app:layout_constraintTop_toTopOf="parent" | |||||
app:layout_constraintStart_toEndOf="@+id/iv_horuns" | |||||
android:gravity="center_vertical" | |||||
/> | |||||
<ImageView | |||||
android:id="@+id/iv_horuns" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
tools:src="@drawable/ic_horuns" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginEnd="8dp" | |||||
app:layout_constraintTop_toTopOf="@+id/tv_word" | |||||
app:layout_constraintBottom_toBottomOf="@+id/tv_word" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
android:paddingRight="4dp"/> | |||||
<TextView | |||||
android:id="@+id/tv_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:textSize="@dimen/smallerSize" | |||||
android:textColor="@color/gray_2" | |||||
tools:text="简介" | |||||
app:layout_constrainedWidth="true" | |||||
app:layout_constraintHorizontal_bias="0" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_word" | |||||
app:layout_constraintBottom_toBottomOf="parent" | |||||
android:layout_marginBottom="8dp" | |||||
android:layout_marginTop="4dp"/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||||
xmlns:tools="http://schemas.android.com/tools"> | |||||
<TextView | |||||
android:id="@+id/tv_word" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginTop="16dp" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:text="jaapjaapjaap" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="22dp" | |||||
android:textStyle="bold" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintHorizontal_bias="0.0" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintTop_toTopOf="parent" /> | |||||
<com.suliang.common.widget.TagLinearLayout | |||||
android:id="@+id/layout_phonetic" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
app:item_horizontal_space="16dp" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_word" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_word" | |||||
android:layout_marginTop="8dp" | |||||
android:layout_marginEnd="@dimen/global_spacing"> | |||||
<TextView | |||||
android:id="@+id/tv_phonetic_uk" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:drawableEnd="@drawable/ic_horuns" | |||||
android:gravity="center" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallerSize" | |||||
tools:text="英 [gud:bai] " /> | |||||
<TextView | |||||
android:id="@+id/tv_phonetic_us" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:drawableEnd="@drawable/ic_horuns" | |||||
android:gravity="center" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallerSize" | |||||
tools:text="美 [gud:bai] " /> | |||||
</com.suliang.common.widget.TagLinearLayout> | |||||
<TextView | |||||
android:id="@+id/tv_explain" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="10dp" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:textColor="@color/main_text_color" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintEnd_toEndOf="parent" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_word" | |||||
app:layout_constraintTop_toBottomOf="@+id/layout_phonetic" | |||||
app:layout_constraintHorizontal_bias="0" | |||||
android:textStyle="bold" | |||||
tools:text="基本释义"/> | |||||
<TextView | |||||
android:id="@+id/tv_expand_explain" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="2dp" | |||||
android:textColor="@color/gray_2" | |||||
android:textSize="@dimen/smallSize" | |||||
app:layout_constraintEnd_toEndOf="@+id/tv_word" | |||||
app:layout_constraintStart_toStartOf="@+id/tv_word" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_explain" | |||||
tools:text="扩展释义>"/> | |||||
<include | |||||
android:id="@+id/inc_word_detail" | |||||
android:layout_width="0dp" | |||||
android:layout_height="wrap_content" | |||||
layout="@layout/inc_word_detail" | |||||
app:layout_constraintTop_toBottomOf="@+id/tv_expand_explain" | |||||
app:layout_constraintStart_toStartOf="parent" | |||||
app:layout_constraintEnd_toEndOf="parent"/> | |||||
</androidx.constraintlayout.widget.ConstraintLayout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="32dp" | |||||
xmlns:tools="http://schemas.android.com/tools" | |||||
android:orientation="horizontal" | |||||
android:gravity="center_vertical"> | |||||
<ImageView | |||||
android:id="@+id/iv" | |||||
android:layout_width="16dp" | |||||
android:layout_height="16dp" | |||||
tools:src="@drawable/ic_clock" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:layout_marginEnd="8dp"/> | |||||
<TextView | |||||
android:id="@+id/tv_word" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:singleLine="true" | |||||
tools:text="jaap" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textColor="@color/main_text_color" | |||||
/> | |||||
<TextView | |||||
android:id="@+id/tv_value" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:singleLine="true" | |||||
android:ellipsize="end" | |||||
android:layout_marginEnd="@dimen/global_spacing" | |||||
android:layout_marginStart="@dimen/global_spacing" | |||||
android:textSize="@dimen/smallSize" | |||||
android:textColor="@color/main_text_color" | |||||
tools:text="治疗"/> | |||||
</LinearLayout> |
tools:text="12:12:12" | tools:text="12:12:12" | ||||
android:textSize="@dimen/smallSize" | android:textSize="@dimen/smallSize" | ||||
android:textColor="@color/gray_2" | android:textColor="@color/gray_2" | ||||
android:layout_marginStart="24dp" /> | |||||
android:layout_marginStart="12dp" /> | |||||
<TextView | <TextView | ||||
android:id="@+id/tv_score" | android:id="@+id/tv_score" |
<androidx.constraintlayout.widget.ConstraintLayout | <androidx.constraintlayout.widget.ConstraintLayout | ||||
android:layout_width="match_parent" | android:layout_width="match_parent" | ||||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||||
android:background="@drawable/shape_rounder_12_white" | |||||
android:background="@drawable/shape_rounder_8_stroke_gray1" | |||||
android:padding="@dimen/global_spacing" | android:padding="@dimen/global_spacing" | ||||
android:layout_marginBottom="12dp" | android:layout_marginBottom="12dp" | ||||
android:layout_marginStart="@dimen/global_spacing" | android:layout_marginStart="@dimen/global_spacing" |
<string name="vocabulary_level">测试等级:</string> | <string name="vocabulary_level">测试等级:</string> | ||||
<string name="vocabulary">词汇量</string> | <string name="vocabulary">词汇量</string> | ||||
<string name="test_vocabulary">测词汇量</string> | <string name="test_vocabulary">测词汇量</string> | ||||
<string name="done">完成</string> | |||||
<string name="xkl_dictionary">学考乐英汉双向词典</string> | |||||
<string name="dialog_delete_history">你确定要删除历史记录吗?</string> | |||||
<string name="delete">删除</string> | |||||
</resources> | </resources> |
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:width="16dp" | |||||
android:height="16dp" | |||||
android:viewportWidth="16" | |||||
android:viewportHeight="16"> | |||||
<path | |||||
android:pathData="M0,0h16v16h-16z" | |||||
android:strokeAlpha="0" | |||||
android:strokeWidth="1" | |||||
android:fillColor="#000000" | |||||
android:fillType="nonZero" | |||||
android:strokeColor="#00000000" | |||||
android:fillAlpha="0"/> | |||||
<path | |||||
android:pathData="M8,1.6C11.5346,1.6 14.4,4.4654 14.4,8C14.4,11.5346 11.5346,14.4 8,14.4C4.4654,14.4 1.6,11.5346 1.6,8C1.6,4.4654 4.4654,1.6 8,1.6ZM8,2.6667C5.0545,2.6667 2.6667,5.0545 2.6667,8C2.6667,10.9455 5.0545,13.3333 8,13.3333C10.9455,13.3333 13.3333,10.9455 13.3333,8C13.3333,5.0545 10.9455,2.6667 8,2.6667ZM8,4.2667C8.2735,4.2667 8.4989,4.4726 8.5297,4.7378L8.5333,4.8L8.5333,7.7141L10.8715,9.2699C11.0992,9.4214 11.1728,9.7177 11.0515,9.9556L11.0201,10.0094C10.8686,10.2371 10.5723,10.3107 10.3344,10.1895L10.2806,10.158L7.7046,8.444C7.5745,8.3575 7.4899,8.2191 7.4708,8.0663L7.4667,8L7.4667,4.8C7.4667,4.5054 7.7054,4.2667 8,4.2667Z" | |||||
android:strokeWidth="1" | |||||
android:fillColor="#8A8A99" | |||||
android:fillType="evenOdd" | |||||
android:strokeColor="#00000000"/> | |||||
</vector> |
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:width="16dp" | |||||
android:height="16dp" | |||||
android:viewportWidth="16" | |||||
android:viewportHeight="16"> | |||||
<path | |||||
android:pathData="M9.9556,1.6C10.2055,1.6 10.422,1.7736 10.4762,2.0176L10.4762,2.0176L10.774,3.36L13.8667,3.36C14.1612,3.36 14.4,3.5988 14.4,3.8933C14.4,4.1668 14.1941,4.3923 13.9289,4.4231L13.8667,4.4267L12.64,4.426L12.64,12.8C12.64,13.6346 12.001,14.3199 11.1856,14.3935L11.04,14.4L4.96,14.4C4.0763,14.4 3.36,13.6837 3.36,12.8L3.36,12.8L3.359,4.426L2.1333,4.4267C1.8388,4.4267 1.6,4.1879 1.6,3.8933C1.6,3.6198 1.8059,3.3944 2.0711,3.3636L2.1333,3.36L5.225,3.36L5.5238,2.0176C5.5713,1.8041 5.7429,1.6445 5.9525,1.6079L6.0444,1.6ZM11.5733,4.4267L4.4267,4.4267L4.4267,12.8C4.4267,13.0735 4.6326,13.2989 4.8978,13.3297L4.8978,13.3297L4.96,13.3333L11.04,13.3333C11.3346,13.3333 11.5733,13.0946 11.5733,12.8L11.5733,12.8L11.5733,4.4267ZM6.8267,6.2933C7.1002,6.2933 7.3256,6.4992 7.3564,6.7645L7.36,6.8267L7.36,10.9333C7.36,11.2279 7.1212,11.4667 6.8267,11.4667C6.5532,11.4667 6.3277,11.2608 6.2969,10.9955L6.2933,10.9333L6.2933,6.8267C6.2933,6.5321 6.5321,6.2933 6.8267,6.2933ZM9.1733,6.2933C9.4468,6.2933 9.6723,6.4992 9.7031,6.7645L9.7067,6.8267L9.7067,10.9333C9.7067,11.2279 9.4679,11.4667 9.1733,11.4667C8.8998,11.4667 8.6744,11.2608 8.6436,10.9955L8.64,10.9333L8.64,6.8267C8.64,6.5321 8.8788,6.2933 9.1733,6.2933ZM9.5275,2.6667L6.472,2.6667L6.3179,3.36L9.6816,3.36L9.5275,2.6667Z" | |||||
android:strokeWidth="1" | |||||
android:fillColor="#9A9EB3" | |||||
android:fillType="evenOdd" | |||||
android:strokeColor="#00000000"/> | |||||
</vector> |
package com.suliang.common.base | package com.suliang.common.base | ||||
import android.R.attr | |||||
import android.graphics.Color | import android.graphics.Color | ||||
import android.graphics.drawable.ColorDrawable | |||||
import android.os.Bundle | import android.os.Bundle | ||||
import android.view.Gravity | |||||
import android.view.LayoutInflater | import android.view.LayoutInflater | ||||
import android.view.View | import android.view.View | ||||
import android.view.ViewGroup | import android.view.ViewGroup | ||||
import androidx.fragment.app.DialogFragment | import androidx.fragment.app.DialogFragment | ||||
import androidx.fragment.app.FragmentManager | |||||
import androidx.viewbinding.ViewBinding | import androidx.viewbinding.ViewBinding | ||||
import com.suliang.common.extension.initBinding | import com.suliang.common.extension.initBinding | ||||
import android.graphics.drawable.ColorDrawable | |||||
import android.util.DisplayMetrics | |||||
import androidx.fragment.app.FragmentManager | |||||
import androidx.fragment.app.FragmentTransaction | |||||
import android.R.attr.tag | |||||
import androidx.fragment.app.Fragment | |||||
import java.lang.IllegalStateException | |||||
import com.suliang.common.util.os.ScreenUtil | |||||
/** | /** | ||||
override fun onCreateView( | override fun onCreateView( | ||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? | inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? | ||||
): View? { | ): View? { | ||||
//设置透明背景,避免DecorView的自带padding | |||||
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) | |||||
_binding = initBinding(inflater, container) | _binding = initBinding(inflater, container) | ||||
return binding.root | return binding.root | ||||
} | } | ||||
//设置背景透明 | //设置背景透明 | ||||
dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) | dialog!!.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) | ||||
} | } | ||||
resizeDialog() | |||||
} | |||||
protected open fun resizeDialog() { | |||||
//设置dialog位置 | |||||
dialog?.window?.let { | |||||
it.attributes.run { | |||||
this.y = ScreenUtil.getScreenHeight() / 5 | |||||
this.width = ScreenUtil.dp2px(300f).toInt() | |||||
it.attributes = this | |||||
} | |||||
it.setGravity(Gravity.TOP) | |||||
} | |||||
} | } | ||||
abstract fun initFragment() | abstract fun initFragment() |