<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" /> |
implementation customDependencies.CalendarView | implementation customDependencies.CalendarView | ||||
// FlexBoxLayoutManager | // FlexBoxLayoutManager | ||||
implementation customDependencies.FlexBoxLayoutManager | implementation customDependencies.FlexBoxLayoutManager | ||||
//图标 | |||||
implementation customDependencies.Chart | |||||
} | } |
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) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
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 //背景 | |||||
} |
return false | return false | ||||
} | } | ||||
/** 获取课程的数量 */ | |||||
fun getTotalCourseSize() : Int { | |||||
var result = 0 | |||||
subjectWithCoursePackMap.forEach { entry -> | |||||
entry.value.forEach { coursePack -> | |||||
result += coursePack.childrenCourses.size | |||||
} | |||||
} | |||||
return result | |||||
} | |||||
} | } |
} | } | ||||
} | } | ||||
/** 获取词条数统计 */ | |||||
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() | |||||
} | |||||
} | |||||
} | } |
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>" | |||||
} | } | ||||
} | } | ||||
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 | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
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 "" | |||||
} | |||||
} |
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("") | |||||
} | |||||
}) | |||||
} | |||||
} | |||||
} |
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); | |||||
} | |||||
} |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<?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> |
<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> |
<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> |
<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> |
<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> |
<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> |
//精美日历 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" | |||||
] | ] | ||||
} | } | ||||
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' | ||||
} | } |
* 小数: 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) | |||||
} | |||||
} | } | ||||
} | } |