@@ -68,6 +68,7 @@ | |||
<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_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_learn_base.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_learn_creading.xml" value="0.4304093567251462" /> | |||
@@ -95,6 +96,7 @@ | |||
<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_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_main.xml" value="0.4979166666666667" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_course_pack.xml" value="0.34427083333333336" /> | |||
@@ -127,6 +129,12 @@ | |||
<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_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_historical_route.xml" value="0.4859375" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo.xml" value="0.67" /> | |||
@@ -136,7 +144,7 @@ | |||
<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_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_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" /> |
@@ -12,6 +12,9 @@ | |||
android:supportsRtl="true" | |||
android:theme="@style/Theme.XklLocal" | |||
tools:ignore="LockedOrientationActivity"> | |||
<activity | |||
android:name=".module.m_service_center.DictionaryActivity" | |||
android:exported="true" /> | |||
<activity | |||
android:name=".module.m_service_center.TestVocabularyActivity" | |||
android:exported="true" /> |
@@ -33,7 +33,7 @@ class AdapterTestScore(vm : TestScoreViewModel) : BaseRVAdapterVM<Exam,TestScore | |||
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") |
@@ -0,0 +1,83 @@ | |||
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 -> { | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
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 | |||
} |
@@ -0,0 +1,24 @@ | |||
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 | |||
} |
@@ -5,4 +5,4 @@ package com.xkl.cdl.data.bean | |||
* create 2022/7/13 10:48 | |||
* 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) |
@@ -1,5 +1,6 @@ | |||
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.Lesson | |||
@@ -16,6 +17,7 @@ import com.xkl.cdl.data.bean.course.Lesson | |||
* | |||
* 课时学后测: coursePackType, courseType, testData ,lesson. | |||
* | |||
* 词汇量测试: testData, vocabularyItem | |||
*/ | |||
data class ExamData( | |||
val subjectId : Int, //项目类型 | |||
@@ -36,5 +38,8 @@ data class ExamData( | |||
// 课程/课时学前测试正确错误列表 key=> {chapter_id}_{lesson_id}_{entity_id} value=>正确 true;错误 false | |||
var mExamWRMap : HashMap<String, Boolean>? = null | |||
//测词汇量item | |||
var vocabularyItem : VocabularyItem? = null | |||
} |
@@ -18,6 +18,7 @@ abstract class AppDatabase : RoomDatabase() { | |||
abstract fun examDao() : ExamDao | |||
abstract fun examItemDao(): ExamItemDao | |||
abstract fun examMiddleDao(): ExamMiddleDao | |||
abstract fun dictionaryDao(): DictionaryDao | |||
companion object{ | |||
private var DATABASE_NAME :String = "${FileUtil.getSaveDirPath("db")}${File.separator}app.db" |
@@ -0,0 +1,22 @@ | |||
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) | |||
} |
@@ -0,0 +1,224 @@ | |||
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) | |||
} | |||
} | |||
} |
@@ -1,14 +1,18 @@ | |||
package com.xkl.cdl.data.manager.db | |||
import android.widget.Toast | |||
import androidx.core.database.getBlobOrNull | |||
import appApi.AppApi | |||
import com.suliang.common.AppConfig | |||
import com.suliang.common.util.AppGlobals | |||
import com.suliang.common.util.file.FileUtil | |||
import com.suliang.common.util.thread.AppExecutors | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.bean.VocabularyItem | |||
import com.xkl.cdl.data.bean.course.ExamBean | |||
import com.xkl.cdl.data.manager.FilePathManager | |||
import net.sqlcipher.database.SQLiteDatabase | |||
import java.io.File | |||
/** | |||
* author suliang | |||
@@ -17,12 +21,15 @@ import net.sqlcipher.database.SQLiteDatabase | |||
*/ | |||
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() { | |||
synchronized(VocabularyManager) { | |||
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) { | |||
AppExecutors.mainThread.run { | |||
@@ -37,12 +44,75 @@ object VocabularyManager { | |||
* @param level VocabularyItem | |||
* @return List<ExamBean> | |||
*/ | |||
fun queryVocabularyTestData(level : VocabularyItem) : List<ExamBean>{ | |||
fun queryVocabularyTestData(level : VocabularyItem) : List<ExamBean> { | |||
open() | |||
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 | |||
} | |||
} |
@@ -8,6 +8,7 @@ import com.suliang.common.util.file.FileUtil | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.manager.db.DBCourseManager | |||
import com.xkl.cdl.data.manager.db.DbControlBase | |||
import com.xkl.cdl.data.manager.db.VocabularyManager | |||
import io.reactivex.rxjava3.core.Observable | |||
import java.io.File | |||
import java.util.* | |||
@@ -94,4 +95,46 @@ object AudioCache { | |||
} | |||
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 | |||
} | |||
} | |||
} |
@@ -95,5 +95,5 @@ class CommonDialog private constructor() : BaseDialogFragment<DialogCommonBindin | |||
} | |||
override fun resizeDialog(){} | |||
} |
@@ -71,6 +71,8 @@ class LearnDialog private constructor() : BaseDialogFragment<DialogLessonLearnBi | |||
//备忘本测试 课程测试 | |||
AppConstants.TEST_TYPE_SERVICE_CENTER, | |||
AppConstants.TEST_TYPE_MEMO -> initMemoTestOver() | |||
//词汇量测试结束 | |||
} | |||
//学习结束弹窗 | |||
AppConstants.DIALOG_TYPE_LEARNING_OVER -> initLessonLearningOver(false) | |||
@@ -87,18 +89,6 @@ class LearnDialog private constructor() : BaseDialogFragment<DialogLessonLearnBi | |||
} | |||
} | |||
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() { | |||
//插画 |
@@ -0,0 +1,97 @@ | |||
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) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -27,6 +27,7 @@ import com.xkl.cdl.adapter.itemdecoration.SpellItemDecoration | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.DataTransferHolder | |||
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.event.LearnEventData | |||
import com.xkl.cdl.data.manager.CourseManager | |||
@@ -36,6 +37,7 @@ import com.xkl.cdl.databinding.* | |||
import com.xkl.cdl.dialog.CommonDialog | |||
import com.xkl.cdl.dialog.CommonDialogBean | |||
import com.xkl.cdl.dialog.LearnDialog | |||
import com.xkl.cdl.dialog.VocabularyDialog | |||
import com.xkl.cdl.module.m_service_center.TestDetailActivity | |||
/** | |||
@@ -137,6 +139,11 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
/** 新单词来了的发音事件 */ | |||
private fun initNewWordRead(it : ExamBean) { | |||
//词汇量测试,新单词发音 | |||
if (vm.intentData.examType == AppConstants.TEST_TYPE_NORMAL){ | |||
wordChooseBinding.ivVoice.performClick() | |||
return | |||
} | |||
when (vm.intentData.courseType) { | |||
//拼写初始不发音,作文不发音, 音标课程测试不发音 | |||
AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_ENGLISH_SPELL, AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | |||
@@ -147,7 +154,6 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | |||
wordChooseBinding.ivVoice.performClick() | |||
} | |||
} | |||
} | |||
@@ -188,7 +194,11 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
private fun initStatistics() { | |||
binding.incStatistics.run { | |||
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) { | |||
tvTestTime.text = DateUtil.formatGMT(it, DateUtil.FORMAT_2) | |||
@@ -200,6 +210,7 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
vm.errorLiveData.observe(this@LearnExamActivity) { | |||
tvErrorNumber.text = "错误: $it" | |||
} | |||
} | |||
} | |||
@@ -497,7 +508,7 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
} | |||
} | |||
} | |||
} ?: let { //取消事件 | |||
} ?: let { //取消选项答案选择事件,设置选项发音事件 | |||
vm.optionList.forEachIndexed { index, optionItemBinding -> | |||
optionItemBinding.root.click(null) | |||
optionItemBinding.tvOption.click { optionItemBinding.ivOption.performClick() } | |||
@@ -523,12 +534,13 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
//口语的音频,有问题,与选项 直接获取其tag获取音频 | |||
currentPlayView?.cancelAnimation() | |||
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) | |||
} | |||
} | |||
} | |||
@@ -593,14 +605,37 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
/** 测试完成 : 弹窗显示 */ | |||
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 { | |||
examType = vm.intentData.examType | |||
score = vm.scoreValue | |||
correctNumber = vm.correctLiveData.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 | |||
} | |||
} | |||
@@ -717,8 +752,7 @@ class LearnExamActivity : BaseActivityVM<ActivityLearnExamBinding, LearnExamView | |||
} | |||
} | |||
//备忘本测试 | |||
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 -> { | |||
dialog.dismissAllowingStateLoss() |
@@ -380,8 +380,10 @@ class LearnExamViewModel : LearnBaseViewModel() { | |||
createErrorRecord() | |||
} | |||
} | |||
//添加到记录集合 | |||
mExamRecordList.add(currentExamRecord!!.build()) | |||
//添加到记录集合 词汇量测试不添加记录 | |||
if (intentData.examType != AppConstants.TEST_TYPE_NORMAL) { | |||
mExamRecordList.add(currentExamRecord!!.build()) | |||
} | |||
currentChooseResultLiveData.value = chooseResult | |||
} | |||
@@ -484,8 +486,8 @@ class LearnExamViewModel : LearnBaseViewModel() { | |||
//分数 与 覆盖率 只有测试成功才进行计算 | |||
if (isVocablularySuccess) { | |||
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() //测试类型的覆盖率 | |||
} | |||
} | |||
@@ -580,16 +582,11 @@ class LearnExamViewModel : LearnBaseViewModel() { | |||
stage = "小学" | |||
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) //测试试卷 | |||
//时间 学习中心的测试需要添加为学习时间 |
@@ -0,0 +1,165 @@ | |||
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 | |||
} | |||
} |
@@ -0,0 +1,111 @@ | |||
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) | |||
} | |||
} |
@@ -13,13 +13,14 @@ import com.suliang.common.base.adapter.BaseRVAdapter | |||
import com.suliang.common.base.fragment.BaseFragmentVM | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.adapter.DictionaryAdapter | |||
import com.xkl.cdl.databinding.FragmentMyBinding | |||
import com.xkl.cdl.databinding.ItemServiceCenterItemBinding | |||
import com.xkl.cdl.databinding.ServiceCenterFragmentBinding | |||
import com.xkl.cdl.module.main.MainActivityViewModel | |||
class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, MainActivityViewModel>() { | |||
class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, MainActivityViewModel>() { | |||
companion object { | |||
@JvmStatic | |||
fun newInstance() = ServiceCenterFragment() | |||
@@ -27,16 +28,17 @@ class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, Main | |||
override fun initFragment() { | |||
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 { | |||
layoutManager = GridLayoutManager(requireContext(),2,GridLayoutManager.VERTICAL,false) | |||
layoutManager = GridLayoutManager(requireContext(), 2, GridLayoutManager.VERTICAL, false) | |||
setHasFixedSize(true) | |||
adapter = object : BaseRVAdapter<Item>() { | |||
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) { | |||
val item = getItem(position) | |||
(holder.binding as ItemServiceCenterItemBinding).apply { | |||
@@ -55,23 +57,25 @@ class ServiceCenterFragment : BaseFragmentVM<ServiceCenterFragmentBinding, Main | |||
} | |||
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 initViewModel(): MainActivityViewModel { | |||
override fun initViewModel() : MainActivityViewModel { | |||
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) | |||
} |
@@ -36,7 +36,7 @@ class TestDetailActivity : BaseActivityVM<ActivityTestDetailBinding,TestDetailVi | |||
if (vm.learnExam.score > 0){ | |||
groupVocabularyLittle.visibility = View.GONE | |||
groupVocabularyNormal.visibility = View.VISIBLE | |||
tvVocabularyCount.text = "${vm.learnExam.score}" | |||
tvVocabularyCount.text = "${vm.learnExam.score.toInt()}" | |||
ratingBar.setStar(vm.learnExam.score/20) | |||
tvVocabularyCoverRateStage.setHtml("覆盖率<font color=\'#F7874F\'>${vm.learnExam.coverRate}%</font>\t\t(${vm.learnExam.stage})") | |||
}else{ |
@@ -4,14 +4,20 @@ import android.os.Bundle | |||
import android.view.ViewGroup | |||
import androidx.lifecycle.ViewModelProvider | |||
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.adapter.BaseAdapterViewHolder | |||
import com.suliang.common.base.adapter.BaseRVAdapter | |||
import com.suliang.common.extension.click | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.AppConstants | |||
import com.xkl.cdl.data.DataTransferHolder | |||
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.ItemVocabularyLevelBinding | |||
import com.xkl.cdl.module.learn.LearnExamActivity | |||
class TestVocabularyActivity : BaseActivityVM<ActivityTestVocabularyBinding, TestVocabularyViewModle>() { | |||
@@ -31,13 +37,13 @@ class TestVocabularyActivity : BaseActivityVM<ActivityTestVocabularyBinding, Tes | |||
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_vocabulary_level)) | |||
} | |||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||
getItem(position).let { | |||
getItem(position).let { item -> | |||
(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) | |||
} | |||
} | |||
} | |||
@@ -47,8 +53,25 @@ class TestVocabularyActivity : BaseActivityVM<ActivityTestVocabularyBinding, Tes | |||
} | |||
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) | |||
} | |||
} | |||
} |
@@ -7,6 +7,7 @@ import com.xkl.cdl.R | |||
import com.xkl.cdl.data.bean.VocabularyItem | |||
import com.xkl.cdl.data.bean.course.ExamBean | |||
import com.xkl.cdl.data.manager.db.DBCourseManager | |||
import com.xkl.cdl.data.manager.db.VocabularyManager | |||
import io.reactivex.rxjava3.core.Observable | |||
/** | |||
@@ -15,16 +16,25 @@ import io.reactivex.rxjava3.core.Observable | |||
* Describe: | |||
*/ | |||
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( | |||
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) ) | |||
/** | |||
* 查询测试数据 | |||
@@ -33,7 +43,7 @@ class TestVocabularyViewModle : BaseViewModel() { | |||
fun queryVocabularyTestData(item : VocabularyItem) : MutableLiveData<List<ExamBean>> { | |||
val result = MutableLiveData<List<ExamBean>>() | |||
Observable.create<List<ExamBean>> { | |||
it.onNext(DBCourseManager.queryLearnTest(dbControlBase, testType, lesson)) | |||
it.onNext(VocabularyManager.queryVocabularyTestData(item)) | |||
it.onComplete() | |||
}.compose(diskIo2Main()).subscribe({ | |||
result.value = it |
@@ -55,11 +55,11 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() { | |||
//复制词典 和 词汇量测试 | |||
val dictionary = FilePathManager.getDictionaryDbPath() | |||
if (!dictionary.exists()) { | |||
val copyAssetResult = FileUtil.copyAsset("dictionary.db", dictionary) | |||
FileUtil.copyAsset("dictionary.db", dictionary) | |||
} | |||
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绑定的课程数据, |
@@ -0,0 +1,138 @@ | |||
<?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> |
@@ -40,6 +40,7 @@ | |||
app:layout_constraintEnd_toEndOf="parent" | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | |||
android:visibility="gone" | |||
tools:visibility="visible" | |||
> | |||
@@ -213,6 +214,7 @@ | |||
app:layout_constraintStart_toStartOf="parent" | |||
app:layout_constraintTop_toBottomOf="@+id/title_bar" | |||
app:layout_constraintVertical_bias="0" | |||
android:visibility="gone" | |||
tools:visibility="gone"> | |||
<androidx.constraintlayout.widget.ConstraintLayout |
@@ -20,10 +20,6 @@ | |||
android:layout_height="@dimen/title_bar_height" | |||
app:titleTextValue="@string/test_vocabulary"/> | |||
<View | |||
android:layout_width="match_parent" | |||
android:layout_height="@dimen/line_height" | |||
android:background="@color/gray_1"/> | |||
<TextView | |||
android:layout_width="wrap_content" |
@@ -0,0 +1,198 @@ | |||
<?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> |
@@ -0,0 +1,47 @@ | |||
<?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> |
@@ -0,0 +1,55 @@ | |||
<?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> |
@@ -0,0 +1,94 @@ | |||
<?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> |
@@ -0,0 +1,40 @@ | |||
<?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> |
@@ -69,7 +69,7 @@ | |||
tools:text="12:12:12" | |||
android:textSize="@dimen/smallSize" | |||
android:textColor="@color/gray_2" | |||
android:layout_marginStart="24dp" /> | |||
android:layout_marginStart="12dp" /> | |||
<TextView | |||
android:id="@+id/tv_score" |
@@ -10,7 +10,7 @@ | |||
<androidx.constraintlayout.widget.ConstraintLayout | |||
android:layout_width="match_parent" | |||
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:layout_marginBottom="12dp" | |||
android:layout_marginStart="@dimen/global_spacing" |
@@ -99,5 +99,9 @@ | |||
<string name="vocabulary_level">测试等级:</string> | |||
<string name="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> |
@@ -0,0 +1,20 @@ | |||
<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> |
@@ -0,0 +1,12 @@ | |||
<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> |
@@ -1,22 +1,17 @@ | |||
package com.suliang.common.base | |||
import android.R.attr | |||
import android.graphics.Color | |||
import android.graphics.drawable.ColorDrawable | |||
import android.os.Bundle | |||
import android.view.Gravity | |||
import android.view.LayoutInflater | |||
import android.view.View | |||
import android.view.ViewGroup | |||
import androidx.fragment.app.DialogFragment | |||
import androidx.fragment.app.FragmentManager | |||
import androidx.viewbinding.ViewBinding | |||
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 | |||
/** | |||
@@ -33,6 +28,8 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment() { | |||
override fun onCreateView( | |||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? | |||
): View? { | |||
//设置透明背景,避免DecorView的自带padding | |||
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) | |||
_binding = initBinding(inflater, container) | |||
return binding.root | |||
} | |||
@@ -52,6 +49,19 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment() { | |||
//设置背景透明 | |||
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() |