@@ -33,10 +33,17 @@ | |||
<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_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_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_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_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_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" /> | |||
@@ -49,6 +56,7 @@ | |||
<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/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_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" /> | |||
@@ -73,6 +81,7 @@ | |||
<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/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_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" /> | |||
@@ -89,6 +98,8 @@ | |||
<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_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_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" /> | |||
@@ -120,11 +131,13 @@ | |||
<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_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_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_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_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_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" /> | |||
@@ -132,6 +145,7 @@ | |||
<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/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_only.xml" value="0.49773550724637683" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/statedrawable/drawable/ic_nav_learn_center.xml" value="0.44166666666666665" /> | |||
@@ -146,6 +160,7 @@ | |||
<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_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_icon___.xml" value="0.287962962962963" /> | |||
<entry key="..\:/Work/XKL/XKL/XklLocal/app/svg/drawable/ic_menu.xml" value="0.4036458333333333" /> |
@@ -119,6 +119,8 @@ dependencies { | |||
implementation customDependencies.CalendarView | |||
// FlexBoxLayoutManager | |||
implementation customDependencies.FlexBoxLayoutManager | |||
//图标 | |||
implementation customDependencies.Chart | |||
} |
@@ -0,0 +1,40 @@ | |||
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) | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
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 //背景 | |||
} |
@@ -449,4 +449,15 @@ object CourseManager { | |||
return false | |||
} | |||
/** 获取课程的数量 */ | |||
fun getTotalCourseSize() : Int { | |||
var result = 0 | |||
subjectWithCoursePackMap.forEach { entry -> | |||
entry.value.forEach { coursePack -> | |||
result += coursePack.childrenCourses.size | |||
} | |||
} | |||
return result | |||
} | |||
} |
@@ -206,4 +206,15 @@ object DataRepository { | |||
} | |||
} | |||
/** 获取词条数统计 */ | |||
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() | |||
} | |||
} | |||
} |
@@ -59,7 +59,7 @@ class TestDetailActivity : BaseActivityVM<ActivityTestDetailBinding,TestDetailVi | |||
private fun initScore():String{ | |||
return when(vm.courseType){ | |||
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>" | |||
} | |||
} | |||
@@ -1,72 +1,287 @@ | |||
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.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.extension.click | |||
import com.suliang.common.extension.loadFragment | |||
import com.suliang.common.extension.setHtml | |||
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.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 { | |||
/** | |||
* 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 | |||
fun newInstance() = StaticsFragment() | |||
} | |||
override fun initViewModel() : StaticsFragmentViewModel { | |||
return ViewModelProvider(this)[StaticsFragmentViewModel::class.java] | |||
} | |||
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() { | |||
//监听图表项目切换变化 | |||
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 | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,302 @@ | |||
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 "" | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
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("") | |||
} | |||
}) | |||
} | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
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); | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
<?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> |
@@ -0,0 +1,64 @@ | |||
<?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> |
@@ -0,0 +1,7 @@ | |||
<?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> |
@@ -0,0 +1,5 @@ | |||
<?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> |
@@ -0,0 +1,5 @@ | |||
<?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> |
@@ -0,0 +1,5 @@ | |||
<?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> |
@@ -0,0 +1,5 @@ | |||
<?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> |
@@ -0,0 +1,24 @@ | |||
<?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> |
@@ -1,14 +1,218 @@ | |||
<?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" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:background="@color/white_1" | |||
android:orientation="vertical" | |||
tools:context=".module.m_statics.StaticsFragment"> | |||
<!-- TODO: Update blank fragment layout --> | |||
<TextView | |||
android:id="@+id/tv_title" | |||
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> |
@@ -0,0 +1,60 @@ | |||
<?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> |
@@ -0,0 +1,72 @@ | |||
<?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> |
@@ -0,0 +1,23 @@ | |||
<?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> |
@@ -0,0 +1,12 @@ | |||
<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> |
@@ -0,0 +1,12 @@ | |||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:width="16dp" | |||
android:height="16dp" | |||
android:viewportWidth="16" | |||
android:viewportHeight="16"> | |||
<path | |||
android:pathData="M9.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> |
@@ -0,0 +1,12 @@ | |||
<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> |
@@ -0,0 +1,12 @@ | |||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:width="16dp" | |||
android:height="16dp" | |||
android:viewportWidth="16" | |||
android:viewportHeight="16"> | |||
<path | |||
android:pathData="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> |
@@ -0,0 +1,12 @@ | |||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:width="16dp" | |||
android:height="16dp" | |||
android:viewportWidth="16" | |||
android:viewportHeight="16"> | |||
<path | |||
android:pathData="M9.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> |
@@ -110,7 +110,9 @@ ext { | |||
//精美日历 calendarview https://github.com/huanghaibin-dev/CalendarView | |||
CalendarView : "com.haibin:calendarview:3.7.1", | |||
//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" | |||
] | |||
@@ -26,7 +26,7 @@ android { | |||
} | |||
debug { | |||
buildConfigField("Boolean","LOG_ENABLE","true") | |||
buildConfigField("Boolean","SHOW_LIFECYCLER_LOG","false") | |||
buildConfigField("Boolean","SHOW_LIFECYCLER_LOG","true") | |||
minifyEnabled false | |||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | |||
} |
@@ -18,7 +18,7 @@ class NumberUtils { | |||
* 小数: n个0,保留n位小数,不足部分,0填充 | |||
* | |||
* @param value Double 格式化的数字 | |||
* @param format String 格式化格式 | |||
* @param format String 格式化格式 例0.0 | |||
* @return String 返回字符串内容 | |||
*/ | |||
@JvmStatic | |||
@@ -27,5 +27,20 @@ class NumberUtils { | |||
roundingMode = RoundingMode.HALF_UP | |||
}.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) | |||
} | |||
} | |||
} |