Browse Source

statistics

master
suliang 2 years ago
parent
commit
f5f4ac2bc1
32 changed files with 1381 additions and 62 deletions
  1. 15
    0
      .idea/misc.xml
  2. 2
    0
      app/build.gradle
  3. BIN
      app/libs/mobile_cache.aar
  4. 40
    0
      app/src/main/java/com/xkl/cdl/adapter/AdapterStaticsTime.kt
  5. 16
    0
      app/src/main/java/com/xkl/cdl/data/bean/TimeStatisticItem.kt
  6. 11
    0
      app/src/main/java/com/xkl/cdl/data/manager/CourseManager.kt
  7. 11
    0
      app/src/main/java/com/xkl/cdl/data/repository/DataRepository.kt
  8. 1
    1
      app/src/main/java/com/xkl/cdl/module/m_service_center/TestDetailActivity.kt
  9. 268
    53
      app/src/main/java/com/xkl/cdl/module/m_statics/StaticsFragment.kt
  10. 302
    0
      app/src/main/java/com/xkl/cdl/module/m_statics/StaticsFragmentViewModel.kt
  11. 66
    0
      app/src/main/java/com/xkl/cdl/module/m_statics/StatisticsTimeTopFragment.kt
  12. 80
    0
      app/src/main/java/com/xkl/cdl/widget/MyMarkerView.java
  13. 10
    0
      app/src/main/res/drawable/select_statictis_time_tab_bg.xml
  14. 64
    0
      app/src/main/res/drawable/shadow_layer.xml
  15. 7
    0
      app/src/main/res/drawable/shape_cicler_6_red.xml
  16. 5
    0
      app/src/main/res/drawable/shape_rounder_4_green_a5.xml
  17. 5
    0
      app/src/main/res/drawable/shape_rounder_4_purple_a5.xml
  18. 5
    0
      app/src/main/res/drawable/shape_rounder_4_red_a5.xml
  19. 5
    0
      app/src/main/res/drawable/shape_rounder_4_theme_a5.xml
  20. 24
    0
      app/src/main/res/layout/custom_marker_view.xml
  21. 209
    5
      app/src/main/res/layout/fragment_statics.xml
  22. 60
    0
      app/src/main/res/layout/fragment_statistics_time_top.xml
  23. 72
    0
      app/src/main/res/layout/item_statics_for_time.xml
  24. 23
    0
      app/src/main/res/layout/item_xpopup_statistics_choose_subject.xml
  25. 12
    0
      app/svg/drawable/ic_chinese.xml
  26. 12
    0
      app/svg/drawable/ic_decline.xml
  27. 12
    0
      app/svg/drawable/ic_english.xml
  28. 12
    0
      app/svg/drawable/ic_keep.xml
  29. 12
    0
      app/svg/drawable/ic_rise.xml
  30. 3
    1
      build.gradle
  31. 1
    1
      lib/common/build.gradle
  32. 16
    1
      lib/common/src/main/java/com/suliang/common/widget/NumberUtils.kt

+ 15
- 0
.idea/misc.xml View File

<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/progressbar_countdown_time.xml" value="0.45740740740740743" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/progressbar_countdown_time.xml" value="0.45740740740740743" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/selector_memo_review_bg.xml" value="0.5010416666666667" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/selector_memo_review_bg.xml" value="0.5010416666666667" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/selector_memo_test_bg.xml" value="0.5010416666666667" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/selector_memo_test_bg.xml" value="0.5010416666666667" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shadow_layer.xml" value="0.4876923076923077" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_cicler_24_c3d69b.xml" value="0.49333333333333335" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_cicler_24_c3d69b.xml" value="0.49333333333333335" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_cicler_24_ffcc99.xml" value="0.49333333333333335" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_cicler_24_ffcc99.xml" value="0.49333333333333335" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_cicler_6_red.xml" value="0.4973958333333333" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_o_red.xml" value="0.36203703703703705" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_o_red.xml" value="0.36203703703703705" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_red_badge.xml" value="0.4973958333333333" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_12_white.xml" value="0.5140625" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_12_white.xml" value="0.5140625" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_4_green_a5.xml" value="0.4973958333333333" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_4_purple_a5.xml" value="0.4973958333333333" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_4_red.xml" value="0.4953125" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_4_theme_a5.xml" value="0.4973958333333333" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_8_solid_green1.xml" value="0.5010416666666667" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_8_solid_green1.xml" value="0.5010416666666667" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_8_solider_gray_1.xml" value="0.5010416666666667" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_8_solider_gray_1.xml" value="0.5010416666666667" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_8_stroke_gray1.xml" value="0.503125" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_rounder_8_stroke_gray1.xml" value="0.503125" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_switch_thumb.xml" value="0.14074074074074075" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_switch_thumb.xml" value="0.14074074074074075" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_switch_track.xml" value="0.26851851851851855" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/shape_switch_track.xml" value="0.26851851851851855" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/spoken_autoplay_btn_text_color_.xml" value="0.5140625" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/spoken_autoplay_btn_text_color_.xml" value="0.5140625" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/statictis_time_tab_bg.xml" value="0.1259259259259259" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/switch_thumb_selector.xml" value="0.3768518518518518" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/switch_thumb_selector.xml" value="0.3768518518518518" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/switch_track_selector.xml" value="0.3768518518518518" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/switch_track_selector.xml" value="0.3768518518518518" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/test_error_state_button_bg.xml" value="0.45740740740740743" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/drawable/test_error_state_button_bg.xml" value="0.45740740740740743" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_splash.xml" value="0.4921875" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_splash.xml" value="0.4921875" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_test_detail.xml" value="0.33" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/activity_test_detail.xml" value="0.33" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/content_learn_base.xml" value="0.4979166666666667" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/custom_marker_view.xml" value="0.23353596757852077" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/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_introducation.xml" value="0.1956521739130435" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_learn_center.xml" value="0.25" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_learn_center.xml" value="0.25" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_memo.xml" value="0.25" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_memo.xml" value="0.25" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_my.xml" value="0.28229166666666666" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_my.xml" value="0.28229166666666666" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_statics.xml" value="0.33" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/fragment_statistics_time_top.xml" value="0.10833333333333334" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_control_button.xml" value="0.46467391304347827" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_control_button.xml" value="0.46467391304347827" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_exam_spell_content.xml" value="0.45153985507246375" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_exam_spell_content.xml" value="0.45153985507246375" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_exam_word_choose_content.xml" value="0.33" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/inc_exam_word_choose_content.xml" value="0.33" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_literacy.xml" value="0.5" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_literacy.xml" value="0.5" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_pinyin.xml" value="0.67" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_memo_detail_list_pinyin.xml" value="0.67" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_spell_single_word.xml" value="0.23632218844984804" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_spell_single_word.xml" value="0.23632218844984804" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_statics_for_time.xml" value="0.27717391304347827" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_task_image.xml" value="0.23353596757852077" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_task_image.xml" value="0.23353596757852077" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail.xml" value="0.348731884057971" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail.xml" value="0.348731884057971" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail_option.xml" value="0.348731884057971" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail_option.xml" value="0.348731884057971" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail_option_2.xml" value="0.348731884057971" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_test_detail_option_2.xml" value="0.348731884057971" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_video_adapter.xml" value="0.67" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_video_adapter.xml" value="0.67" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_xpopup_statistics_choose_subject.xml" value="0.21965579710144928" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_course_progress.xml" value="0.25" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_course_progress.xml" value="0.25" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_coursepack.xml" value="0.43500866551126516" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_coursepack.xml" value="0.43500866551126516" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_memo_list_item_english_header.xml" value="0.2373353596757852" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_memo_list_item_english_header.xml" value="0.2373353596757852" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_memo_list_item_pinyin_header.xml" value="0.5" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_memo_list_item_pinyin_header.xml" value="0.5" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_recyclerview_smart_refresh_layout.xml" value="0.34427083333333336" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_recyclerview_smart_refresh_layout.xml" value="0.34427083333333336" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/smart_refresh_header.xml" value="0.34427083333333336" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/smart_refresh_header.xml" value="0.34427083333333336" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/statics_tab_top_radiobutton.xml" value="0.20833333333333334" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/textview.xml" value="0.49773550724637683" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/textview.xml" value="0.49773550724637683" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/textview_only.xml" value="0.49773550724637683" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/textview_only.xml" value="0.49773550724637683" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/statedrawable/drawable/ic_nav_learn_center.xml" value="0.44166666666666665" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/statedrawable/drawable/ic_nav_learn_center.xml" value="0.44166666666666665" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_course_voice.xml" value="0.35555555555555557" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_course_voice.xml" value="0.35555555555555557" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_discern.xml" value="0.5061538461538462" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_discern.xml" value="0.5061538461538462" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_down.xml" value="0.503125" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_down.xml" value="0.503125" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_english.xml" value="0.4973958333333333" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_horuns.xml" value="0.503125" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_horuns.xml" value="0.503125" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_icon___.xml" value="0.287962962962963" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_icon___.xml" value="0.287962962962963" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_menu.xml" value="0.4036458333333333" /> <entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_menu.xml" value="0.4036458333333333" />

+ 2
- 0
app/build.gradle View File

implementation customDependencies.CalendarView implementation customDependencies.CalendarView
// FlexBoxLayoutManager // FlexBoxLayoutManager
implementation customDependencies.FlexBoxLayoutManager implementation customDependencies.FlexBoxLayoutManager
//图标
implementation customDependencies.Chart




} }

BIN
app/libs/mobile_cache.aar View File


+ 40
- 0
app/src/main/java/com/xkl/cdl/adapter/AdapterStaticsTime.kt View File

package com.xkl.cdl.adapter

import android.view.ViewGroup
import androidx.core.content.ContextCompat
import com.suliang.common.base.adapter.BaseAdapterViewHolder
import com.suliang.common.base.adapter.BaseRVAdapter
import com.xkl.cdl.R
import com.xkl.cdl.data.bean.TimeStatisticItem
import com.xkl.cdl.databinding.ItemStaticsForTimeBinding

/**
* author suliang
* create 2022/6/23 14:34
* Describe:
*/
class AdapterStaticsTime:BaseRVAdapter<TimeStatisticItem>() {
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder {
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_statics_for_time))
}
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) {
(holder.binding as ItemStaticsForTimeBinding).run {
getItem(position).let {
layout.setBackgroundResource(it.backGround)
tvName.text = it.name
tvContent.text = it.time
tvUnit.text = it.unit
tvState.run {
text = it.incr
if (it.incrTextColor != 0) {
setTextColor(ContextCompat.getColor(context,it.incrTextColor))
}
setCompoundDrawablesWithIntrinsicBounds(it.imgDrawable,0,0,0)
}
}
}
}
}

+ 16
- 0
app/src/main/java/com/xkl/cdl/data/bean/TimeStatisticItem.kt View File

package com.xkl.cdl.data.bean

/**
* author suliang
* create 2022/6/23 14:38
* Describe:
*/
class TimeStatisticItem {
var name : String ="" //标题
var unit : String = "" //显示单位
var time : String = "" //显示时间内容
var incr : String = "" //增量
var imgDrawable : Int = 0 //drawableStart值
var incrTextColor: Int = 0 //增量颜色
var backGround : Int = 0 //背景
}

+ 11
- 0
app/src/main/java/com/xkl/cdl/data/manager/CourseManager.kt View File

return false return false
} }
/** 获取课程的数量 */
fun getTotalCourseSize() : Int {
var result = 0
subjectWithCoursePackMap.forEach { entry ->
entry.value.forEach { coursePack ->
result += coursePack.childrenCourses.size
}
}
return result
}
} }

+ 11
- 0
app/src/main/java/com/xkl/cdl/data/repository/DataRepository.kt View File

} }
} }
/** 获取词条数统计 */
fun getStatisticsChartData(projectId:Int): Observable<AppApi.EntityCountListResponse> {
return Observable.create {
//近90天词条数统计
val entityCountList = XKLApplication.mobileCache.entityCountList(projectId.toLong(), 0)
val parseFrom = AppApi.EntityCountListResponse.parseFrom(entityCountList)
it.onNext(parseFrom)
it.onComplete()
}
}
} }

+ 1
- 1
app/src/main/java/com/xkl/cdl/module/m_service_center/TestDetailActivity.kt View File

private fun initScore():String{ private fun initScore():String{
return when(vm.courseType){ return when(vm.courseType){
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> "完成" AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> "完成"
else -> "${vm.learnExam.score}<small><small><small>分</small></small></small>"
else -> "${vm.learnExam.score.toInt()}<small><small><small>分</small></small></small>"
} }
} }

+ 268
- 53
app/src/main/java/com/xkl/cdl/module/m_statics/StaticsFragment.kt View File

package com.xkl.cdl.module.m_statics package com.xkl.cdl.module.m_statics


import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.graphics.Typeface
import android.text.Html
import android.text.SpannableString
import android.text.Spanned
import android.text.style.StyleSpan
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import appApi.AppApi.EntityCount
import com.github.mikephil.charting.components.*
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.github.mikephil.charting.listener.OnChartValueSelectedListener
import com.github.mikephil.charting.renderer.LineChartRenderer
import com.google.android.material.tabs.TabLayout
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.enums.PopupPosition
import com.suliang.common.base.fragment.BaseFragmentVM import com.suliang.common.base.fragment.BaseFragmentVM
import com.suliang.common.extension.click
import com.suliang.common.extension.loadFragment
import com.suliang.common.extension.setHtml
import com.xkl.cdl.R import com.xkl.cdl.R
import com.xkl.cdl.databinding.FragmentMyBinding
import com.xkl.cdl.adapter.AdapterStaticsTime
import com.xkl.cdl.data.AppConstants
import com.xkl.cdl.databinding.FragmentStaticsBinding import com.xkl.cdl.databinding.FragmentStaticsBinding
import com.xkl.cdl.module.main.MainActivityViewModel

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
* A simple [Fragment] subclass.
* Use the [StaticsFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class StaticsFragment : BaseFragmentVM<FragmentStaticsBinding, MainActivityViewModel>() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_statics, container, false)
}
import com.xkl.cdl.widget.MyMarkerView


class StaticsFragment : BaseFragmentVM<FragmentStaticsBinding, StaticsFragmentViewModel>() {
companion object { companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment StaticsFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic @JvmStatic
fun newInstance() = StaticsFragment() fun newInstance() = StaticsFragment()
} }

override fun initViewModel() : StaticsFragmentViewModel {
return ViewModelProvider(this)[StaticsFragmentViewModel::class.java]
}
override fun initFragment() { override fun initFragment() {

//添加碎片
loadFragment(R.id.fragment_top_time,0,StatisticsTimeTopFragment())
//detail
binding.layoutEnglish.click {
// TODO: 2022/6/24 进入详情
}
binding.layoutChinese.click { }
//chart change
binding.tvChartSubjectChoose.click {
XPopup.Builder(requireContext()).apply {
hasShadowBg(false)
atView(it)
popupPosition(PopupPosition.Bottom)
hasStatusBar(true)
isLightStatusBar(true)
}.asAttachList(initChartSubjectChooseValue(), intArrayOf(), { position, text ->
if (binding.tvChartSubjectChoose.text.toString() != text) {
binding.tvChartSubjectChoose.text = text
vm.chartChooseProjectIdLiveData.value = when (text) {
"英语" -> AppConstants.SUBJECT_ENGLISH
"语文" -> AppConstants.SUBJECT_CHINESE
else -> 0
}
}
}, 0, R.layout.item_xpopup_statistics_choose_subject).show()
}
initChart()
} }

override fun loadData() { override fun loadData() {


//监听图表项目切换变化
vm.chartChooseProjectIdLiveData.observe(this) {
//获取词条数据,进行图标数据实例
vm.getStatisticsChartData(it)
}
//监听图标数据初始结果
vm.chartLineInitLiveData.observe(this) {
when {
!it -> binding.chart.setNoDataText("暂无数据")
else -> {
setChartData()
val lineData = LineData(vm.linDataSet_new, vm.linDataSet_review).apply {
setValueTextColor(ContextCompat.getColor(requireContext(), R.color.white))
setValueTextSize(9f)
}
//渐变设置
lineData.dataSets.forEach {
//设置折线顺滑
(it as LineDataSet).run {
mode = LineDataSet.Mode.HORIZONTAL_BEZIER
setDrawValues(false)
}
}
binding.chart.data = lineData
//设置是否显示点
binding.chart.run {
(renderer as LineChartRenderer).run {
}
//默认选中
vm.linDataSet_review?.let {
highlightValue(it.values.size - 1f, 1)
}
//设置高亮x文字颜色
rendererXAxis
}
}
}
}
}
override fun onHiddenChanged(hidden : Boolean) {
super.onHiddenChanged(hidden)
if (!hidden){
///设置时间统计的选中项
childFragmentManager.findFragmentByTag(StatisticsTimeTopFragment::javaClass.name)?.run {
//设置时间统计的选中项
(this as StatisticsTimeTopFragment).binding.tabLayoutTime.getTabAt(0)?.select()
}
//图表设置
vm.chartChooseProjectIdLiveData.value = vm.chartChooseProjectIdLiveData.value
}
}
private fun initChartSubjectChooseValue() : Array<String> {
return when (binding.tvChartSubjectChoose.text.toString()) {
"全部项目" -> arrayOf("英语", "语文")
"英语" -> arrayOf("全部项目", "语文")
else -> arrayOf("英语", "全部项目")
}
} }
private fun initChart() {
binding.chart.run {
description.isEnabled = false //no description text 描述隐藏
setTouchEnabled(true) // enable touch gesture
isDragEnabled = true //滑动
setScaleEnabled(false) //紧张缩放
setDrawGridBackground(false) //不绘制网格
isHighlightPerDragEnabled = true //高亮显示
setPinchZoom(false) //缩放显示详细数字
isDoubleTapToZoomEnabled = false //双击缩放
setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white)) //背景
animateX(800) //动画时间
//隐藏legend
legend.isEnabled = false


override fun initViewModel(): MainActivityViewModel {
return ViewModelProvider(requireActivity())[MainActivityViewModel::class.java]
// //线条描述
// legend.apply {
// isEnabled = false
// form = Legend.LegendForm.CIRCLE
// verticalAlignment = Legend.LegendVerticalAlignment.TOP
// horizontalAlignment = Legend.LegendHorizontalAlignment.LEFT
// setDrawInside(false)
// }
//右侧不显示
axisRight.isEnabled = false
setOnChartValueSelectedListener(object : OnChartValueSelectedListener {
override fun onValueSelected(e : Entry, h : Highlight) {
binding.chart.data.dataSets.forEach {
if (it.getEntryIndex(e) >= 0) {
(binding.chart.marker as MyMarkerView).offsetX = if (e.x > 4) -300f else 300f
binding.chart.moveViewToAnimated(it.getEntryIndex(e) - 4f, 100f, YAxis.AxisDependency.RIGHT, 500)
}
}
}
override fun onNothingSelected() {
}
})
//标记显示View
val myMarkerView = MyMarkerView(context, R.layout.custom_marker_view)
myMarkerView.chartView = this
marker = myMarkerView
myMarkerView.setValueCallback { tv, e ->
val sets : List<ILineDataSet> = this.data.dataSets
val dataSet1 = sets[0]
val dataSet2 = sets[1]
var index = dataSet1.getEntryIndex(e)
if (index == -1) {
index = dataSet2.getEntryIndex(e)
}
if (vm.entityCountList.size > index) {
var str = """
${vm.entityCountList[index].day}
<font color='#8A8A99'> 新学词条数:</font> <font color='#3F51B5'> ${vm.entityCountList[index].n}</font><font color='#8A8A99'> 个 </font>
<font color='#8A8A99'> 复习词条数:</font> <font color='#F26255'> ${vm.entityCountList[index].r}</font><font color='#8A8A99'> 个 </font>
""".trimIndent()
val spanString = SpannableString(str)
val span = StyleSpan(Typeface.BOLD)
spanString.setSpan(span, 0, vm.entityCountList[index].day.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
str = str.replace("\n", "<br>")
tv.setHtml(str)
}
}
}
}
private fun setChartData() {
// LineChart 折线图
// LineData //线集合,所有折线已数组形式存放到此集合
// LineDataSet //点集合,即一条折线
// Entry //点

// XAxis //x轴
// YAxis //y轴
// Legend //图例 标识哪一条曲线
// LimitLine //限制线
// Description //描述
// List<Float> 存放数据的list列表
// List<Entry> 存放折线点的列表
// LineDataSet(List<Entry>,"步") 点集合,一条线
//x轴
binding.chart.xAxis.run {
textSize = 11f //dp
textColor = ContextCompat.getColor(requireContext(), R.color.gray_2) //颜色
//设置坐标轴的线条
setDrawGridLines(false)
setDrawAxisLine(false)
//x坐标最小间隔
granularity = 1f
//x轴的最大,最小值
axisMinimum = -0.6f
axisMaximum = vm.entityCountList.size - 0.1f
isGranularityEnabled = true //间隔粒度控制
position = XAxis.XAxisPosition.BOTTOM_INSIDE //x标签位置
//设置x轴为字符串
valueFormatter = object : ValueFormatter() {
override fun getFormattedValue(value : Float) : String {
return vm.getxAxisValue(value)
}
}
}
//x轴一页可见个数
binding.chart.setVisibleXRange(0f, 6f)
//左侧y轴
binding.chart.axisLeft.run {
gridColor = ContextCompat.getColor(requireContext(), R.color.gray_1)
textColor = ContextCompat.getColor(requireContext(), R.color.gray_2)
textSize = 11f
setDrawGridLines(true)
setDrawAxisLine(false)
// 设置最大最小值
when {
vm.maxChart > 0 -> {
axisMaximum = vm.getMaxY()
axisMinimum = vm.getMinY()
}
else -> {
axisMaximum = 5f
axisMinimum = -0.9f
}
}
}
//右侧y轴
binding.chart.axisRight.run {
textColor = ContextCompat.getColor(requireContext(), R.color.gray_2)
// 设置最大最小值
when {
vm.maxChart > 0 -> {
axisMaximum = vm.getMaxY()
axisMinimum = vm.getMinY()
}
else -> {
axisMaximum = 5f
axisMinimum = -0.9f
}
}
}
} }
} }

+ 302
- 0
app/src/main/java/com/xkl/cdl/module/m_statics/StaticsFragmentViewModel.kt View File

package com.xkl.cdl.module.m_statics

import android.graphics.Color
import androidx.lifecycle.MutableLiveData
import appApi.AppApi
import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.utils.ColorTemplate
import com.suliang.common.base.activity.ToastEvent
import com.suliang.common.base.viewmodel.BaseViewModel
import com.suliang.common.extension.diskIo2Main
import com.suliang.common.util.thread.AppExecutors
import com.suliang.common.widget.NumberUtils
import com.xkl.cdl.R
import com.xkl.cdl.data.bean.TimeStatisticItem
import com.xkl.cdl.data.manager.CourseManager
import com.xkl.cdl.data.repository.DataRepository
import com.xkl.cdl.module.XKLApplication
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlin.math.abs
import kotlin.math.max

class StaticsFragmentViewModel : BaseViewModel() {
/**顶部统计信息*/
/** 时间统计选择位置 */
val timeStatisticsPositionLiveData = MutableLiveData<Int>()
lateinit var statisticsResponse : AppApi.StatisticsCenterResponse
var timeValuesList : MutableList<MutableList<TimeStatisticItem>> = mutableListOf()
//chart选中 itemId
var chartChooseProjectIdLiveData = MutableLiveData<Int>(0)
//图标初始完成
val chartLineInitLiveData = MutableLiveData<Boolean>()
fun isInitStatisticsResponse() : Boolean {
return this::statisticsResponse.isInitialized
}
/** 获取时间统计数据 */
fun getStatistics() : MutableLiveData<Boolean> {
val result = MutableLiveData<Boolean>()
Observable.fromCallable {
val statisticsCenter = XKLApplication.mobileCache.statisticsCenter(0, 0)
val parseFrom = AppApi.StatisticsCenterResponse.parseFrom(statisticsCenter)
return@fromCallable parseFrom
}.compose(diskIo2Main()).subscribe({
statisticsResponse = it
initTimeStatic(it)
result.value = true
}, {
it.printStackTrace()
showToast(ToastEvent("数据获取失败"))
result.value = false
})
return result
}
private fun initTimeStatic(statisticsResponse : AppApi.StatisticsCenterResponse) {
timeValuesList.clear()
timeValuesList.add(initTimeStaticItem(statisticsResponse.total))
timeValuesList.add(initTimeStaticItem(statisticsResponse.today))
timeValuesList.add(initTimeStaticItem(statisticsResponse.week))
timeValuesList.add(initTimeStaticItem(statisticsResponse.month))
}
private fun initTimeStaticItem(statistics : AppApi.Statistics) : MutableList<TimeStatisticItem> {
val result = mutableListOf<TimeStatisticItem>()
//有效学习时长
val timeStaticItem_1 = TimeStatisticItem().apply {
name = "有效学习时长"
backGround = R.drawable.shape_rounder_4_red_a5
}
//计算显示使用的单位
if (statistics.sd != 0L) {
val hour = statistics.sd / 3600000.0
val minute = statistics.sd / 60000.0
when {
//大于1小时
hour > 1 -> {
timeStaticItem_1.time =initShow(hour)
timeStaticItem_1.unit = "小时"
}
//大于1分钟
minute > 1 -> {
//取整和保留一位小数的值相同,则使用取整的值显示,否则使用保留小数的值显示
timeStaticItem_1.time =initShow(minute)
timeStaticItem_1.unit = "分钟"
}
//小于1分钟
else -> {
timeStaticItem_1.time = ""
timeStaticItem_1.unit = "不足1分钟"
}
}
}else{
timeStaticItem_1.time = "0"
timeStaticItem_1.unit = ""
}
//增量不为0
if (statistics.sdIncr != 0L ){
val hour_1 = statistics.sdIncr / 3600000.0
val minute_1 = statistics.sdIncr / 60000.0
val sencond = statistics.sdIncr / 1000
when {
//大于1小时
abs(hour_1) > 1 -> timeStaticItem_1.incr = if(statistics.sdIncr > 0) "${initShow(hour_1)}小时" else "-${initShow(abs(hour_1))}小时"
//大于1分钟
abs(minute_1) > 1 -> timeStaticItem_1.incr = if(statistics.sdIncr > 0) "${initShow(minute_1)}分钟" else "-${initShow(abs(minute_1))}分钟"
//小于1分钟 秒数
else -> timeStaticItem_1.incr = "${sencond}秒"
}
}
initIncr(timeStaticItem_1,statistics.sdIncr.toDouble())
result.add(timeStaticItem_1)
//综合学习效率
val timeStaticItem_2 = TimeStatisticItem().apply {
backGround = R.drawable.shape_rounder_4_theme_a5
name = "综合学习效率"
unit = "%"
time = initShow(statistics.se)
initIncr(this,statistics.seIncr)
}
result.add(timeStaticItem_2)
//已学课程
val timeStaticItem_3 = TimeStatisticItem().apply {
backGround = R.drawable.shape_rounder_4_green_a5
name = "已学课程"
unit = "/${CourseManager.getTotalCourseSize()}个"
time = "${statistics.sc}"
initIncr(this,statistics.scIncr.toDouble())
}
result.add(timeStaticItem_3)
//已学进度
val timeStaticItem_4 = TimeStatisticItem().apply {
backGround = R.drawable.shape_rounder_4_purple_a5
name = "已学进度"
unit = "%"
time = initShow(statistics.ts)
initIncr(this,statistics.tsIncr)
}
result.add(timeStaticItem_4)
return result
}
/** 格式化数据,决定显示小数还是不显示 */
private fun initShow(value:Double):String{
//保留一位小数 向下取舍
val formatFloor = NumberUtils.formatFloor(value, "0.0")
val toDouble = formatFloor.toDouble()
//取整
val formatFloor_1 = NumberUtils.formatFloor(value, "0")
val toDouble_1 = formatFloor.toDouble()
//取整和保留一位小数的值相同,则使用取整的值显示,否则使用保留小数的值显示
return when (toDouble_1) {
toDouble -> formatFloor_1
else -> formatFloor
}
}
/**实例化增量图标和颜色与正负*/
private fun initIncr(timeStaticItem_1 : TimeStatisticItem, sdIncr : Double) {
timeStaticItem_1.run {
when{
sdIncr == 0.0 -> {
incr = ""
imgDrawable = R.drawable.ic_keep
}
sdIncr > 0 -> {
imgDrawable = R.drawable.ic_rise
incrTextColor = R.color.green_1
incr = "+$incr"
}
else -> {
imgDrawable = R.drawable.ic_decline
incrTextColor = R.color.red_1
}
}
}
}
/**获取词条数据,进行图标数据实例 */
fun getStatisticsChartData(projectId:Int) {
DataRepository.getStatisticsChartData(projectId)
.subscribeOn(Schedulers.from(AppExecutors.diskIO))
.observeOn(Schedulers.from(AppExecutors.io))
.subscribe({
//进行图标数据处理
entityCountList.clear()
entityCountList.addAll(it.entityCountListList)
initChartLine(it.entityCountListList)
},{
it.printStackTrace()
showToast(ToastEvent("统计数据获取失败"))
})
}
val entityCountList: MutableList<AppApi.EntityCount> = mutableListOf()
var maxChart = 0L
var linDataSet_new : LineDataSet? = null //折线1 : 新学词条
var linDataSet_review : LineDataSet? = null //折线2 : 复习词条
private fun initChartLine(list: List<AppApi.EntityCount>){
maxChart = 0L
linDataSet_new = null
linDataSet_review = null
val entrys_new = mutableListOf<Entry>() //新学点集合
val entrys_review = mutableListOf<Entry>() //复习点集合
list.forEachIndexed { index, it ->
entrys_new.add(Entry(index.toFloat(),it.n.toFloat()))
entrys_review.add(Entry(index.toFloat(),it.r.toFloat()))
maxChart = when{
it.n > it.r -> max(maxChart, it.n)
else -> max(maxChart, it.r)
}
}
if (list.isEmpty()){
chartLineInitLiveData.postValue(false)
return
}
linDataSet_new = LineDataSet(entrys_new, "新学词条数").apply {
axisDependency = YAxis.AxisDependency.RIGHT
color = Color.parseColor("#5082E6")
lineWidth = 2f
circleRadius = 5f
circleHoleRadius = 3f
setCircleColor(Color.parseColor("#5082E6"))
fillAlpha = 65
fillColor = ColorTemplate.getHoloBlue()
highLightColor = Color.parseColor("#1A5082E6")
highlightLineWidth = 18f
setDrawCircleHole(true)
setDrawHorizontalHighlightIndicator(false)
setDrawVerticalHighlightIndicator(true)
}
linDataSet_review = LineDataSet(entrys_review, "复习词条数").apply {
axisDependency = YAxis.AxisDependency.RIGHT
color = Color.parseColor("#F25255")
lineWidth = 2f
circleRadius = 5f
circleHoleRadius = 3f
setCircleColor(Color.parseColor("#F25255"))
fillAlpha = 65
fillColor = Color.RED
highLightColor = Color.parseColor("#1A5082E6")
highlightLineWidth = 18f
setDrawCircleHole(true)
setDrawHorizontalHighlightIndicator(false)
}
chartLineInitLiveData.postValue(true)
}
/** 获取y轴的最大值 */
fun getMaxY(): Float{
//设置坐标轴最大值和最小值
var temp : Int = (maxChart / 5).toInt()
temp = if (temp >= 1000) {
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000
} else if (temp >= 100) {
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100
} else if (temp >= 10) {
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10
} else {
(temp + if (maxChart % 5 > 0) 1 else 0) * 1
}
return (temp * 5 + temp / 2.0).toFloat()
}
/**获取y轴的最小值*/
fun getMinY():Float{
//设置坐标轴最大值和最小值
var temp : Int = (maxChart / 5).toInt()
temp = if (temp >= 1000) {
(temp / 1000 + if (temp % 1000 > 0) 1 else 0) * 1000
} else if (temp >= 100) {
(temp / 100 + if (temp % 100 > 0) 1 else 0) * 100
} else if (temp >= 10) {
(temp / 10 + if (temp % 10 > 0) 1 else 0) * 10
} else {
(temp + if (maxChart % 5 > 0) 1 else 0) * 1
}
return (-(temp - temp / 2.0) - if (temp / 2.5 == 0.0) 0.3 else temp / 2.5).toFloat()
}
/** 获取为x显示的值 */
fun getxAxisValue(value : Float) : String {
if (entityCountList.size > value){
val entity = entityCountList[value.toInt()]
val split = entity.day.split("-")
return if (split[2].equals("01")) "$split[1]月" else split[2]
}
return ""
}
}

+ 66
- 0
app/src/main/java/com/xkl/cdl/module/m_statics/StatisticsTimeTopFragment.kt View File

package com.xkl.cdl.module.m_statics

import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.tabs.TabLayout
import com.suliang.common.base.fragment.BaseFragmentVM
import com.xkl.cdl.adapter.AdapterStaticsTime
import com.xkl.cdl.databinding.FragmentStatisticsTimeTopBinding

/**
* author suliang
* create 2022/6/24 17:24
* Describe:
*/
class StatisticsTimeTopFragment : BaseFragmentVM<FragmentStatisticsTimeTopBinding, StaticsFragmentViewModel>() {
override fun initViewModel() : StaticsFragmentViewModel {
return ViewModelProvider(requireParentFragment())[StaticsFragmentViewModel::class.java]
}
override fun initFragment() {
initTabLayout()
//rv
binding.rvTime.apply {
layoutManager = GridLayoutManager(requireContext(), 2)
adapter = AdapterStaticsTime()
}
}
override fun loadData() {
//监听时间选项变化
vm.timeStatisticsPositionLiveData.observe(this) { position ->
if (!vm.isInitStatisticsResponse()) {
vm.getStatistics().observe(this) {
if (it) {
(binding.rvTime.adapter as AdapterStaticsTime).setData(vm.timeValuesList[position])
}
}
} else {
(binding.rvTime.adapter as AdapterStaticsTime).setData(vm.timeValuesList[position])
}
}
}
private fun initTabLayout() {
binding.tabLayoutTime.run {
addTab(this.newTab().setText("全部时间"), false)
addTab(this.newTab().setText("今日"), false)
addTab(this.newTab().setText("本周"), false)
addTab(this.newTab().setText("本月"), false)
addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab : TabLayout.Tab) {
vm.timeStatisticsPositionLiveData.value = binding.tabLayoutTime.selectedTabPosition
}
override fun onTabUnselected(tab : TabLayout.Tab?) {
print("")
}
override fun onTabReselected(tab : TabLayout.Tab?) {
print("")
}
})
}
}
}

+ 80
- 0
app/src/main/java/com/xkl/cdl/widget/MyMarkerView.java View File


package com.xkl.cdl.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.TextView;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.MarkerView;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.utils.MPPointF;
import com.xkl.cdl.R;

/**
* Custom implementation of the MarkerView.
*
* @author Philipp Jahoda
*/
@SuppressLint("ViewConstructor")
public class MyMarkerView extends MarkerView {

private final TextView tvContent;

private ValueOnListener valueonListener;


//x 绘制偏移量
private float offsetX ;

public void setValueCallback( ValueOnListener listener){
this.valueonListener = listener;
}

public void setOffsetX(float offsetX) {
this.offsetX = offsetX;
}

public float getOffsetX() {
return offsetX;
}

public MyMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
tvContent = findViewById(R.id.tvContent);
}

@Override
public MPPointF getOffset() {
return new MPPointF(-(getWidth() / 2), -getHeight());
}

// runs every time the MarkerView is redrawn, can be used to update the
// content (user-interface)
@Override
public void refreshContent(Entry e, Highlight highlight) {
if (valueonListener!= null)
valueonListener.getFormValue(tvContent,e);

super.refreshContent(e, highlight);
}

// runs every time the MarkerView is redrawn, can be used to update the
// content (user-interface)
public interface ValueOnListener {
void getFormValue(TextView view , Entry e);
}

@Override
public void draw(Canvas canvas, float posX, float posY) {
float newPosX = posX + getOffsetX();
MPPointF offset = getOffsetForDrawingAtPoint(newPosX, posY);
int saveId = canvas.save();
// translate to the correct position and draw
canvas.translate(newPosX + offset.x, posY + offset.y );
draw(canvas);
canvas.restoreToCount(saveId);
}
}

+ 10
- 0
app/src/main/res/drawable/select_statictis_time_tab_bg.xml View File

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="@color/theme_color"/>
<corners android:radius="4dp"/>
</shape>
</item>
<item android:state_selected="false" android:drawable="@color/translation"/>
</selector>

+ 64
- 0
app/src/main/res/drawable/shadow_layer.xml View File

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
/>
<solid android:color="#0DCCCCCC" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
/>
<solid android:color="#10CCCCCC" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
/>
<solid android:color="#15CCCCCC" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
/>
<solid android:color="#20CCCCCC" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#30CCCCCC" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape>
<solid android:color="#FFFFFF" />
<corners android:radius="4dp" />
</shape>
</item>
</layer-list>

+ 7
- 0
app/src/main/res/drawable/shape_cicler_6_red.xml View File

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/red_1"/>
<size android:width="6dp"
android:height="6dp"/>
</shape>

+ 5
- 0
app/src/main/res/drawable/shape_rounder_4_green_a5.xml View File

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp"/>
<solid android:color="#0D52CC52"/>
</shape>

+ 5
- 0
app/src/main/res/drawable/shape_rounder_4_purple_a5.xml View File

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp"/>
<solid android:color="#0D8757E6"/>
</shape>

+ 5
- 0
app/src/main/res/drawable/shape_rounder_4_red_a5.xml View File

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp"/>
<solid android:color="#0DF26255"/>
</shape>

+ 5
- 0
app/src/main/res/drawable/shape_rounder_4_theme_a5.xml View File

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp"/>
<solid android:color="#0D5082E6"/>
</shape>

+ 24
- 0
app/src/main/res/layout/custom_marker_view.xml View File

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shadow_layer">

<TextView
android:id="@+id/tvContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_margin="3dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingBottom="3dp"
android:elevation="4dp"
android:text="afafafa\ndada"
android:singleLine="false"
android:lineSpacingMultiplier="1.2"
android:textColor="@android:color/background_dark"
android:textSize="13sp" />


</RelativeLayout>

+ 209
- 5
app/src/main/res/layout/fragment_statics.xml View File

<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/white_1"
android:orientation="vertical"
tools:context=".module.m_statics.StaticsFragment"> tools:context=".module.m_statics.StaticsFragment">


<!-- TODO: Update blank fragment layout -->
<TextView <TextView
android:id="@+id/tv_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
android:layout_height="@dimen/title_bar_height"
android:background="@color/white"
android:gravity="center"
android:text="学习统计"
android:textColor="@color/main_text_color"
android:textSize="@dimen/bigSize"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent" />


</FrameLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_top_time"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="@dimen/global_spacing"
android:layout_marginTop="@dimen/global_spacing"
android:layout_marginEnd="@dimen/global_spacing"
app:layout_constraintDimensionRatio="h,343:275"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<!-- android:name="com.xkl.cdl.module.m_statics.StatisticsTimeTopFragment"-->

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_english"
android:layout_width="0dp"
android:layout_height="72dp"
android:layout_marginStart="@dimen/global_spacing"
android:layout_marginTop="12dp"
android:background="@drawable/shape_rounder_12_white"
app:layout_constraintEnd_toStartOf="@+id/layout_chinese"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fragment_top_time">

<ImageView
android:id="@+id/iv_english"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_english"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tv_english_"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_english"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="英语统计"
android:textColor="@color/main_text_color"
android:textSize="@dimen/normalSize"
app:layout_constraintBottom_toTopOf="@+id/tv_english_"
app:layout_constraintStart_toStartOf="@+id/tv_english_"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />

<TextView
android:id="@+id/tv_english_"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="英语课程学习情况"
android:textColor="@color/main_text_color"
android:textSize="@dimen/smallerSize"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/iv_english"
app:layout_constraintTop_toBottomOf="@+id/tv_english" />

</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_chinese"
android:layout_width="0dp"
android:layout_height="72dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="@dimen/global_spacing"
android:background="@drawable/shape_rounder_12_white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/layout_english"
app:layout_constraintTop_toTopOf="@+id/layout_english">

<ImageView
android:id="@+id/iv_chinese"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_chinese"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tv_chinese_"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_chinese"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="语文统计"
android:textColor="@color/main_text_color"
android:textSize="@dimen/normalSize"
app:layout_constraintBottom_toTopOf="@+id/tv_chinese_"
app:layout_constraintStart_toStartOf="@+id/tv_chinese_"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />

<TextView
android:id="@+id/tv_chinese_"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="语文课程学习情况"
android:textColor="@color/main_text_color"
android:textSize="@dimen/smallerSize"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/iv_chinese"
app:layout_constraintTop_toBottomOf="@+id/tv_chinese" />

</androidx.constraintlayout.widget.ConstraintLayout>


<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="@dimen/global_spacing"
android:layout_marginTop="12dp"
android:layout_marginEnd="@dimen/global_spacing"
android:background="@drawable/shape_rounder_12_white"
android:padding="12dp"
app:layout_constraintDimensionRatio="h,343:243"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/layout_english">

<TextView
android:id="@+id/chart_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已学词条数统计"
android:textColor="@color/main_text_color"
android:textSize="@dimen/bigSize"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_flag_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:drawableLeft="@drawable/shape_cicler_6_red"
android:drawablePadding="5dp"
android:drawableTint="@color/theme_color"
android:text="新学词条数"
android:textColor="#ff323233"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/chart_title"
app:layout_constraintTop_toBottomOf="@+id/chart_title" />

<TextView
android:id="@+id/tv_flag_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:drawableLeft="@drawable/shape_cicler_6_red"
android:drawablePadding="5dp"
android:text="复习词条数"
android:textColor="#ff323233"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@+id/tv_flag_1"
app:layout_constraintTop_toTopOf="@+id/tv_flag_1" />

<com.google.android.material.button.MaterialButton
android:id="@+id/tv_chart_subject_choose"
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:drawableEnd="@drawable/ic_down"
android:gravity="center"
android:insetTop="0dp"
android:insetBottom="0dp"
android:minWidth="124dp"
android:text="全部科目"
android:textColor="@color/main_text_color"
android:textSize="@dimen/smallerSize"
app:layout_constraintBottom_toBottomOf="@+id/chart_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/chart_title"
app:strokeColor="@color/gray_1"
app:strokeWidth="@dimen/line_height" />

<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_flag_1" />


</androidx.constraintlayout.widget.ConstraintLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

+ 60
- 0
app/src/main/res/layout/fragment_statistics_time_top.xml View File

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<data>

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_time"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_rounder_12_white"
android:padding="12dp">

<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:background="@drawable/shape_rounder_4_theme_a5"
app:tabIndicatorHeight="0dp"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabRippleColor="@color/translation"
app:tabTextColor="@color/gray_2"
app:tabSelectedTextColor="@color/white"
app:tabBackground="@drawable/select_statictis_time_tab_bg">
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="全部时间" />-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="今天"/>-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="本周"/>-->
<!-- <com.google.android.material.tabs.TabItem-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="本月"/>-->
</com.google.android.material.tabs.TabLayout>


<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_time"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/tab_layout_time"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:paddingEnd="12dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

+ 72
- 0
app/src/main/res/layout/item_statics_for_time.xml View File

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginStart="12dp"
>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:paddingStart="12dp"
app:layout_constraintDimensionRatio="h,154:100"
app:layout_constraintTop_toTopOf="parent">

<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="有效学习时长"
android:textColor="@color/gray_2"
android:textSize="@dimen/smallerSize"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/tv_content"
app:layout_constraintVertical_chainStyle="packed"/>

<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/main_text_color"
android:textSize="26dp"
tools:text="100"
app:layout_constraintTop_toBottomOf="@+id/tv_name"
app:layout_constraintStart_toStartOf="@+id/tv_name"
app:layout_constraintBottom_toTopOf="@+id/tv_state"/>

<TextView
android:id="@+id/tv_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/main_text_color"
android:textSize="@dimen/smallSize"
tools:text="%"
app:layout_constraintStart_toEndOf="@id/tv_content"
app:layout_constraintBaseline_toBaselineOf="@+id/tv_content"/>

<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/smallSize"
tools:drawableStart="@drawable/ic_keep"
android:gravity="center_vertical"
app:layout_constraintTop_toBottomOf="@+id/tv_content"
app:layout_constraintStart_toStartOf="@+id/tv_name"
app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

+ 23
- 0
app/src/main/res/layout/item_xpopup_statistics_choose_subject.xml View File

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:paddingTop="2dp"
android:paddingBottom="2dp">

<ImageView
android:id="@+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
/>
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/smallerSize"
android:textColor="@color/main_text_color"/>

</androidx.appcompat.widget.LinearLayoutCompat>

+ 12
- 0
app/svg/drawable/ic_chinese.xml View File

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M23.2,5.6C24.0837,5.6 24.8,6.3163 24.8,7.2L24.8,28C24.8,28.8837 24.0837,29.6 23.2,29.6L5.6,29.6C4.7163,29.6 4,28.8837 4,28L4,7.2C4,6.3163 4.7163,5.6 5.6,5.6L23.2,5.6ZM25.6,2.4C26.8781,2.4 27.9229,3.3991 27.9959,4.659L28,4.8L28,25.6C28,26.0418 27.6418,26.4 27.2,26.4C26.7897,26.4 26.4516,26.0912 26.4054,25.6933L26.4,25.6L26.4,4.8C26.4,4.3897 26.0912,4.0516 25.6933,4.0054L25.6,4L8,4C7.5582,4 7.2,3.6418 7.2,3.2C7.2,2.7897 7.5088,2.4516 7.9067,2.4054L8,2.4L25.6,2.4ZM19.6497,17.2785C18.987,17.2785 18.4497,17.8157 18.4497,18.4785L18.4497,18.4785L18.4497,24.8785L18.4552,24.994C18.5134,25.6026 19.026,26.0785 19.6497,26.0785C20.3125,26.0785 20.8497,25.5412 20.8497,24.8785L20.8497,24.8785L20.8497,18.4785L20.8442,18.3629C20.7861,17.7544 20.2735,17.2785 19.6497,17.2785ZM9.2497,18.8785C8.587,18.8785 8.0497,19.4157 8.0497,20.0785L8.0497,20.0785L8.0497,24.8785L8.0552,24.994C8.1134,25.6026 8.626,26.0785 9.2497,26.0785C9.9125,26.0785 10.4497,25.5412 10.4497,24.8785L10.4497,24.8785L10.4497,20.0785L10.4442,19.9629C10.3861,19.3544 9.8735,18.8785 9.2497,18.8785ZM14.4,20.4C13.7373,20.4 13.2,20.9373 13.2,21.6L13.2,21.6L13.2,24.8L13.2055,24.9156C13.2636,25.5241 13.7762,26 14.4,26C15.0627,26 15.6,25.4627 15.6,24.8L15.6,24.8L15.6,21.6L15.5945,21.4844C15.5364,20.8759 15.0238,20.4 14.4,20.4ZM12.7473,10.7257C12.3927,10.2278 11.7108,10.0719 11.1706,10.3838L11.1706,10.3838L7.4,12.5608L7.3027,12.6233C6.8047,12.9779 6.6489,13.6598 6.9608,14.2L6.9608,14.2L7.0233,14.2973C7.3779,14.7953 8.0598,14.9511 8.6,14.6392L8.6,14.6392L11.3318,13.0619L13.1314,16.1799L13.1939,16.2773C13.5486,16.7752 14.2304,16.9311 14.7706,16.6192L14.7706,16.6192L20.6995,13.1962L20.7968,13.1336C21.2947,12.779 21.4506,12.0971 21.1387,11.5569L21.1387,11.5569L21.0762,11.4596C20.7216,10.9617 20.0397,10.8058 19.4995,11.1177L19.4995,11.1177L14.6102,13.9403L12.8099,10.823Z"
android:strokeWidth="1"
android:fillColor="#40A540"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

+ 12
- 0
app/svg/drawable/ic_decline.xml View File

<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.4848,2C9.8698,2 10.1819,2.3058 10.1819,2.6831L10.1814,7.4649L12.8515,7.4649C13.044,7.4649 13.2,7.6179 13.2,7.8065C13.2,7.884 13.1731,7.9593 13.1236,8.0199L8.5443,13.6293C8.3038,13.9239 7.8652,13.9717 7.5645,13.736C7.5243,13.7045 7.4878,13.6687 7.4557,13.6293L2.8764,8.0199C2.7561,7.8726 2.7805,7.6576 2.9308,7.5398C2.9926,7.4913 3.0694,7.4649 3.1486,7.4649L5.8176,7.4642L5.8181,2.6831C5.8181,2.3058 6.1302,2 6.5152,2L9.4848,2Z"
android:strokeWidth="1"
android:fillColor="#F26255"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

+ 12
- 0
app/svg/drawable/ic_english.xml View File

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M23.2,5.6C24.0837,5.6 24.8,6.3163 24.8,7.2L24.8,28C24.8,28.8837 24.0837,29.6 23.2,29.6L5.6,29.6C4.7163,29.6 4,28.8837 4,28L4,7.2C4,6.3163 4.7163,5.6 5.6,5.6L23.2,5.6ZM19.9629,19.4195C19.4508,19.4195 18.9975,19.5221 18.603,19.7274C18.2649,19.9034 17.9497,20.165 17.6573,20.5121L17.6573,20.5121L17.5131,20.6928L17.5131,20.4645L17.5055,20.3014C17.4904,20.1448 17.4525,20.0077 17.392,19.8901C17.3112,19.7332 17.204,19.6156 17.0702,19.5371C16.9364,19.4587 16.7864,19.4195 16.6203,19.4195C16.3481,19.4195 16.1336,19.5083 15.9767,19.6859C15.8423,19.8382 15.7654,20.0574 15.7462,20.3435L15.7462,20.3435L15.7414,20.4922L15.7414,25.9524L15.7468,26.1053C15.7683,26.4008 15.8541,26.6335 16.0044,26.8036C16.1797,27.002 16.4035,27.1012 16.6757,27.1012C16.9571,27.1012 17.1866,27.0054 17.3643,26.814C17.5165,26.6498 17.6035,26.4154 17.6253,26.1106L17.6253,26.1106L17.6307,25.9524L17.6307,23.5856L17.6324,23.3378C17.6415,22.7012 17.6871,22.2579 17.7691,22.0077C17.8983,21.6571 18.1013,21.3814 18.3781,21.1807C18.6549,20.98 18.9617,20.8797 19.2985,20.8797C19.8153,20.8797 20.1601,21.0446 20.3331,21.3745C20.4845,21.6631 20.5697,22.0639 20.5886,22.5769L20.5886,22.5769L20.5926,22.8036L20.5926,25.9524L20.598,26.1053C20.6195,26.4008 20.7054,26.6335 20.8556,26.8036C21.0309,27.002 21.2593,27.1012 21.5407,27.1012C21.8176,27.1012 22.0425,27.0043 22.2155,26.8105C22.3638,26.6444 22.4485,26.4105 22.4697,26.1088L22.4697,26.1088L22.475,25.9524L22.475,22.4368L22.4728,22.1965C22.4669,21.888 22.4492,21.6266 22.4196,21.4126C22.3827,21.145 22.302,20.8958 22.1774,20.6652C21.9837,20.2684 21.6907,19.9616 21.2985,19.7448C20.9064,19.5279 20.4612,19.4195 19.9629,19.4195ZM13.1601,16.7828L7.7345,16.7828L7.5663,16.7879C7.3504,16.8016 7.1677,16.8426 7.0183,16.9108C6.8314,16.9962 6.6941,17.1323 6.6065,17.3191C6.5364,17.4686 6.4943,17.6528 6.4803,17.8717L6.4803,17.8717L6.475,18.0423L6.475,25.6686L6.4796,25.829C6.501,26.1898 6.5975,26.457 6.7691,26.6306C6.9407,26.8041 7.2085,26.9018 7.5726,26.9235L7.5726,26.9235L7.7345,26.9281L13.3193,26.9281L13.4741,26.9219C13.7212,26.9011 13.9129,26.8282 14.0494,26.7032C14.2132,26.5533 14.2951,26.3584 14.2951,26.1185C14.2951,25.8693 14.2132,25.6698 14.0494,25.5198C13.9129,25.3949 13.7212,25.322 13.4741,25.3012L13.4741,25.3012L13.3193,25.2949L8.5304,25.2949L8.5304,22.4091L12.7933,22.4091L12.9456,22.4031C13.1878,22.3829 13.3723,22.3122 13.4992,22.1911C13.6515,22.0458 13.7276,21.8578 13.7276,21.6271C13.7276,21.3964 13.6503,21.2107 13.4958,21.07C13.367,20.9527 13.1829,20.8843 12.9436,20.8648L12.9436,20.8648L12.7933,20.8589L8.5304,20.8589L8.5304,18.3676L13.1601,18.3676L13.3169,18.3615C13.5665,18.3413 13.7576,18.2707 13.8902,18.1496C14.0494,18.0043 14.129,17.8116 14.129,17.5717C14.129,17.3364 14.0494,17.1461 13.8902,17.0008C13.7576,16.8797 13.5665,16.8091 13.3169,16.7889L13.3169,16.7889L13.1601,16.7828ZM25.6,2.4C26.8781,2.4 27.9229,3.3991 27.9959,4.659L28,4.8L28,25.6C28,26.0418 27.6418,26.4 27.2,26.4C26.7897,26.4 26.4516,26.0912 26.4054,25.6933L26.4,25.6L26.4,4.8C26.4,4.3897 26.0912,4.0516 25.6933,4.0054L25.6,4L8,4C7.5582,4 7.2,3.6418 7.2,3.2C7.2,2.7897 7.5088,2.4516 7.9067,2.4054L8,2.4L25.6,2.4ZM12.9736,9.1445C12.7347,8.823 12.2874,8.7247 11.9321,8.9298L11.9321,8.9298L6.5646,12.0287L6.4865,12.08C6.1651,12.319 6.0667,12.7662 6.2718,13.1215L6.2718,13.1215L6.3231,13.1996C6.5621,13.5211 7.0093,13.6195 7.3646,13.4144L7.3646,13.4144L12.0391,10.7156L14.0393,14.1795L14.0906,14.2576C14.3296,14.5791 14.7768,14.6775 15.1321,14.4724L15.1321,14.4724L22.2354,10.3713L22.3135,10.32C22.6349,10.081 22.7333,9.6338 22.5282,9.2785L22.5282,9.2785L22.4769,9.2004C22.2379,8.8789 21.7907,8.7805 21.4354,8.9856L21.4354,8.9856L15.0247,12.6868L13.0249,9.2226Z"
android:strokeWidth="1"
android:fillColor="#F7874F"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

+ 12
- 0
app/svg/drawable/ic_keep.xml View File

<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="M4.8,7.2L11.2,7.2A0.8,0.8 0,0 1,12 8L12,8A0.8,0.8 0,0 1,11.2 8.8L4.8,8.8A0.8,0.8 0,0 1,4 8L4,8A0.8,0.8 0,0 1,4.8 7.2z"
android:strokeWidth="1"
android:fillColor="#40A540"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

+ 12
- 0
app/svg/drawable/ic_rise.xml View File

<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.4848,13.8857C9.8698,13.8857 10.1819,13.5799 10.1819,13.2026L10.1814,8.4208L12.8515,8.4208C13.044,8.4208 13.2,8.2679 13.2,8.0792C13.2,8.0017 13.1731,7.9264 13.1236,7.8659L8.5443,2.2564C8.3038,1.9618 7.8652,1.914 7.5645,2.1497C7.5243,2.1812 7.4878,2.217 7.4557,2.2564L2.8764,7.8659C2.7561,8.0132 2.7805,8.2281 2.9308,8.3459C2.9926,8.3944 3.0694,8.4208 3.1486,8.4208L5.8176,8.4215L5.8181,13.2026C5.8181,13.5799 6.1302,13.8857 6.5152,13.8857L9.4848,13.8857Z"
android:strokeWidth="1"
android:fillColor="#40A540"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>

+ 3
- 1
build.gradle View File

//精美日历 calendarview https://github.com/huanghaibin-dev/CalendarView //精美日历 calendarview https://github.com/huanghaibin-dev/CalendarView
CalendarView : "com.haibin:calendarview:3.7.1", CalendarView : "com.haibin:calendarview:3.7.1",
//google 流式布局 https://blog.csdn.net/ww897532167/article/details/85952498 https://github.com/google/flexbox-layout //google 流式布局 https://blog.csdn.net/ww897532167/article/details/85952498 https://github.com/google/flexbox-layout
FlexBoxLayoutManager : "com.google.android.flexbox:flexbox:3.0.0"
FlexBoxLayoutManager : "com.google.android.flexbox:flexbox:3.0.0",
//图表
Chart: "com.github.PhilJay:MPAndroidChart:v3.1.0"
] ]





+ 1
- 1
lib/common/build.gradle View File

} }
debug { debug {
buildConfigField("Boolean","LOG_ENABLE","true") buildConfigField("Boolean","LOG_ENABLE","true")
buildConfigField("Boolean","SHOW_LIFECYCLER_LOG","false")
buildConfigField("Boolean","SHOW_LIFECYCLER_LOG","true")
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }

+ 16
- 1
lib/common/src/main/java/com/suliang/common/widget/NumberUtils.kt View File

* 小数: n个0,保留n位小数,不足部分,0填充 * 小数: n个0,保留n位小数,不足部分,0填充
* *
* @param value Double 格式化的数字 * @param value Double 格式化的数字
* @param format String 格式化格式
* @param format String 格式化格式 例0.0
* @return String 返回字符串内容 * @return String 返回字符串内容
*/ */
@JvmStatic @JvmStatic
roundingMode = RoundingMode.HALF_UP roundingMode = RoundingMode.HALF_UP
}.format(value) }.format(value)
} }
/**
* 数字格式化 舍弃模式,相当于直接截取
* 整数 : 0 有值为原来的值,没有值以0填充,如果是#则为原来的数值
* 小数: n个0,保留n位小数,不足部分,0填充
*
* @param value Double 格式化的数字
* @param format String 格式化格式 例0.0
* @return String 返回字符串内容
*/
fun formatFloor(value:Double,format : String): String{
return DecimalFormat(format).apply {
roundingMode = RoundingMode.FLOOR
}.format(value)
}
} }
} }

Loading…
Cancel
Save