| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" /> | ||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_auto_play_select.xml" value="0.4979166666666667" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_auto_play_select.xml" value="0.4979166666666667" /> | ||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_course_more.xml" value="0.33" /> | <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_course_more.xml" value="0.33" /> | ||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_course_pack_introducation.xml" value="0.1956521739130435" /> | |||||
| <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/dialog_bottom_course_pack_introduction.xml" value="0.21203703703703702" /> | |||||
| <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" /> |
| 如何实现防快速点击 aspectJ | 如何实现防快速点击 aspectJ | ||||
| SpellTipsLinearLayout onDraw为什么不调用?为什么设置背景后就有效过了? | SpellTipsLinearLayout onDraw为什么不调用?为什么设置背景后就有效过了? | ||||
| 实现dialog动画:从底部进入和从底部滑出 | |||||
| DialogFragment原理 | |||||
| BottomSheetDialog 固定高度和原理 | |||||
| BottomSheetDialog中使用TextView滑动的冲突? | |||||
| Behavior |
| * @param refrence String? 参考 | * @param refrence String? 参考 | ||||
| */ | */ | ||||
| @SuppressLint("SetTextI18n") | @SuppressLint("SetTextI18n") | ||||
| fun IncWordDetailBinding.initValue(phrase : String?, example : String?, refrence : String?){ | |||||
| phrase?.let { | |||||
| tvPhraseFlag.visibility = View.VISIBLE | |||||
| layoutPhrase.run { | |||||
| visibility = View.VISIBLE | |||||
| removeAllViews() | |||||
| val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) | |||||
| it.split("\n").forEach { | |||||
| val child = TextView(context).apply { | |||||
| layoutParams = params | |||||
| text = it | |||||
| setTextColor(ContextCompat.getColor(context, R.color.main_text_color)) | |||||
| setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14f) | |||||
| fun IncWordDetailBinding.initValue(phrase : String?, example : String?, refrence : String?) { | |||||
| when{ | |||||
| phrase.isNullOrEmpty() -> { | |||||
| tvPhraseFlag.visibility = View.GONE | |||||
| layoutPhrase.visibility = View.GONE | |||||
| } | |||||
| else -> phrase.let { | |||||
| tvPhraseFlag.visibility = View.VISIBLE | |||||
| layoutPhrase.run { | |||||
| visibility = View.VISIBLE | |||||
| removeAllViews() | |||||
| val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, | |||||
| LinearLayout.LayoutParams.WRAP_CONTENT) | |||||
| it.split("\n").forEach { | |||||
| val child = TextView(context).apply { | |||||
| layoutParams = params | |||||
| text = it | |||||
| setTextColor(ContextCompat.getColor(context, R.color.main_text_color)) | |||||
| setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14f) | |||||
| } | |||||
| addView(child) | |||||
| } | } | ||||
| addView(child) | |||||
| } | } | ||||
| } | } | ||||
| }?:let { | |||||
| tvPhraseFlag.visibility = View.GONE | |||||
| layoutPhrase.visibility = View.GONE | |||||
| } | } | ||||
| example?.let { | |||||
| tvExampleFlag.visibility = View.VISIBLE | |||||
| tvExample.visibility = View.VISIBLE | |||||
| tvExample.text = "▪ ${it.replace("\n", "\n▪ ")}" | |||||
| }?:let { | |||||
| tvExampleFlag.visibility = View.GONE | |||||
| tvExample.visibility = View.GONE | |||||
| when{ | |||||
| example.isNullOrEmpty() -> { | |||||
| tvExampleFlag.visibility = View.GONE | |||||
| tvExample.visibility = View.GONE | |||||
| } | |||||
| else -> example.let { | |||||
| tvExampleFlag.visibility = View.VISIBLE | |||||
| tvExample.visibility = View.VISIBLE | |||||
| tvExample.text = "▪ ${it.replace("\n", "\n▪ ")}" | |||||
| } | |||||
| } | } | ||||
| refrence?.let { | |||||
| tvReferenceFlag.visibility = View.VISIBLE | |||||
| tvReference.visibility = View.VISIBLE | |||||
| tvReference.text = refrence | |||||
| }?:let { | |||||
| tvReferenceFlag.visibility = View.GONE | |||||
| tvReference.visibility = View.GONE | |||||
| when{ | |||||
| refrence.isNullOrEmpty() -> { | |||||
| tvReferenceFlag.visibility = View.GONE | |||||
| tvReference.visibility = View.GONE | |||||
| } | |||||
| else -> example.let { | |||||
| tvReferenceFlag.visibility = View.VISIBLE | |||||
| tvReference.visibility = View.VISIBLE | |||||
| tvReference.text = refrence | |||||
| } | |||||
| } | } | ||||
| } | } |
| mDataBase?.rawQuery(sql, null)?.run { | mDataBase?.rawQuery(sql, null)?.run { | ||||
| when (base.courseType) { | when (base.courseType) { | ||||
| AppConstants.COURSE_TYPE_ENGLISH_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_VOICE, | AppConstants.COURSE_TYPE_ENGLISH_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_VOICE, | ||||
| AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_CHINESE_LITERACY, | |||||
| AppConstants.COURSE_TYPE_CHINESE_PINYIN, | |||||
| -> { | |||||
| while (moveToNext()) { | |||||
| AppConstants.COURSE_TYPE_CHINESE_LITERACY, | |||||
| AppConstants.COURSE_TYPE_CHINESE_PINYIN -> while (moveToNext()) { | |||||
| result.add(ExamBean().apply { | result.add(ExamBean().apply { | ||||
| id = getLong(0) | id = getLong(0) | ||||
| word_id = getLong(1) | word_id = getLong(1) | ||||
| lessonId = getLong(9) | lessonId = getLong(9) | ||||
| }) | }) | ||||
| } | } | ||||
| AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK -> while (moveToNext()) { | |||||
| result.add(ExamBean().apply { | |||||
| id = getLong(0) | |||||
| word_id = getLong(1) | |||||
| word = getString(2) | |||||
| correct = getString(3) | |||||
| error1 = getString(4) | |||||
| error2 = getString(5) | |||||
| error3 = getString(6) | |||||
| type = AppConstants.TEST_QUEST_TYPE_CHOICE // 为1 | |||||
| chapterId = getLong(11) | |||||
| lessonId = getLong(12) | |||||
| }) | |||||
| } | } | ||||
| AppConstants.COURSE_TYPE_ENGLISH_SPELL -> { | AppConstants.COURSE_TYPE_ENGLISH_SPELL -> { | ||||
| while (moveToNext()) { | while (moveToNext()) { |
| package com.xkl.cdl.dialog | |||||
| import android.annotation.SuppressLint | |||||
| import android.app.Dialog | |||||
| import android.os.Bundle | |||||
| import android.view.LayoutInflater | |||||
| import android.view.View | |||||
| import android.view.ViewGroup | |||||
| import android.view.WindowManager | |||||
| import android.widget.FrameLayout | |||||
| import androidx.coordinatorlayout.widget.CoordinatorLayout | |||||
| import androidx.databinding.DataBindingUtil | |||||
| import com.google.android.material.bottomsheet.BottomSheetBehavior | |||||
| import com.google.android.material.bottomsheet.BottomSheetDialog | |||||
| import com.google.android.material.bottomsheet.BottomSheetDialogFragment | |||||
| import com.suliang.common.AppConfig | |||||
| import com.suliang.common.extension.setHtml | |||||
| import com.suliang.common.util.os.ScreenUtil | |||||
| import com.xkl.cdl.R | |||||
| import com.xkl.cdl.databinding.DialogBottomCoursePackIntroductionBinding | |||||
| /** | |||||
| * author suliang | |||||
| * create 2022/5/13 10:51 | |||||
| * Describe: | |||||
| */ | |||||
| class CoursePackIntroductionBottomSheetDialog: BottomSheetDialogFragment() { | |||||
| companion object{ | |||||
| fun newInstance(coursePackName : String, introduction : String) : CoursePackIntroductionBottomSheetDialog { | |||||
| val args = Bundle() | |||||
| args.putString(AppConfig.INTENT_1, coursePackName) | |||||
| args.putString(AppConfig.INTENT_2,introduction) | |||||
| val fragment = CoursePackIntroductionBottomSheetDialog() | |||||
| fragment.arguments = args | |||||
| return fragment | |||||
| } | |||||
| } | |||||
| var behavior : BottomSheetBehavior<FrameLayout>? = null | |||||
| override fun onCreateDialog(savedInstanceState : Bundle?) : Dialog { | |||||
| return context?.let { | |||||
| BottomSheetDialog(it,R.style.dialog_style) | |||||
| }?: super.onCreateDialog(savedInstanceState) | |||||
| } | |||||
| @SuppressLint("ClickableViewAccessibility") | |||||
| override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? { | |||||
| val introductionBinding = DataBindingUtil.inflate<DialogBottomCoursePackIntroductionBinding>(layoutInflater, | |||||
| R.layout.dialog_bottom_course_pack_introduction, | |||||
| null, false) | |||||
| //标题 | |||||
| introductionBinding.tvTitle.text = requireArguments()[AppConfig.INTENT_1] as String | |||||
| //内容 | |||||
| (requireArguments()[AppConfig.INTENT_2] as String).let { | |||||
| if (it.isNotEmpty()) { | |||||
| introductionBinding.tvIntroduction.setHtml(it) | |||||
| } | |||||
| } | |||||
| return introductionBinding.root | |||||
| } | |||||
| override fun onStart() { | |||||
| super.onStart() | |||||
| dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) | |||||
| (dialog as BottomSheetDialog).delegate.findViewById<FrameLayout>(R.id.design_bottom_sheet)?.let { | |||||
| (it.layoutParams as CoordinatorLayout.LayoutParams).height = ScreenUtil.getScreenHeight() / 6 * 5 | |||||
| behavior = BottomSheetBehavior.from(it).apply { | |||||
| state = BottomSheetBehavior.STATE_EXPANDED | |||||
| } | |||||
| } | |||||
| } | |||||
| // override fun onCreate(savedInstanceState : Bundle?) { | |||||
| // super.onCreate(savedInstanceState) | |||||
| // setCancelable(true) | |||||
| // setCanceledOnTouchOutside(true) | |||||
| // behavior.peekHeight = ScreenUtil.getScreenHeight() / 6 * 5 | |||||
| // window?.apply { | |||||
| // setLayout(ViewGroup.LayoutParams.MATCH_PARENT,behavior.peekHeight) | |||||
| // setGravity(Gravity.BOTTOM) | |||||
| // } | |||||
| // } | |||||
| // | |||||
| // override fun onStart() { | |||||
| // super.onStart() | |||||
| // if (behavior.state == BottomSheetBehavior.STATE_HIDDEN) { | |||||
| // behavior.state = BottomSheetBehavior.STATE_EXPANDED | |||||
| // } | |||||
| // } | |||||
| } |
| /** 新单词来了的发音事件 */ | /** 新单词来了的发音事件 */ | ||||
| private fun initNewWordRead(it : ExamBean) { | private fun initNewWordRead(it : ExamBean) { | ||||
| 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_SPELL, AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | ||||
| } | } | ||||
| //英语认读,英语音标,英语口语,语文识字,语文拼音 出现即发音一次 | //英语认读,英语音标,英语口语,语文识字,语文拼音 出现即发音一次 | ||||
| AppConstants.COURSE_TYPE_ENGLISH_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_ENGLISH_SPOKEN, AppConstants.COURSE_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_CHINESE_PINYIN, | |||||
| AppConstants.COURSE_TYPE_ENGLISH_DISCERN, | |||||
| AppConstants.COURSE_TYPE_ENGLISH_SPOKEN, | |||||
| AppConstants.COURSE_TYPE_CHINESE_LITERACY, | |||||
| AppConstants.COURSE_TYPE_CHINESE_PINYIN, | |||||
| // 英语辨音 重复播放 | // 英语辨音 重复播放 | ||||
| AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | ||||
| wordChooseBinding.ivVoice.performClick() | wordChooseBinding.ivVoice.performClick() | ||||
| //发音方式 | //发音方式 | ||||
| when (vm.intentData.subjectId) { | when (vm.intentData.subjectId) { | ||||
| AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK -> voiceSwitch.visibility = View.GONE | |||||
| AppConstants.SUBJECT_CHINESE -> { | AppConstants.SUBJECT_CHINESE -> { | ||||
| vm.defaultSoundWay = AppConstants.SOUND_TYPE_CN | vm.defaultSoundWay = AppConstants.SOUND_TYPE_CN | ||||
| voiceSwitch.visibility = View.GONE | voiceSwitch.visibility = View.GONE | ||||
| /** 初始四选一的点击事件 只处理问题和单词的事件,选项事件,每个新的单词开始时设置,答题后再取消设置 | /** 初始四选一的点击事件 只处理问题和单词的事件,选项事件,每个新的单词开始时设置,答题后再取消设置 | ||||
| * 拼写,释义、单词都不发音,只有拼写在拼写完成发音 | * 拼写,释义、单词都不发音,只有拼写在拼写完成发音 | ||||
| * 作文知识点测试,没有发音 | * 作文知识点测试,没有发音 | ||||
| * 音标测试也不发音 | |||||
| * 辨音、口语单词与音频均可发音, | * 辨音、口语单词与音频均可发音, | ||||
| * 其他单词可以发音 | * 其他单词可以发音 | ||||
| * */ | * */ | ||||
| private fun initChooseQuestionListener() { | private fun initChooseQuestionListener() { | ||||
| 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_SPELL, AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> { | ||||
| } | } | ||||
| else -> { | else -> { |
| tag = LEFT_TAG_ANSWER | tag = LEFT_TAG_ANSWER | ||||
| } | } | ||||
| binding.incControlButton.tvCenter.visibility = View.INVISIBLE | binding.incControlButton.tvCenter.visibility = View.INVISIBLE | ||||
| binding.incControlButton.tvRight.visibility = when (vm.learnData.lesson.courseType) { | |||||
| AppConstants.COURSEPACK_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_CHINESE_PINYIN, AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK -> View.INVISIBLE | |||||
| binding.incControlButton.tvRight.visibility = when (vm.learnData.lesson.coursePackType) { | |||||
| AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION,AppConstants.COURSEPACK_TYPE_ENGLISH_SOUNDMARK -> View.INVISIBLE | |||||
| else -> View.VISIBLE | else -> View.VISIBLE | ||||
| } | } | ||||
| tag = LEFT_TAG_CORRECT | tag = LEFT_TAG_CORRECT | ||||
| } | } | ||||
| binding.incControlButton.tvCenter.visibility = View.VISIBLE | binding.incControlButton.tvCenter.visibility = View.VISIBLE | ||||
| //音标,显示重读 | |||||
| when(vm.learnData.lesson.coursePackType){ | |||||
| AppConstants.COURSEPACK_TYPE_ENGLISH_SOUNDMARK -> View.VISIBLE | |||||
| } | |||||
| } | } | ||||
| /**点击正确*/ | /**点击正确*/ | ||||
| private fun clickCorrect() { | private fun clickCorrect() { | ||||
| readWord() | |||||
| //设tag为0 ,避免出现异常情况 | //设tag为0 ,避免出现异常情况 | ||||
| binding.incControlButton.tvLeft.tag = 0 | binding.incControlButton.tvLeft.tag = 0 | ||||
| adapterHistorical.currentLearnOver() | adapterHistorical.currentLearnOver() |
| import android.content.Intent | import android.content.Intent | ||||
| import android.graphics.Color | import android.graphics.Color | ||||
| import android.os.Bundle | import android.os.Bundle | ||||
| import android.text.Html | |||||
| import android.text.method.ScrollingMovementMethod | |||||
| import android.view.View | import android.view.View | ||||
| import androidx.core.content.ContextCompat | import androidx.core.content.ContextCompat | ||||
| import androidx.core.content.res.ResourcesCompat | import androidx.core.content.res.ResourcesCompat | ||||
| import androidx.lifecycle.ViewModel | import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
| import androidx.viewpager2.widget.ViewPager2 | import androidx.viewpager2.widget.ViewPager2 | ||||
| import com.google.android.material.bottomsheet.BottomSheetBehavior | |||||
| import com.google.android.material.bottomsheet.BottomSheetDialog | import com.google.android.material.bottomsheet.BottomSheetDialog | ||||
| import com.suliang.common.AppConfig | import com.suliang.common.AppConfig | ||||
| import com.suliang.common.base.activity.BaseActivityVM | import com.suliang.common.base.activity.BaseActivityVM | ||||
| import com.suliang.common.extension.click | import com.suliang.common.extension.click | ||||
| import com.suliang.common.util.LogUtil | |||||
| import com.suliang.common.extension.setHtml | |||||
| import com.suliang.common.util.os.ScreenUtil | import com.suliang.common.util.os.ScreenUtil | ||||
| import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
| import com.xkl.cdl.adapter.AdapterAutoPlaySelectRepeat | import com.xkl.cdl.adapter.AdapterAutoPlaySelectRepeat | ||||
| import com.xkl.cdl.adapter.ViewPagerAdapter | import com.xkl.cdl.adapter.ViewPagerAdapter | ||||
| 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.LearnWord | |||||
| import com.xkl.cdl.data.bean.course.Lesson | import com.xkl.cdl.data.bean.course.Lesson | ||||
| import com.xkl.cdl.data.bean.intentdata.LearnData | import com.xkl.cdl.data.bean.intentdata.LearnData | ||||
| import com.xkl.cdl.data.binding.BindingAdapter | import com.xkl.cdl.data.binding.BindingAdapter | ||||
| import com.xkl.cdl.data.manager.CourseManager | import com.xkl.cdl.data.manager.CourseManager | ||||
| import com.xkl.cdl.data.repository.DataRepository | |||||
| import com.xkl.cdl.databinding.ActivityCourseMainBinding | |||||
| import com.xkl.cdl.databinding.DialogBottomAutoPlaySelectBinding | |||||
| import com.xkl.cdl.databinding.DialogBottomCourseMoreBinding | |||||
| import com.xkl.cdl.databinding.* | |||||
| 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.CoursePackIntroductionBottomSheetDialog | |||||
| import com.xkl.cdl.module.learn.LearnWordActivity | import com.xkl.cdl.module.learn.LearnWordActivity | ||||
| import com.xkl.cdl.module.m_center_learn.coursechildren.CourseMainFragment | import com.xkl.cdl.module.m_center_learn.coursechildren.CourseMainFragment | ||||
| import com.zackratos.ultimatebarx.ultimatebarx.statusBarOnly | import com.zackratos.ultimatebarx.ultimatebarx.statusBarOnly | ||||
| //设置简介的箭头大小 | //设置简介的箭头大小 | ||||
| ResourcesCompat.getDrawable(resources, R.drawable.ic_arrow_right, null)?.apply { | ResourcesCompat.getDrawable(resources, R.drawable.ic_arrow_right, null)?.apply { | ||||
| setBounds(0, 0, 36, 36) | setBounds(0, 0, 36, 36) | ||||
| binding.textViewIntroduction.setCompoundDrawables(null, null, this, null) | |||||
| binding.tvIntroduction.setCompoundDrawables(null, null, this, null) | |||||
| } | |||||
| //简介点击 | |||||
| binding.tvIntroduction.click { | |||||
| showIntroductionDialog() | |||||
| } | } | ||||
| //返回事件 | //返回事件 | ||||
| binding.includeTitleBar.titleBar.run { | binding.includeTitleBar.titleBar.run { | ||||
| onBackClick = { _ -> finish() } | onBackClick = { _ -> finish() } | ||||
| } | } | ||||
| //更多按钮点击 | |||||
| binding.includeCourseProgress.ivMore.click { | |||||
| if ((childFragments[binding.viewPager2.currentItem] as CourseMainFragment).vm.showMoreIsEnable()) showMoreDialog() | |||||
| else showToast("请先进行学习") | |||||
| } | |||||
| //初始化tab和viewPager | //初始化tab和viewPager | ||||
| initTabAndViewPager() | initTabAndViewPager() | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| //更多按钮点击 | |||||
| binding.includeCourseProgress.ivMore.click { | |||||
| if ((childFragments[binding.viewPager2.currentItem] as CourseMainFragment).vm.showMoreIsEnable()) showMoreDialog() | |||||
| else showToast("请先进行学习") | |||||
| } | |||||
| } | } | ||||
| override fun loadData() { | override fun loadData() { | ||||
| } | } | ||||
| /** 简介弹窗 */ | |||||
| private fun showIntroductionDialog() { | |||||
| CoursePackIntroductionBottomSheetDialog.newInstance(vm.coursePack.coursePackName,vm.coursePack.summary).show(supportFragmentManager,"introducation") | |||||
| } | |||||
| /** 点击显示更多的弹窗 */ | /** 点击显示更多的弹窗 */ | ||||
| private fun showMoreDialog() { | private fun showMoreDialog() { | ||||
| val moreDialog = BottomSheetDialog(this, R.style.dialog_style).apply { | |||||
| BottomSheetDialog(this, R.style.dialog_style).apply { | |||||
| val moreBinding = DataBindingUtil.inflate<DialogBottomCourseMoreBinding>(layoutInflater, | val moreBinding = DataBindingUtil.inflate<DialogBottomCourseMoreBinding>(layoutInflater, | ||||
| R.layout.dialog_bottom_course_more, null, | R.layout.dialog_bottom_course_more, null, | ||||
| false) | false) |
| //读取课程数据 | //读取课程数据 | ||||
| // TODO: 2022/3/22 读取当前app绑定的课程数据, | // TODO: 2022/3/22 读取当前app绑定的课程数据, | ||||
| DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615") | |||||
| DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615,516,411") | |||||
| //复制课程的数据库到对应位置 | //复制课程的数据库到对应位置 | ||||
| CourseManager.checkCourseDb() | CourseManager.checkCourseDb() | ||||
| //定时跳跃到住主界面 | //定时跳跃到住主界面 |
| <!--简介--> | <!--简介--> | ||||
| <TextView | <TextView | ||||
| android:id="@+id/text_view_introduction" | |||||
| android:id="@+id/tv_introduction" | |||||
| android:layout_width="wrap_content" | android:layout_width="wrap_content" | ||||
| android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||||
| android:layout_marginEnd="@dimen/global_spacing" | android:layout_marginEnd="@dimen/global_spacing" |
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <layout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
| xmlns:tools="http://schemas.android.com/tools" | |||||
| xmlns:app="http://schemas.android.com/apk/res-auto"> | |||||
| <data> | |||||
| </data> | |||||
| <LinearLayout | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="match_parent" | |||||
| android:background="@drawable/shape_rounder_toplr_24_white" | |||||
| android:orientation="vertical" | |||||
| android:paddingStart="@dimen/global_spacing" | |||||
| android:paddingTop="24dp" | |||||
| android:paddingEnd="@dimen/global_spacing" | |||||
| android:paddingBottom="10dp"> | |||||
| <TextView | |||||
| android:id="@+id/tv_title" | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="wrap_content" | |||||
| android:textColor="@color/main_text_color" | |||||
| android:textSize="22dp" | |||||
| android:textStyle="bold" | |||||
| tools:text="学考乐小学英语单词班" /> | |||||
| <TextView | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="wrap_content" | |||||
| android:layout_marginTop="12dp" | |||||
| android:text="@string/course_introduction" | |||||
| android:textColor="@color/main_text_color" | |||||
| android:textSize="@dimen/bigSize" | |||||
| android:textStyle="bold" /> | |||||
| <!-- <androidx.core.widget.NestedScrollView--> | |||||
| <!-- android:layout_width="match_parent"--> | |||||
| <!-- android:layout_height="match_parent"--> | |||||
| <!-- android:overScrollMode="never"--> | |||||
| <!-- >--> | |||||
| <TextView | |||||
| android:id="@+id/tv_introduction" | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="match_parent" | |||||
| app:layout_behavior="@string/appbar_scrolling_view_behavior" | |||||
| android:layout_marginTop="12dp" | |||||
| android:textColor="@color/gray_2" | |||||
| android:textSize="@dimen/smallSize" | |||||
| android:text="getLayoutPosition,顾名思义,就是获取该ViewHolder在实际布局中的位置。我们都知道,RecyclerView使用LayoutManager来管理数据集的现实。当开发者调用notifyData*()等方法通知RecyclerView刷新UI时,出于性能的考虑,RecyclerView的UI并不会立刻刷新,和Data保持一致,而是通过LayoutManager惰性更新相关布局——这个过程伴随着时间上的等待,通常情况下,这个等待时间小于16ms。所以,从感官上讲,getLayoutPosition与getAbsoluteAdapterPosition十分相似:getAbsoluteAdapterPosition返回的是该ViewHolder相对于RecyclerView的绝对位置,而getLayoutPosition返回的是该ViewHolder相对于RecyclerView实际布局的绝对位置。 | |||||
| 说具体点,就是adapter和layout的位置会有时间差(通常情况下16ms), 如果你改变了Adapter的数据然后刷新视图, layout需要过一段时间才会更新视图, 在这段时间里面, 这两个方法返回的position会不一样。 | |||||
| 在notifyDataSetChanged之后并不能马上获取Adapter中的position, 要等布局结束之后才能获取到. | |||||
| 而对于Layout的position, 在notifyItemInserted之后, Layout不能马上获取到新的position, 因为布局还没更新(需要16ms的时间刷新视图), 所以只能获取到旧的, 但是Adapter中的position就可以马上获取到最新的position。 | |||||
| 所以,对于上面的点击事件的场景,我们在获取用户点击位置的时候,使用getLayoutPosition可能效果更好,这样,就能确保用户点击的始终是他看到的那个数据(消除16ms带来的时间差问题),代码可以改造成下面这样 | |||||
| ———————————————— | |||||
| 版权声明:本文为CSDN博主「普通网友」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 | |||||
| 原文链接:https://blog.csdn.net/u012165769/article/details/119706823遇到这种方法模棱两可,让人傻傻getLayoutPosition,顾名思义,就是获取该ViewHolder在实际布局中的位置。我们都知道,RecyclerView使用LayoutManager来管理数据集的现实。当开发者调用notifyData*()等方法通知RecyclerView刷新UI时,出于性能的考虑,RecyclerView的UI并不会立刻刷新,和Data保持一致,而是通过LayoutManager惰性更新相关布局——这个过程伴随着时间上的等待,通常情况下,这个等待时间小于16ms。所以,从感官上讲,getLayoutPosition与getAbsoluteAdapterPosition十分相似:getAbsoluteAdapterPosition返回的是该ViewHolder相对于RecyclerView的绝对位置,而getLayoutPosition返回的是该ViewHolder相对于RecyclerView实际布局的绝对位置。 | |||||
| 说具体点,就是adapter和layout的位置会有时间差(通常情况下16ms), 如果你改变了Adapter的数据然后刷新视图, layout需要过一段时间才会更新视图, 在这段时间里面, 这两个方法返回的position会不一样。 | |||||
| 在notifyDataSetChanged之后并不能马上获取Adapter中的position, 要等布局结束之后才能获取到. | |||||
| 而对于Layout的position, 在notifyItemInserted之后, Layout不能马上获取到新的position, 因为布局还没更新(需要16ms的时间刷新视图), 所以只能获取到旧的, 但是Adapter中的position就可以马上获取到最新的position。 | |||||
| 所以,对于上面的点击事件的场景,我们在获取用户点击位置的时候,使用getLayoutPosition可能效果更好,这样,就能确保用户点击的始终是他看到的那个数据(消除16ms带来的时间差问题),代码可以改造成下面这样 | |||||
| ———————————————— | |||||
| 版权声明:本文为CSDN博主「普通网友」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 | |||||
| 原文链接:https://blog.csdn.net/u012165769/article/details/119706823遇到这种方法模棱两可,让人傻傻分不清楚的情况,作为API调用者的我们,需要我们做到的就是适当的阅读源码注释,结合官方文档,正确理解他们各自所代表的含义以及可能带来的影响,合理使用他们。" /> | |||||
| <!-- </androidx.core.widget.NestedScrollView>--> | |||||
| </LinearLayout> | |||||
| </layout> |
| <resources> | |||||
| <dimen name="fab_margin">48dp</dimen> | |||||
| </resources> |
| <resources> | |||||
| <dimen name="fab_margin">200dp</dimen> | |||||
| </resources> |
| <resources> | |||||
| <dimen name="fab_margin">48dp</dimen> | |||||
| </resources> |
| <string name="course_relearn_sure">确认清空</string> | <string name="course_relearn_sure">确认清空</string> | ||||
| <string name="quit_auto_play_title">你确定要退出自动播放吗?</string> | <string name="quit_auto_play_title">你确定要退出自动播放吗?</string> | ||||
| <string name="quit_auto_play_title_over">本课程自动播放完毕</string> | <string name="quit_auto_play_title_over">本课程自动播放完毕</string> | ||||
| <string name="course_introduction">课程简介</string> | |||||
| </resources> | </resources> |