Commit c694ab53aacd2776649e37019ef596f067822f87

Authored by shixianjie
1 parent ea57c8d609
Exists in master

周报详情展示

Showing 41 changed files with 4343 additions and 2 deletions   Show diff stats
... ... @@ -23,7 +23,7 @@ android {
23 23  
24 24 defaultConfig {
25 25 applicationId "com.hjx.parent"
26   - minSdk 24
  26 + minSdk 26
27 27 targetSdk 32
28 28 versionCode 1005
29 29 versionName "1.0.0.5"
... ...
app/src/main/AndroidManifest.xml
... ... @@ -157,6 +157,7 @@
157 157 <activity android:name=".HomeworkFeedbackActivity" />
158 158 <activity android:name=".HomeworkTopicActivity" />
159 159 <activity android:name=".HomeworkShareActivity" />
  160 + <activity android:name=".HuyouDetailActivity" />
160 161  
161 162 <provider
162 163 android:name="androidx.core.content.FileProvider"
... ...
app/src/main/java/com/hjx/parent/HuyouDetailActivity.java
... ... @@ -0,0 +1,421 @@
  1 +package com.hjx.parent;
  2 +
  3 +
  4 +import android.annotation.SuppressLint;
  5 +import android.content.Intent;
  6 +import android.content.res.ColorStateList;
  7 +import android.graphics.Bitmap;
  8 +import android.net.Uri;
  9 +import android.os.Bundle;
  10 +import android.text.Html;
  11 +import android.view.View;
  12 +import android.widget.TextView;
  13 +
  14 +import androidx.annotation.NonNull;
  15 +import androidx.annotation.Nullable;
  16 +import androidx.core.content.res.ResourcesCompat;
  17 +
  18 +import com.bumptech.glide.Glide;
  19 +import com.chad.library.adapter.base.BaseQuickAdapter;
  20 +import com.chad.library.adapter.base.BaseViewHolder;
  21 +import com.github.mikephil.charting.components.Legend;
  22 +import com.github.mikephil.charting.components.XAxis;
  23 +import com.github.mikephil.charting.components.YAxis;
  24 +import com.github.mikephil.charting.data.Entry;
  25 +import com.github.mikephil.charting.data.LineData;
  26 +import com.github.mikephil.charting.data.LineDataSet;
  27 +import com.github.mikephil.charting.formatter.ValueFormatter;
  28 +import com.hjx.parent.databinding.ActivityHuyouDetailBinding;
  29 +import com.hjx.parent.rx.BaseRxActivity;
  30 +import com.prws.common.bean.Student;
  31 +import com.prws.common.bean.homework.StDetail;
  32 +import com.prws.common.net.NetWorks;
  33 +import com.prws.common.utils.BitmapUtils;
  34 +import com.prws.common.utils.ContentUtil;
  35 +import com.trello.rxlifecycle2.android.RxLifecycleAndroid;
  36 +
  37 +import java.text.DecimalFormat;
  38 +import java.text.SimpleDateFormat;
  39 +import java.util.ArrayList;
  40 +import java.util.Date;
  41 +import java.util.List;
  42 +import java.util.Locale;
  43 +import java.util.TimeZone;
  44 +
  45 +import io.reactivex.android.schedulers.AndroidSchedulers;
  46 +import io.reactivex.schedulers.Schedulers;
  47 +
  48 +public class HuyouDetailActivity extends BaseRxActivity<ActivityHuyouDetailBinding> {
  49 +
  50 + private String id;
  51 + private int type; // 0:周 1:阶段
  52 + private Student student;
  53 +
  54 + private StDetail mData;
  55 +
  56 + final String indent = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
  57 +
  58 + private boolean a4 = false;
  59 +
  60 + @Override
  61 + protected void onResume() {
  62 + super.onResume();
  63 + binding.root.postDelayed(() -> {
  64 + float scale = 1f * binding.getRoot().getWidth() / binding.root.getWidth();
  65 + if (scale >= 1) return;
  66 + binding.root.setScaleX(scale);
  67 + binding.root.setScaleY(scale);
  68 + }, 100);
  69 + }
  70 +
  71 + @SuppressLint("CheckResult")
  72 + @Override
  73 + public void initView(Bundle savedInstanceState) {
  74 + id = getIntent().getStringExtra("id");
  75 + type = getIntent().getIntExtra("type", 0);
  76 + student = (Student) getIntent().getSerializableExtra("student");
  77 +
  78 + if (type == 1) binding.tvTitle.setText("阶段作业学习总结");
  79 +
  80 + Glide.with(this).load(student.photo).into(binding.ivAvatar);
  81 + binding.tvStuName.setText(student.stuName);
  82 +
  83 + setupChart();
  84 + NetWorks.service_url.getHuyouDetail(NetWorks.getHeader(), id)
  85 + .subscribeOn(Schedulers.io())
  86 + .map(response -> response.getData())
  87 + .map(data -> {
  88 + if (type == 1) data.formatCollection();
  89 + return data;
  90 + })
  91 + .observeOn(AndroidSchedulers.mainThread())
  92 + .compose(RxLifecycleAndroid.bindActivity(getRxLifecycle()))
  93 + .subscribe((data, th) -> {
  94 + mData = data;
  95 + if (th != null) th.printStackTrace();
  96 + if (data != null) showData(data);
  97 + });
  98 +
  99 + binding.btnShare.setOnClickListener(v -> {
  100 + Uri shareUri = prepareShare();
  101 + if (shareUri != null) {
  102 + Intent shareIntent = new Intent(Intent.ACTION_SEND);
  103 + shareIntent.setType("image/jpeg");
  104 + shareIntent.putExtra(Intent.EXTRA_STREAM, shareUri);
  105 + shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  106 +
  107 + startActivity(shareIntent);
  108 + }
  109 + });
  110 +
  111 + binding.btnSwitch.setOnClickListener(v -> {
  112 + switchPage();
  113 + });
  114 +
  115 + }
  116 +
  117 + private SimpleDateFormat getFormatWithGmt8(String pattern) {
  118 + SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.CHINA);
  119 + format.setTimeZone(TimeZone.getTimeZone("GMT+16"));
  120 + return format;
  121 + }
  122 +
  123 + @SuppressLint("SetTextI18n")
  124 + private void showData(StDetail data) {
  125 + binding.tvGrade.setText(data.grade);
  126 + binding.tvSubject.setText(data.homeworkSubject);
  127 + String start = getFormatWithGmt8("yyyy.M.d").format(data.startTime);
  128 + String end = new SimpleDateFormat(" - M.d", Locale.CHINA).format(data.endTime);
  129 + binding.tvDate.setText(start + end);
  130 +
  131 + if (data.points == null) data.points = new ArrayList<>();
  132 + if (data.points.size() == 0) {
  133 + binding.cpBefore.setValue(0);
  134 + binding.cpAfter.setValue(0);
  135 + binding.pgBefore.setText("0");
  136 + binding.pgAfter.setText("0");
  137 + } else {
  138 + float before = 0;
  139 + float after = 0;
  140 + for (StDetail.Point point: data.points) {
  141 + before += point.beforeState;
  142 + after += point.afterState;
  143 + }
  144 + before = (int) (100f * before / data.points.size() + 0.5f);
  145 + after = (int) (100f * after / data.points.size() + 0.5f);
  146 + binding.cpBefore.setValue(before);
  147 + binding.cpAfter.setValue(after);
  148 + DecimalFormat format = new DecimalFormat("0");
  149 + binding.pgBefore.setText(format.format(before));
  150 + binding.pgAfter.setText(format.format(after));
  151 +
  152 + String comment;
  153 + if (after >= 90) {
  154 + comment = "知识点掌握的比较扎实,多练习多巩固掌握一般的知识点会有很大帮助。";
  155 + } else if (after >= 80) {
  156 + comment = "知识点掌握程度有进步,还要再继续学习,多练习,不断巩固。";
  157 + } else if (after >= 60) {
  158 + comment = "薄弱知识点还有进步空间,再多做一些类似题目来巩固知识点,继续努力。";
  159 + } else {
  160 + comment = "你的薄弱知识点还需要再深入了解,有不清楚的地方及时问老师,继续加油。";
  161 + }
  162 + String percent = new DecimalFormat("0%").format(after / 100);
  163 + String temp = indent + "通过学习,你的薄弱知识点掌握程度为 %s," + comment;
  164 + temp = String.format(temp, fromColor(percent, "#F24E38"));
  165 + binding.tvWeakRate.setText(Html.fromHtml(temp, Html.FROM_HTML_MODE_COMPACT));
  166 + }
  167 +
  168 + binding.tvTotalRate.setText(new DecimalFormat("0").format(100f * data.correct / data.total));
  169 + binding.tvTotalCorrect.setText(String.valueOf(data.correct));
  170 + binding.tvTotalError.setText(String.valueOf(data.total - data.correct));
  171 + if (data.total == 0) {
  172 + binding.tvRating.setText("");
  173 + } else {
  174 + float rate = 100f * data.correct / data.total;
  175 + String comment;
  176 + if (rate >= 90) {
  177 + comment = "掌握程度比较优秀,你对知识的理解和运用能力非常强,这是你努力的结果。请继续保持这份优秀,在未来的学习中,可以继续挑战更难的题目,勇攀高峰。";
  178 + } else if (rate >= 80) {
  179 + comment = "掌握良好。接下来,跟随老师的学习规划,针对薄弱环节重点突破。加油,只要持之以恒,坚持下去,你一定会更加出色。";
  180 + } else if (rate >= 60) {
  181 + comment = "掌握程度一般。不过别灰心,你有提升的潜力。跟随老师的步伐,制定合理的学习计划,多做一些练习题来巩固知识。老师相信你一定可以做到。";
  182 + } else {
  183 + comment = "掌握程度较为薄弱。但不要放弃,这正是你奋起直追的好时机。认真分析自己的问题,从基础开始逐步提升。老师会一直支持你,只要你有决心,就没有克服不了的困难。";
  184 + }
  185 + String rateStr = new DecimalFormat("0%").format(rate / 100f);
  186 + String temp;
  187 + if (type == 0) {
  188 + temp = indent + "在本周作业中,你的综合正确率是 %s," + comment;
  189 + } else {
  190 + temp = indent + "你的综合正确率是 %s," + comment;
  191 + }
  192 + temp = String.format(temp, fromColor(rateStr, "#3BC3B6"));
  193 + binding.tvRating.setText(Html.fromHtml(temp, Html.FROM_HTML_MODE_COMPACT));
  194 + }
  195 +
  196 + List<Entry> entries = new ArrayList<>();
  197 + if (type == 0) {
  198 + entries.add(new Entry(1, data.mondayCorrection));
  199 + entries.add(new Entry(2, data.tuesdayCorrection));
  200 + entries.add(new Entry(3, data.wednesdayCorrection));
  201 + entries.add(new Entry(4, data.thursdayCorrection));
  202 + entries.add(new Entry(5, data.fridayCorrection));
  203 + } else {
  204 + for (int i = 0; i < data.correctionList.size(); i ++) {
  205 + StDetail.Correction c = data.correctionList.get(i);
  206 + entries.add(new Entry(i, c.correction));
  207 + }
  208 + XAxis xAxis = binding.lineChart.getXAxis();
  209 + xAxis.setLabelCount(Math.min(entries.size(), 5), true);
  210 + xAxis.setValueFormatter(new ValueFormatter() {
  211 + SimpleDateFormat format = new SimpleDateFormat("M.d", Locale.CHINA);
  212 + @Override
  213 + public String getFormattedValue(float value) {
  214 + int index = (int) value;
  215 + if (index < 0 || index >= data.correctionList.size()) return "";
  216 + Date date = data.correctionList.get(index).date;
  217 + return format.format(date);
  218 + }
  219 + });
  220 + }
  221 +
  222 + LineDataSet set = new LineDataSet(entries, "");
  223 + set.setColor(0xFF3BC3B6);
  224 + set.setCircleColor(0xFF3BC3B6);
  225 + set.setDrawFilled(true);
  226 + set.setDrawCircles(type == 0 || entries.size() == 1);
  227 + set.setDrawValues(false);
  228 + set.setHighlightEnabled(false);
  229 + set.setDrawHighlightIndicators(false);
  230 + set.setFillDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.bg_line_chart_fill2, null));
  231 + binding.lineChart.setData(new LineData(set));
  232 + binding.lineChart.invalidate();
  233 +
  234 + if (!data.points.isEmpty()) {
  235 + int exNo = 0, goodNo = 0, normalNo = 0, weakNo = 0;
  236 + float total = 0;
  237 + for (StDetail.Point point: data.points) {
  238 + total += point.afterState;
  239 + if (point.afterState >= 0.9) {
  240 + exNo ++;
  241 + } else if (point.afterState >= 0.8) {
  242 + goodNo ++;
  243 + } else if (point.afterState >= 0.6) {
  244 + normalNo ++;
  245 + } else {
  246 + weakNo ++;
  247 + }
  248 + }
  249 + binding.tvExcellent.setText(String.valueOf(exNo));
  250 + binding.tvGood.setText(String.valueOf(goodNo));
  251 + binding.tvNormal.setText(String.valueOf(normalNo));
  252 + binding.tvWeak.setText(String.valueOf(weakNo));
  253 +
  254 + float exRate = 100f * exNo / data.points.size();
  255 + float goodRate = 100f * goodNo / data.points.size();
  256 + float normalRate = 100f * normalNo / data.points.size();
  257 + float weakRate = 100f * weakNo / data.points.size();
  258 + binding.cpGood.setValue(goodRate + normalRate + weakRate);
  259 + binding.cpNormal.setValue(normalRate + weakRate);
  260 + binding.cpWeak.setValue(weakRate);
  261 + binding.tvAvePoint.setText(new DecimalFormat("0").format(100f * total / data.points.size()));
  262 + }
  263 +
  264 + List<StDetail.Point> points = new ArrayList<>();
  265 + for (StDetail.Point point: data.points) {
  266 + if (point.beforeState < 1) points.add(point);
  267 + }
  268 + binding.tableRoot.setClipToOutline(true);
  269 + binding.rvPoint.setAdapter(new Adapter(points));
  270 + binding.tableRoot.setVisibility(points.isEmpty() ? View.GONE : View.VISIBLE);
  271 + binding.flPointDesc.setVisibility(points.isEmpty() ? View.GONE : View.VISIBLE);
  272 + binding.flEmptyPoints.setVisibility(points.isEmpty() ? View.VISIBLE : View.GONE);
  273 + }
  274 +
  275 + private void setupChart() {
  276 + binding.lineChart.getLegend().setForm(Legend.LegendForm.NONE);
  277 + binding.lineChart.setScaleEnabled(false);
  278 + binding.lineChart.setTouchEnabled(false);
  279 + binding.lineChart.setDescription(null);
  280 + binding.lineChart.getAxisRight().setEnabled(false);
  281 + YAxis yAxis = binding.lineChart.getAxisLeft();
  282 + yAxis.setDrawAxisLine(false);
  283 + yAxis.setDrawGridLines(true);
  284 + yAxis.setGridColor(0xFFDDDDDD);
  285 + yAxis.setTextColor(0xFF333333);
  286 + if (type == 0) {
  287 + yAxis.setTextSize(16);
  288 + yAxis.setXOffset(16);
  289 + } else {
  290 + yAxis.setTextSize(13);
  291 + }
  292 + yAxis.setAxisMinimum(0);
  293 + yAxis.setAxisMaximum(1);
  294 + yAxis.setLabelCount(5, true);
  295 + yAxis.setValueFormatter(new ValueFormatter() {
  296 + @Override
  297 + public String getFormattedValue(float value) {
  298 + return new DecimalFormat("0%").format(value);
  299 + }
  300 + });
  301 +
  302 + XAxis xAxis = binding.lineChart.getXAxis();
  303 + xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
  304 + xAxis.setDrawAxisLine(false);
  305 + xAxis.setDrawGridLines(false);
  306 + xAxis.setTextColor(0xFF333333);
  307 + xAxis.setTextSize(16);
  308 + xAxis.setYOffset(16);
  309 + if (type == 0) {
  310 + xAxis.setAxisMinimum(0.5f);
  311 + xAxis.setAxisMaximum(5.5f);
  312 + xAxis.setLabelCount(11, true);
  313 + xAxis.setValueFormatter(new ValueFormatter() {
  314 + @Override
  315 + public String getFormattedValue(float value) {
  316 + if (value == 1) {
  317 + return "周一";
  318 + } else if (value == 2) {
  319 + return "周二";
  320 + } else if (value == 3) {
  321 + return "周三";
  322 + } else if (value == 4) {
  323 + return "周四";
  324 + } else if (value == 5) {
  325 + return "周五";
  326 + }
  327 + return "";
  328 + }
  329 + });
  330 + } else {
  331 + xAxis.setTextSize(13);
  332 + }
  333 + }
  334 +
  335 + private String fromColor(String str, String color) {
  336 + return String.format("<font color='%s'><b>%s</b></font>", color, str);
  337 + }
  338 +
  339 + private void switchPage() {
  340 + Intent intent = new Intent(getIntent());
  341 + intent.putExtra("a4", !a4);
  342 + startActivity(intent);
  343 + finish();
  344 + }
  345 +
  346 + private Uri prepareShare() {
  347 + try {
  348 + binding.toolbar.setVisibility(View.INVISIBLE);
  349 + Bitmap bitmap = BitmapUtils.shotView(binding.root);
  350 + binding.toolbar.setVisibility(View.VISIBLE);
  351 +
  352 + String fileName = student.stuName + "_周作业学习报告_" + System.currentTimeMillis();
  353 + return ContentUtil.saveBitmapToGallery(this, bitmap, fileName);
  354 + } catch (Exception e) {
  355 + e.printStackTrace();
  356 + }
  357 + return null;
  358 + }
  359 +
  360 + @Override
  361 + protected ActivityHuyouDetailBinding getViewBinding() {
  362 + a4 = getIntent().getBooleanExtra("a4", false);
  363 + View view;
  364 + if (a4) view = getLayoutInflater().inflate(R.layout.activity_huyou_detail_a4, null);
  365 + else view = getLayoutInflater().inflate(R.layout.activity_huyou_detail, null);
  366 + return ActivityHuyouDetailBinding.bind(view);
  367 + }
  368 +
  369 + public static class Adapter extends BaseQuickAdapter<StDetail.Point, BaseViewHolder> {
  370 +
  371 + public Adapter(@Nullable List<StDetail.Point> data) {
  372 + super(R.layout.item_huyou_point, data);
  373 + }
  374 +
  375 + @Override
  376 + protected void convert(@NonNull BaseViewHolder holder, StDetail.Point point) {
  377 + DecimalFormat format1 = new DecimalFormat("0%");
  378 + DecimalFormat format2 = new DecimalFormat("0");
  379 + holder.setText(R.id.tvName, point.pointName);
  380 + holder.setText(R.id.tvBefore, format1.format(point.beforeState));
  381 + holder.setText(R.id.tvAfter, format1.format(point.afterState));
  382 + holder.setText(R.id.tvGap, format2.format(point.gap * 100));
  383 + holder.setGone(R.id.ivFlag, getData().indexOf(point) == 0);
  384 + holder.<TextView>getView(R.id.tvName).setTooltipText(point.pointName);
  385 +
  386 + TextView before = holder.getView(R.id.tvBeforeState);
  387 + TextView after = holder.getView(R.id.tvAfterState);
  388 +
  389 + if (point.beforeState >= 0.9) {
  390 + before.setText("掌握优秀");
  391 + before.setBackgroundTintList(ColorStateList.valueOf(0xFF4FBB7A));
  392 + } else if (point.beforeState >= 0.8) {
  393 + before.setText("掌握良好");
  394 + before.setBackgroundTintList(ColorStateList.valueOf(0xFF489AFA));
  395 + } else if (point.beforeState >= 0.6) {
  396 + before.setText("掌握一般");
  397 + before.setBackgroundTintList(ColorStateList.valueOf(0xFFF58725));
  398 + } else {
  399 + before.setText("掌握薄弱");
  400 + before.setBackgroundTintList(ColorStateList.valueOf(0xFFEA5127));
  401 + }
  402 + if (point.afterState >= 0.9) {
  403 + after.setText("掌握优秀");
  404 + after.setBackgroundTintList(ColorStateList.valueOf(0xFF4FBB7A));
  405 + } else if (point.afterState >= 0.8) {
  406 + after.setText("掌握良好");
  407 + after.setBackgroundTintList(ColorStateList.valueOf(0xFF489AFA));
  408 + } else if (point.afterState >= 0.6) {
  409 + after.setText("掌握一般");
  410 + after.setBackgroundTintList(ColorStateList.valueOf(0xFFF58725));
  411 + } else {
  412 + after.setText("掌握薄弱");
  413 + after.setBackgroundTintList(ColorStateList.valueOf(0xFFEA5127));
  414 + }
  415 +
  416 + holder.setText(R.id.tvHuyou, format1.format(point.correctness));
  417 + }
  418 +
  419 + }
  420 +
  421 +}
... ...
app/src/main/java/com/hjx/parent/StuHomeworkActivity.java
... ... @@ -131,10 +131,21 @@ public class StuHomeworkActivity extends BaseRxActivity&lt;ActivityStudentHomeworkB
131 131 stageHuyouDialog.show(this::generalStage);
132 132 });
133 133  
  134 + weekAdapter.detailCall = data -> goHuyou(data, 0);
  135 + stageAdapter.detailCall = data -> goHuyou(data, 1);
  136 +
134 137 getWeekHuyou();
135 138 getStageHuyou();
136 139 }
137 140  
  141 + private void goHuyou(StDetail data, int type) {
  142 + Intent intent = new Intent(this, HuyouDetailActivity.class);
  143 + intent.putExtra("id", data.id);
  144 + intent.putExtra("type", type);
  145 + intent.putExtra("student", state.student);
  146 + startActivity(intent);
  147 + }
  148 +
138 149 @Override
139 150 protected void onStart() {
140 151 super.onStart();
... ... @@ -422,6 +433,7 @@ public class StuHomeworkActivity extends BaseRxActivity&lt;ActivityStudentHomeworkB
422 433  
423 434 static class HuyouAdapter extends BaseQuickAdapter<StDetail, BaseViewHolder> {
424 435 public Function1<StDetail> deleteCall;
  436 + public Function1<StDetail> detailCall;
425 437 public Student student;
426 438  
427 439 public HuyouAdapter(@Nullable List<StDetail> data) {
... ... @@ -458,6 +470,14 @@ public class StuHomeworkActivity extends BaseRxActivity&lt;ActivityStudentHomeworkB
458 470 String title = startStr + endStr + data.homeworkSubject + typeStr;
459 471 holder.setText(R.id.tvName, title);
460 472 holder.setText(R.id.tvGrade, data.grade);
  473 + View btnDelete = holder.getView(R.id.btnDelete);
  474 + View btnDetail = holder.getView(R.id.btnDetail);
  475 + btnDelete.setOnClickListener(v -> {
  476 + if (deleteCall != null) deleteCall.invoke(data);
  477 + });
  478 + btnDetail.setOnClickListener(v -> {
  479 + if (detailCall != null) detailCall.invoke(data);
  480 + });
461 481 }
462 482  
463 483 private SimpleDateFormat getFormatWithGmt8(String pattern) {
... ...
app/src/main/res/drawable/bg_circle.xml
... ... @@ -0,0 +1,4 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <corners android:radius="888dp"/>
  4 +</shape>
0 5 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_huyou_a4.xml
... ... @@ -0,0 +1,12 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item>
  5 + <color android:color="#CEF1EC"/>
  6 + </item>
  7 +
  8 + <item android:width="104dp" android:height="66dp"
  9 + android:start="30dp" android:top="-16dp"
  10 + android:drawable="@drawable/png_huyou_logo"/>
  11 +
  12 +</layer-list>
0 13 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_huyou_table_bg.xml
... ... @@ -0,0 +1,7 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <corners android:radius="10dp"/>
  5 + <stroke android:color="#50CEC2" android:width="1dp"/>
  6 +
  7 +</shape>
0 8 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_hy_analyse_title.xml
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:height="5dp"
  5 + android:gravity="bottom">
  6 + <shape>
  7 + <corners android:radius="8dp"/>
  8 + <solid android:color="#50CEC2"/>
  9 + </shape>
  10 + </item>
  11 +
  12 + <item android:drawable="@drawable/png_hy_analyse_title"
  13 + android:gravity="bottom" android:bottom="1dp" android:start="4dp"
  14 + android:width="18dp" android:height="22dp" />
  15 +
  16 +
  17 +</layer-list>
0 18 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_hy_point_title.xml
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:height="5dp"
  5 + android:gravity="bottom">
  6 + <shape>
  7 + <corners android:radius="8dp"/>
  8 + <solid android:color="#50CEC2"/>
  9 + </shape>
  10 + </item>
  11 +
  12 + <item android:drawable="@drawable/png_hy_point_title"
  13 + android:gravity="bottom" android:start="2dp" android:bottom="4dp"
  14 + android:width="21dp" android:height="15dp" />
  15 +
  16 +
  17 +</layer-list>
0 18 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_hy_summary_title.xml
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:height="5dp"
  5 + android:gravity="bottom">
  6 + <shape>
  7 + <corners android:radius="8dp"/>
  8 + <solid android:color="#50CEC2"/>
  9 + </shape>
  10 + </item>
  11 +
  12 + <item android:drawable="@drawable/png_hy_summary_title"
  13 + android:gravity="bottom" android:start="2dp" android:bottom="3dp"
  14 + android:width="22dp" android:height="16dp" />
  15 +
  16 +
  17 +</layer-list>
0 18 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_hy_weak_title.xml
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:height="5dp"
  5 + android:gravity="bottom">
  6 + <shape>
  7 + <corners android:radius="8dp"/>
  8 + <solid android:color="#50CEC2"/>
  9 + </shape>
  10 + </item>
  11 +
  12 + <item android:drawable="@drawable/png_hy_weak_title"
  13 + android:gravity="bottom" android:bottom="2dp"
  14 + android:width="16dp" android:height="18dp" />
  15 +
  16 +
  17 +</layer-list>
0 18 \ No newline at end of file
... ...
app/src/main/res/drawable/bg_line_chart_fill2.xml
... ... @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <gradient
  5 + android:startColor="#AA3BC3B6"
  6 + android:endColor="#00FFFFFF"
  7 + android:angle="-90"/>
  8 +
  9 +</shape>
0 10 \ No newline at end of file
... ...
app/src/main/res/drawable/png_huyou_logo.png

25.9 KB

app/src/main/res/drawable/png_huyou_points_empty.png

65.2 KB

app/src/main/res/drawable/png_huyou_progress_bg.png

19.4 KB

app/src/main/res/drawable/png_huyou_top_bg.png

41.1 KB

app/src/main/res/drawable/png_hy_analyse_title.png

3.88 KB

app/src/main/res/drawable/png_hy_point_title.png

3.22 KB

app/src/main/res/drawable/png_hy_summary_comment.png

3.63 KB

app/src/main/res/drawable/png_hy_summary_title.png

3.33 KB

app/src/main/res/drawable/png_hy_weak_comment.png

3.25 KB

app/src/main/res/drawable/png_hy_weak_title.png

3.18 KB

app/src/main/res/drawable/png_ic_during.png

2.33 KB

app/src/main/res/drawable/png_ic_excellent.png

7.66 KB

app/src/main/res/drawable/png_ic_good.png

9.47 KB

app/src/main/res/drawable/png_ic_normal.png

9.43 KB

app/src/main/res/drawable/png_ic_weak.png

8.71 KB

app/src/main/res/drawable/png_info_bg.png

11.7 KB

app/src/main/res/drawable/png_iv_subject.png

2.45 KB

app/src/main/res/drawable/png_up.png

664 Bytes

app/src/main/res/drawable/shape_radius_2.xml
... ... @@ -0,0 +1,4 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <corners android:radius="2dp"/>
  4 +</shape>
0 5 \ No newline at end of file
... ...
app/src/main/res/layout/activity_huyou_detail.xml
... ... @@ -0,0 +1,1074 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<FrameLayout
  3 + xmlns:android="http://schemas.android.com/apk/res/android"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + xmlns:app="http://schemas.android.com/apk/res-auto"
  6 + android:layout_width="match_parent"
  7 + android:layout_height="match_parent"
  8 + tools:ignore="HardcodedText,ContentDescription,SmallSp,UseCompoundDrawables,RtlSymmetry">
  9 +<androidx.core.widget.NestedScrollView
  10 + android:layout_gravity="center_horizontal"
  11 + android:layout_width="wrap_content"
  12 + android:layout_height="match_parent">
  13 +
  14 + <LinearLayout
  15 + android:id="@+id/root"
  16 + android:orientation="vertical"
  17 + android:background="#CEF1EC"
  18 + android:layout_width="378dp"
  19 + android:layout_height="match_parent">
  20 +
  21 + <FrameLayout
  22 + android:orientation="horizontal"
  23 + android:paddingHorizontal="16dp"
  24 + android:layout_marginTop="34dp"
  25 + android:layout_width="match_parent"
  26 + android:layout_height="wrap_content">
  27 + <FrameLayout
  28 + android:id="@+id/toolbar"
  29 + android:layout_gravity="center_vertical"
  30 + android:layout_width="match_parent"
  31 + android:layout_height="wrap_content">
  32 + <TextView
  33 + android:id="@+id/btnSwitch"
  34 + android:text="A4版"
  35 + android:textSize="16sp"
  36 + android:textColor="#333"
  37 + android:layout_marginStart="48dp"
  38 + android:layout_width="wrap_content"
  39 + android:layout_height="wrap_content"/>
  40 + <TextView
  41 + android:id="@+id/btnShare"
  42 + android:text="分享"
  43 + android:textSize="16sp"
  44 + android:textColor="#333"
  45 + android:layout_width="wrap_content"
  46 + android:layout_height="wrap_content"/>
  47 + <TextView
  48 + android:id="@+id/btnSame"
  49 + android:visibility="gone"
  50 + android:text="举一反三"
  51 + android:textSize="16sp"
  52 + android:textColor="#333"
  53 + android:layout_gravity="center_vertical|end"
  54 + android:layout_width="wrap_content"
  55 + android:layout_height="wrap_content"/>
  56 + </FrameLayout>
  57 + <TextView
  58 + android:id="@+id/tvTitle"
  59 + android:text="周作业学习报告"
  60 + android:textSize="18sp"
  61 + android:textColor="#333"
  62 + android:textStyle="bold"
  63 + android:layout_gravity="center_horizontal"
  64 + android:layout_width="wrap_content"
  65 + android:layout_height="wrap_content" />
  66 + </FrameLayout>
  67 +
  68 +
  69 + <ImageView
  70 + android:src="@drawable/png_huyou_top_bg"
  71 + android:elevation="1dp"
  72 + android:layout_gravity="end"
  73 + android:layout_marginHorizontal="16dp"
  74 + android:layout_width="102dp"
  75 + android:layout_height="90dp"/>
  76 +
  77 + <LinearLayout
  78 + android:orientation="vertical"
  79 + android:background="@drawable/png_info_bg"
  80 + android:padding="16dp"
  81 + android:layout_marginHorizontal="16dp"
  82 + android:layout_marginTop="-60dp"
  83 + android:layout_width="match_parent"
  84 + android:layout_height="144dp">
  85 + <LinearLayout
  86 + android:orientation="horizontal"
  87 + android:layout_width="match_parent"
  88 + android:layout_height="wrap_content">
  89 + <androidx.constraintlayout.utils.widget.ImageFilterView
  90 + android:id="@+id/ivAvatar"
  91 + tools:background="#2491FF"
  92 + app:round="40dp"
  93 + android:layout_width="40dp"
  94 + android:layout_height="40dp"/>
  95 + <LinearLayout
  96 + android:orientation="vertical"
  97 + android:layout_gravity="center_vertical"
  98 + android:layout_marginStart="10dp"
  99 + android:layout_width="wrap_content"
  100 + android:layout_height="wrap_content">
  101 + <TextView
  102 + android:id="@+id/tvStuName"
  103 + tools:text="杨同学 "
  104 + android:textSize="14sp"
  105 + android:textColor="#333"
  106 + android:textStyle="bold"
  107 + android:layout_width="wrap_content"
  108 + android:layout_height="wrap_content"/>
  109 + <TextView
  110 + android:id="@+id/tvGrade"
  111 + tools:text="七年级"
  112 + android:textSize="13sp"
  113 + android:textColor="#666"
  114 + android:textStyle="bold"
  115 + android:layout_width="wrap_content"
  116 + android:layout_height="wrap_content"/>
  117 + </LinearLayout>
  118 + </LinearLayout>
  119 + <LinearLayout
  120 + android:orientation="horizontal"
  121 + android:background="@drawable/shape_radius_10"
  122 + android:backgroundTint="#F4FAFF"
  123 + android:layout_marginTop="12dp"
  124 + android:layout_width="match_parent"
  125 + android:layout_height="60dp">
  126 + <LinearLayout
  127 + android:orientation="vertical"
  128 + android:gravity="center"
  129 + android:layout_width="0dp"
  130 + android:layout_height="match_parent"
  131 + android:layout_weight="1">
  132 + <LinearLayout
  133 + android:paddingEnd="20dp"
  134 + android:gravity="center_vertical"
  135 + android:layout_width="wrap_content"
  136 + android:layout_height="wrap_content">
  137 + <ImageView
  138 + android:src="@drawable/png_iv_subject"
  139 + android:layout_marginEnd="5dp"
  140 + android:layout_width="16dp"
  141 + android:layout_height="14dp"/>
  142 + <TextView
  143 + android:text="学科"
  144 + android:textSize="12sp"
  145 + android:textColor="#333"
  146 + android:textStyle="bold"
  147 + android:layout_width="wrap_content"
  148 + android:layout_height="wrap_content"/>
  149 + </LinearLayout>
  150 + <TextView
  151 + android:id="@+id/tvSubject"
  152 + tools:text="数学"
  153 + android:textSize="12sp"
  154 + android:textColor="#3BC3B6"
  155 + android:textStyle="bold"
  156 + android:layout_marginTop="8dp"
  157 + android:layout_width="wrap_content"
  158 + android:layout_height="wrap_content"/>
  159 + </LinearLayout>
  160 + <LinearLayout
  161 + android:orientation="vertical"
  162 + android:gravity="center"
  163 + android:layout_width="0dp"
  164 + android:layout_height="match_parent"
  165 + android:layout_weight="1">
  166 + <LinearLayout
  167 + android:paddingEnd="20dp"
  168 + android:gravity="center_vertical"
  169 + android:layout_width="wrap_content"
  170 + android:layout_height="wrap_content">
  171 + <ImageView
  172 + android:src="@drawable/png_ic_during"
  173 + android:layout_marginEnd="5dp"
  174 + android:layout_width="14dp"
  175 + android:layout_height="13dp"/>
  176 + <TextView
  177 + android:text="周期"
  178 + android:textSize="12sp"
  179 + android:textColor="#333"
  180 + android:textStyle="bold"
  181 + android:layout_width="wrap_content"
  182 + android:layout_height="wrap_content"/>
  183 + </LinearLayout>
  184 + <TextView
  185 + android:id="@+id/tvDate"
  186 + tools:text="2024.09.01-2024.09.30"
  187 + android:textSize="12sp"
  188 + android:textColor="#3BC3B6"
  189 + android:textStyle="bold"
  190 + android:layout_marginTop="8dp"
  191 + android:layout_width="wrap_content"
  192 + android:layout_height="wrap_content"/>
  193 + </LinearLayout>
  194 + </LinearLayout>
  195 + </LinearLayout>
  196 +
  197 + <LinearLayout
  198 + android:orientation="vertical"
  199 + android:background="@drawable/shape_radius_10"
  200 + android:backgroundTint="@color/white"
  201 + android:padding="16dp"
  202 + android:layout_marginHorizontal="16dp"
  203 + android:layout_marginTop="12dp"
  204 + android:layout_width="match_parent"
  205 + android:layout_height="wrap_content">
  206 + <TextView
  207 + android:text="薄弱知识点总评"
  208 + android:textSize="16sp"
  209 + android:textColor="#333333"
  210 + android:textStyle="bold"
  211 + android:background="@drawable/bg_hy_weak_title"
  212 + android:paddingStart="20dp"
  213 + android:paddingEnd="4dp"
  214 + android:layout_gravity="center_horizontal"
  215 + android:layout_width="wrap_content"
  216 + android:layout_height="wrap_content"/>
  217 + <LinearLayout
  218 + android:orientation="horizontal"
  219 + android:layout_marginTop="28dp"
  220 + android:layout_width="match_parent"
  221 + android:layout_height="wrap_content">
  222 + <LinearLayout
  223 + android:orientation="vertical"
  224 + android:layout_width="0dp"
  225 + android:layout_height="wrap_content"
  226 + android:layout_weight="1">
  227 + <TextView
  228 + android:text="学习前"
  229 + android:textSize="12sp"
  230 + android:textColor="#333"
  231 + android:layout_gravity="center_horizontal"
  232 + android:layout_width="wrap_content"
  233 + android:layout_height="wrap_content"/>
  234 + <FrameLayout
  235 + android:background="@drawable/png_huyou_progress_bg"
  236 + android:padding="8dp"
  237 + android:layout_gravity="center_horizontal"
  238 + android:layout_marginTop="16dp"
  239 + android:layout_width="126dp"
  240 + android:layout_height="126dp">
  241 + <com.littlejie.circleprogress.CircleProgress
  242 + android:id="@+id/cpBefore"
  243 + app:arcWidth="15dp"
  244 + app:bgArcWidth="15dp"
  245 + app:arcColors="#F36A27"
  246 + app:bgArcColor="#FFF1EA"
  247 + app:startAngle="-90"
  248 + app:sweepAngle="360"
  249 + app:maxValue="100"
  250 + app:value="0"
  251 + app:hintColor="@color/transparent"
  252 + app:unitColor="@color/transparent"
  253 + app:valueColor="@color/transparent"
  254 + android:layout_width="match_parent"
  255 + android:layout_height="match_parent"/>
  256 + <LinearLayout
  257 + android:orientation="vertical"
  258 + android:gravity="center_horizontal"
  259 + android:layout_gravity="center"
  260 + android:layout_width="wrap_content"
  261 + android:layout_height="wrap_content">
  262 + <LinearLayout
  263 + android:layout_width="wrap_content"
  264 + android:layout_height="wrap_content">
  265 + <TextView
  266 + android:id="@+id/pgBefore"
  267 + tools:text="88"
  268 + android:textSize="25sp"
  269 + android:textColor="#EA5127"
  270 + android:textStyle="bold"
  271 + android:layout_width="wrap_content"
  272 + android:layout_height="wrap_content"/>
  273 + <TextView
  274 + android:text="%"
  275 + android:textSize="12sp"
  276 + android:textColor="#EA5127"
  277 + android:layout_width="wrap_content"
  278 + android:layout_height="wrap_content"/>
  279 + </LinearLayout>
  280 + <TextView
  281 + android:text="整体掌握程度"
  282 + android:textSize="10sp"
  283 + android:textColor="#333"
  284 + android:textStyle="bold"
  285 + android:layout_marginTop="-2dp"
  286 + android:layout_width="wrap_content"
  287 + android:layout_height="wrap_content"/>
  288 + </LinearLayout>
  289 + </FrameLayout>
  290 + </LinearLayout>
  291 + <LinearLayout
  292 + android:orientation="vertical"
  293 + android:layout_width="0dp"
  294 + android:layout_height="wrap_content"
  295 + android:layout_weight="1">
  296 + <TextView
  297 + android:text="学习后"
  298 + android:textSize="12sp"
  299 + android:textColor="#333"
  300 + android:layout_gravity="center_horizontal"
  301 + android:layout_width="wrap_content"
  302 + android:layout_height="wrap_content"/>
  303 + <FrameLayout
  304 + android:background="@drawable/png_huyou_progress_bg"
  305 + android:padding="8dp"
  306 + android:layout_gravity="center_horizontal"
  307 + android:layout_marginTop="16dp"
  308 + android:layout_width="126dp"
  309 + android:layout_height="126dp">
  310 + <com.littlejie.circleprogress.CircleProgress
  311 + android:id="@+id/cpAfter"
  312 + app:arcWidth="15dp"
  313 + app:bgArcWidth="15dp"
  314 + app:arcColors="#3BC3B6"
  315 + app:bgArcColor="#C2FCF6"
  316 + app:startAngle="-90"
  317 + app:sweepAngle="360"
  318 + app:maxValue="100"
  319 + app:value="0"
  320 + app:hintColor="@color/transparent"
  321 + app:unitColor="@color/transparent"
  322 + app:valueColor="@color/transparent"
  323 + android:layout_width="match_parent"
  324 + android:layout_height="match_parent"/>
  325 + <LinearLayout
  326 + android:orientation="vertical"
  327 + android:gravity="center_horizontal"
  328 + android:layout_gravity="center"
  329 + android:layout_width="wrap_content"
  330 + android:layout_height="wrap_content">
  331 + <LinearLayout
  332 + android:layout_width="wrap_content"
  333 + android:layout_height="wrap_content">
  334 + <TextView
  335 + android:id="@+id/pgAfter"
  336 + tools:text="88"
  337 + android:textSize="25sp"
  338 + android:textColor="#3BC3B6"
  339 + android:textStyle="bold"
  340 + android:layout_width="wrap_content"
  341 + android:layout_height="wrap_content"/>
  342 + <TextView
  343 + android:text="%"
  344 + android:textSize="12sp"
  345 + android:textColor="#3BC3B6"
  346 + android:layout_width="wrap_content"
  347 + android:layout_height="wrap_content"/>
  348 + </LinearLayout>
  349 + <TextView
  350 + android:text="整体掌握程度"
  351 + android:textSize="10sp"
  352 + android:textColor="#333"
  353 + android:textStyle="bold"
  354 + android:layout_marginTop="-2dp"
  355 + android:layout_width="wrap_content"
  356 + android:layout_height="wrap_content"/>
  357 + </LinearLayout>
  358 + </FrameLayout>
  359 + </LinearLayout>
  360 + </LinearLayout>
  361 +
  362 + <FrameLayout
  363 + android:layout_marginTop="20dp"
  364 + android:layout_width="match_parent"
  365 + android:layout_height="wrap_content">
  366 + <ImageView
  367 + android:src="@drawable/png_hy_weak_comment"
  368 + android:layout_width="16dp"
  369 + android:layout_height="18dp"/>
  370 + <TextView
  371 + android:id="@+id/tvWeakRate"
  372 + android:textSize="16sp"
  373 + android:textColor="#333"
  374 + android:lineSpacingMultiplier="1.3"
  375 + android:layout_width="wrap_content"
  376 + android:layout_height="wrap_content"/>
  377 + </FrameLayout>
  378 + </LinearLayout>
  379 +
  380 + <LinearLayout
  381 + android:orientation="vertical"
  382 + android:background="@drawable/shape_radius_10"
  383 + android:backgroundTint="@color/white"
  384 + android:padding="16dp"
  385 + android:layout_marginHorizontal="16dp"
  386 + android:layout_marginTop="12dp"
  387 + android:layout_width="match_parent"
  388 + android:layout_height="wrap_content">
  389 +
  390 + <TextView
  391 + android:text="作业概括"
  392 + android:textSize="16sp"
  393 + android:textColor="#333333"
  394 + android:textStyle="bold"
  395 + android:background="@drawable/bg_hy_summary_title"
  396 + android:paddingStart="28dp"
  397 + android:paddingEnd="4dp"
  398 + android:layout_gravity="center_horizontal"
  399 + android:layout_width="wrap_content"
  400 + android:layout_height="wrap_content"/>
  401 + <LinearLayout
  402 + android:orientation="horizontal"
  403 + android:background="@drawable/shape_radius_5"
  404 + android:backgroundTint="#F4FAFF"
  405 + android:layout_width="match_parent"
  406 + android:layout_height="80dp"
  407 + android:layout_marginTop="16dp">
  408 + <LinearLayout
  409 + android:orientation="vertical"
  410 + android:gravity="center"
  411 + android:layout_width="0dp"
  412 + android:layout_height="match_parent"
  413 + android:layout_weight="1">
  414 + <LinearLayout
  415 + android:orientation="horizontal"
  416 + android:gravity="center_vertical"
  417 + android:layout_width="wrap_content"
  418 + android:layout_height="wrap_content">
  419 + <ImageView
  420 + android:src="@drawable/png_icon_statistical_accuracy"
  421 + android:layout_width="12dp"
  422 + android:layout_height="13dp"/>
  423 + <TextView
  424 + android:text="作业正确率"
  425 + android:textSize="11sp"
  426 + android:textColor="#333"
  427 + android:textStyle="bold"
  428 + android:layout_marginStart="5dp"
  429 + android:layout_width="wrap_content"
  430 + android:layout_height="wrap_content"/>
  431 + </LinearLayout>
  432 + <LinearLayout
  433 + android:orientation="horizontal"
  434 + android:layout_marginTop="8dp"
  435 + android:layout_width="wrap_content"
  436 + android:layout_height="wrap_content">
  437 + <TextView
  438 + android:id="@+id/tvTotalRate"
  439 + tools:text="88"
  440 + android:textSize="14sp"
  441 + android:textColor="#3BC3B6"
  442 + android:textStyle="bold"
  443 + android:layout_width="wrap_content"
  444 + android:layout_height="wrap_content"/>
  445 + <TextView
  446 + android:text="%"
  447 + android:textSize="9sp"
  448 + android:textColor="#3BC3B6"
  449 + android:textStyle="bold"
  450 + android:layout_width="wrap_content"
  451 + android:layout_height="wrap_content"/>
  452 + </LinearLayout>
  453 + </LinearLayout>
  454 + <View
  455 + android:background="#9ECAFC"
  456 + android:layout_marginVertical="8dp"
  457 + android:layout_width="1dp"
  458 + android:layout_height="match_parent"/>
  459 + <LinearLayout
  460 + android:orientation="vertical"
  461 + android:gravity="center"
  462 + android:layout_width="0dp"
  463 + android:layout_height="match_parent"
  464 + android:layout_weight="1">
  465 + <LinearLayout
  466 + android:orientation="horizontal"
  467 + android:gravity="center_vertical"
  468 + android:layout_width="wrap_content"
  469 + android:layout_height="wrap_content">
  470 + <ImageView
  471 + android:src="@drawable/png_icon_statistical_accuracy"
  472 + android:layout_width="12dp"
  473 + android:layout_height="13dp"/>
  474 + <TextView
  475 + android:text="答对题数"
  476 + android:textSize="11sp"
  477 + android:textColor="#333"
  478 + android:textStyle="bold"
  479 + android:layout_marginStart="5dp"
  480 + android:layout_width="wrap_content"
  481 + android:layout_height="wrap_content"/>
  482 + </LinearLayout>
  483 + <LinearLayout
  484 + android:orientation="horizontal"
  485 + android:layout_marginTop="8dp"
  486 + android:layout_width="wrap_content"
  487 + android:layout_height="wrap_content">
  488 + <TextView
  489 + android:id="@+id/tvTotalCorrect"
  490 + tools:text="88"
  491 + android:textSize="14sp"
  492 + android:textColor="#3BC3B6"
  493 + android:textStyle="bold"
  494 + android:layout_width="wrap_content"
  495 + android:layout_height="wrap_content"/>
  496 + <TextView
  497 + android:text="道"
  498 + android:textSize="9sp"
  499 + android:textColor="#3BC3B6"
  500 + android:textStyle="bold"
  501 + android:layout_width="wrap_content"
  502 + android:layout_height="wrap_content"/>
  503 + </LinearLayout>
  504 + </LinearLayout>
  505 + <View
  506 + android:background="#9ECAFC"
  507 + android:layout_marginVertical="8dp"
  508 + android:layout_width="1dp"
  509 + android:layout_height="match_parent"/>
  510 + <LinearLayout
  511 + android:orientation="vertical"
  512 + android:gravity="center"
  513 + android:layout_width="0dp"
  514 + android:layout_height="match_parent"
  515 + android:layout_weight="1">
  516 + <LinearLayout
  517 + android:orientation="horizontal"
  518 + android:gravity="center_vertical"
  519 + android:layout_width="wrap_content"
  520 + android:layout_height="wrap_content">
  521 + <ImageView
  522 + android:src="@drawable/png_icon_statistical_accuracy"
  523 + android:layout_width="12dp"
  524 + android:layout_height="13dp"/>
  525 + <TextView
  526 + android:text="答错题数"
  527 + android:textSize="11sp"
  528 + android:textColor="#333"
  529 + android:textStyle="bold"
  530 + android:layout_marginStart="5dp"
  531 + android:layout_width="wrap_content"
  532 + android:layout_height="wrap_content"/>
  533 + </LinearLayout>
  534 + <LinearLayout
  535 + android:orientation="horizontal"
  536 + android:layout_marginTop="8dp"
  537 + android:layout_width="wrap_content"
  538 + android:layout_height="wrap_content">
  539 + <TextView
  540 + android:id="@+id/tvTotalError"
  541 + tools:text="88"
  542 + android:textSize="14sp"
  543 + android:textColor="#3BC3B6"
  544 + android:textStyle="bold"
  545 + android:layout_width="wrap_content"
  546 + android:layout_height="wrap_content"/>
  547 + <TextView
  548 + android:text="道"
  549 + android:textSize="9sp"
  550 + android:textColor="#3BC3B6"
  551 + android:textStyle="bold"
  552 + android:layout_width="wrap_content"
  553 + android:layout_height="wrap_content"/>
  554 + </LinearLayout>
  555 + </LinearLayout>
  556 + </LinearLayout>
  557 +
  558 + <TextView
  559 + android:text="每日作业正确率"
  560 + android:textSize="13sp"
  561 + android:textColor="#333"
  562 + android:textStyle="bold"
  563 + android:layout_gravity="center_horizontal"
  564 + android:layout_marginTop="16dp"
  565 + android:layout_width="wrap_content"
  566 + android:layout_height="wrap_content"/>
  567 + <com.github.mikephil.charting.charts.LineChart
  568 + android:id="@+id/lineChart"
  569 + android:layout_marginStart="-8dp"
  570 + android:layout_width="match_parent"
  571 + android:layout_height="220dp"/>
  572 + <FrameLayout
  573 + android:layout_marginVertical="20dp"
  574 + android:layout_width="match_parent"
  575 + android:layout_height="wrap_content">
  576 + <ImageView
  577 + android:src="@drawable/png_hy_summary_comment"
  578 + android:layout_width="22dp"
  579 + android:layout_height="22dp"/>
  580 + <TextView
  581 + android:id="@+id/tvRating"
  582 + android:textSize="16sp"
  583 + android:textColor="#333"
  584 + android:lineSpacingMultiplier="1.3"
  585 + android:layout_marginTop="2dp"
  586 + android:layout_width="match_parent"
  587 + android:layout_height="wrap_content"/>
  588 + </FrameLayout>
  589 + </LinearLayout>
  590 +
  591 + <Space
  592 + android:id="@+id/splitLine"
  593 + android:layout_marginTop="6dp"
  594 + android:layout_width="match_parent"
  595 + android:layout_height="0dp"/>
  596 +
  597 + <LinearLayout
  598 + android:orientation="vertical"
  599 + android:background="@drawable/shape_radius_10"
  600 + android:backgroundTint="@color/white"
  601 + android:padding="16dp"
  602 + android:layout_marginHorizontal="16dp"
  603 + android:layout_marginTop="6dp"
  604 + android:layout_width="match_parent"
  605 + android:layout_height="wrap_content">
  606 + <TextView
  607 + android:text="知识点掌握情况"
  608 + android:textSize="16sp"
  609 + android:textColor="#333333"
  610 + android:textStyle="bold"
  611 + android:background="@drawable/bg_hy_point_title"
  612 + android:paddingStart="28dp"
  613 + android:paddingEnd="4dp"
  614 + android:layout_gravity="center_horizontal"
  615 + android:layout_width="wrap_content"
  616 + android:layout_height="wrap_content"/>
  617 +
  618 + <LinearLayout
  619 + android:orientation="horizontal"
  620 + android:layout_width="match_parent"
  621 + android:layout_height="120dp"
  622 + android:layout_marginTop="20dp">
  623 + <LinearLayout
  624 + android:orientation="vertical"
  625 + android:background="@drawable/shape_radius_10"
  626 + android:backgroundTint="#F4FAFF"
  627 + android:gravity="center_horizontal"
  628 + android:paddingTop="10dp"
  629 + android:layout_width="0dp"
  630 + android:layout_height="match_parent"
  631 + android:layout_weight="1">
  632 + <ImageView
  633 + android:src="@drawable/png_ic_excellent"
  634 + android:backgroundTint="#3BC3B6"
  635 + android:background="@drawable/bg_circle"
  636 + android:padding="8dp"
  637 + android:layout_width="40dp"
  638 + android:layout_height="40dp"/>
  639 + <TextView
  640 + android:id="@+id/tvExcellent"
  641 + android:text="-"
  642 + android:textColor="#3BC3B6"
  643 + android:textSize="25sp"
  644 + android:textStyle="bold"
  645 + android:layout_marginTop="4dp"
  646 + android:layout_width="wrap_content"
  647 + android:layout_height="wrap_content"/>
  648 + <TextView
  649 + android:text="掌握优秀"
  650 + android:textSize="15sp"
  651 + android:textColor="#333"
  652 + android:textStyle="bold"
  653 + android:layout_width="wrap_content"
  654 + android:layout_height="wrap_content"/>
  655 + </LinearLayout>
  656 + <LinearLayout
  657 + android:orientation="vertical"
  658 + android:background="@drawable/shape_radius_10"
  659 + android:backgroundTint="#F4FAFF"
  660 + android:gravity="center_horizontal"
  661 + android:paddingTop="10dp"
  662 + android:layout_marginStart="14dp"
  663 + android:layout_width="0dp"
  664 + android:layout_height="match_parent"
  665 + android:layout_weight="1">
  666 + <ImageView
  667 + android:src="@drawable/png_ic_good"
  668 + android:backgroundTint="#489AFA"
  669 + android:background="@drawable/bg_circle"
  670 + android:padding="8dp"
  671 + android:layout_width="40dp"
  672 + android:layout_height="40dp"/>
  673 + <TextView
  674 + android:id="@+id/tvGood"
  675 + android:text="-"
  676 + android:textColor="#489AFA"
  677 + android:textSize="25sp"
  678 + android:textStyle="bold"
  679 + android:layout_marginTop="4dp"
  680 + android:layout_width="wrap_content"
  681 + android:layout_height="wrap_content"/>
  682 + <TextView
  683 + android:text="掌握良好"
  684 + android:textSize="15sp"
  685 + android:textColor="#333"
  686 + android:textStyle="bold"
  687 + android:layout_width="wrap_content"
  688 + android:layout_height="wrap_content"/>
  689 + </LinearLayout>
  690 + <LinearLayout
  691 + android:orientation="vertical"
  692 + android:background="@drawable/shape_radius_10"
  693 + android:backgroundTint="#F4FAFF"
  694 + android:gravity="center_horizontal"
  695 + android:paddingTop="10dp"
  696 + android:layout_marginStart="14dp"
  697 + android:layout_width="0dp"
  698 + android:layout_height="match_parent"
  699 + android:layout_weight="1">
  700 + <ImageView
  701 + android:src="@drawable/png_ic_normal"
  702 + android:backgroundTint="#F58725"
  703 + android:background="@drawable/bg_circle"
  704 + android:padding="8dp"
  705 + android:layout_width="40dp"
  706 + android:layout_height="40dp"/>
  707 + <TextView
  708 + android:id="@+id/tvNormal"
  709 + android:text="-"
  710 + android:textColor="#F58725"
  711 + android:textSize="25sp"
  712 + android:textStyle="bold"
  713 + android:layout_marginTop="4dp"
  714 + android:layout_width="wrap_content"
  715 + android:layout_height="wrap_content"/>
  716 + <TextView
  717 + android:text="掌握一般"
  718 + android:textSize="15sp"
  719 + android:textColor="#333"
  720 + android:textStyle="bold"
  721 + android:layout_width="wrap_content"
  722 + android:layout_height="wrap_content"/>
  723 + </LinearLayout>
  724 + <LinearLayout
  725 + android:orientation="vertical"
  726 + android:background="@drawable/shape_radius_10"
  727 + android:backgroundTint="#F4FAFF"
  728 + android:gravity="center_horizontal"
  729 + android:paddingTop="10dp"
  730 + android:layout_marginStart="14dp"
  731 + android:layout_width="0dp"
  732 + android:layout_height="match_parent"
  733 + android:layout_weight="1">
  734 + <ImageView
  735 + android:src="@drawable/png_ic_weak"
  736 + android:backgroundTint="#EA5127"
  737 + android:background="@drawable/bg_circle"
  738 + android:padding="8dp"
  739 + android:layout_width="40dp"
  740 + android:layout_height="40dp"/>
  741 + <TextView
  742 + android:id="@+id/tvWeak"
  743 + android:text="-"
  744 + android:textColor="#EA5127"
  745 + android:textSize="25sp"
  746 + android:textStyle="bold"
  747 + android:layout_marginTop="4dp"
  748 + android:layout_width="wrap_content"
  749 + android:layout_height="wrap_content"/>
  750 + <TextView
  751 + android:text="掌握薄弱"
  752 + android:textSize="15sp"
  753 + android:textColor="#333"
  754 + android:textStyle="bold"
  755 + android:layout_width="wrap_content"
  756 + android:layout_height="wrap_content"/>
  757 + </LinearLayout>
  758 + </LinearLayout>
  759 +
  760 + <FrameLayout
  761 + android:layout_gravity="center_horizontal"
  762 + android:layout_marginTop="20dp"
  763 + android:layout_width="180dp"
  764 + android:layout_height="180dp">
  765 + <com.littlejie.circleprogress.CircleProgress
  766 + android:id="@+id/cpBase"
  767 + app:value="0"
  768 + app:arcWidth="35dp"
  769 + app:bgArcWidth="35dp"
  770 + app:bgArcColor="#3BC3B6"
  771 + app:startAngle="0"
  772 + app:sweepAngle="360"
  773 + app:hintColor="@color/transparent"
  774 + app:unitColor="@color/transparent"
  775 + app:valueColor="@color/transparent"
  776 + android:layout_width="match_parent"
  777 + android:layout_height="match_parent"/>
  778 + <com.littlejie.circleprogress.CircleProgress
  779 + android:id="@+id/cpGood"
  780 + app:value="0"
  781 + app:arcWidth="35dp"
  782 + app:bgArcWidth="35dp"
  783 + app:arcColors="#489AFA"
  784 + app:bgArcColor="@color/transparent"
  785 + app:startAngle="0"
  786 + app:sweepAngle="360"
  787 + app:hintColor="@color/transparent"
  788 + app:unitColor="@color/transparent"
  789 + app:valueColor="@color/transparent"
  790 + android:layout_width="match_parent"
  791 + android:layout_height="match_parent"/>
  792 + <com.littlejie.circleprogress.CircleProgress
  793 + android:id="@+id/cpNormal"
  794 + app:value="0"
  795 + app:arcWidth="35dp"
  796 + app:bgArcWidth="35dp"
  797 + app:arcColors="#F58725"
  798 + app:bgArcColor="@color/transparent"
  799 + app:startAngle="0"
  800 + app:sweepAngle="360"
  801 + app:hintColor="@color/transparent"
  802 + app:unitColor="@color/transparent"
  803 + app:valueColor="@color/transparent"
  804 + android:layout_width="match_parent"
  805 + android:layout_height="match_parent"/>
  806 + <com.littlejie.circleprogress.CircleProgress
  807 + android:id="@+id/cpWeak"
  808 + app:value="0"
  809 + app:arcWidth="35dp"
  810 + app:bgArcWidth="35dp"
  811 + app:arcColors="#EA5127"
  812 + app:bgArcColor="@color/transparent"
  813 + app:startAngle="0"
  814 + app:sweepAngle="360"
  815 + app:hintColor="@color/transparent"
  816 + app:unitColor="@color/transparent"
  817 + app:valueColor="@color/transparent"
  818 + android:layout_width="match_parent"
  819 + android:layout_height="match_parent"/>
  820 +
  821 + <LinearLayout
  822 + android:orientation="vertical"
  823 + android:gravity="center_horizontal"
  824 + android:layout_gravity="center"
  825 + android:layout_width="wrap_content"
  826 + android:layout_height="wrap_content">
  827 + <LinearLayout
  828 + android:layout_width="wrap_content"
  829 + android:layout_height="wrap_content">
  830 + <TextView
  831 + android:id="@+id/tvAvePoint"
  832 + tools:text="88"
  833 + android:textSize="25sp"
  834 + android:textColor="#3BC3B6"
  835 + android:textStyle="bold"
  836 + android:layout_width="wrap_content"
  837 + android:layout_height="wrap_content"/>
  838 + <TextView
  839 + android:text="%"
  840 + android:textSize="12sp"
  841 + android:textColor="#3BC3B6"
  842 + android:layout_width="wrap_content"
  843 + android:layout_height="wrap_content"/>
  844 + </LinearLayout>
  845 + <TextView
  846 + android:text="综合掌握程度"
  847 + android:textSize="10sp"
  848 + android:textColor="#333"
  849 + android:textStyle="bold"
  850 + android:layout_marginTop="-2dp"
  851 + android:layout_width="wrap_content"
  852 + android:layout_height="wrap_content"/>
  853 + </LinearLayout>
  854 + </FrameLayout>
  855 + </LinearLayout>
  856 +
  857 + <LinearLayout
  858 + android:orientation="vertical"
  859 + android:background="@drawable/shape_radius_10"
  860 + android:backgroundTint="@color/white"
  861 + android:padding="16dp"
  862 + android:layout_marginHorizontal="16dp"
  863 + android:layout_marginTop="12dp"
  864 + android:layout_width="match_parent"
  865 + android:layout_height="wrap_content">
  866 + <TextView
  867 + android:text="学习效果分析"
  868 + android:textSize="16sp"
  869 + android:textColor="#333333"
  870 + android:textStyle="bold"
  871 + android:background="@drawable/bg_hy_analyse_title"
  872 + android:paddingStart="24dp"
  873 + android:paddingEnd="4dp"
  874 + android:layout_gravity="center_horizontal"
  875 + android:layout_width="wrap_content"
  876 + android:layout_height="wrap_content"/>
  877 +
  878 + <LinearLayout
  879 + android:id="@+id/flEmptyPoints"
  880 + android:visibility="gone"
  881 + android:orientation="vertical"
  882 + android:gravity="center_horizontal"
  883 + android:layout_marginTop="50dp"
  884 + android:layout_width="match_parent"
  885 + android:layout_height="wrap_content">
  886 + <ImageView
  887 + android:src="@drawable/png_huyou_points_empty"
  888 + android:layout_width="195dp"
  889 + android:layout_height="145dp"/>
  890 + <TextView
  891 + android:text="你太棒了!"
  892 + android:textSize="20sp"
  893 + android:textColor="#999"
  894 + android:layout_marginVertical="16dp"
  895 + android:layout_width="wrap_content"
  896 + android:layout_height="wrap_content"/>
  897 + </LinearLayout>
  898 +
  899 + <LinearLayout
  900 + android:id="@+id/tableRoot"
  901 + android:orientation="vertical"
  902 + android:background="@drawable/bg_huyou_table_bg"
  903 + android:layout_marginTop="16dp"
  904 + android:layout_width="match_parent"
  905 + android:layout_height="wrap_content">
  906 + <LinearLayout
  907 + android:orientation="horizontal"
  908 + android:background="#50CEC2"
  909 + android:layout_width="match_parent"
  910 + android:layout_height="60dp">
  911 + <TextView
  912 + android:text="知识点名称"
  913 + android:textSize="13sp"
  914 + android:textColor="@color/white"
  915 + android:gravity="center"
  916 + android:layout_weight="82"
  917 + android:layout_width="0dp"
  918 + android:layout_height="match_parent"/>
  919 + <View
  920 + android:background="#38B3A7"
  921 + android:layout_width="1dp"
  922 + android:layout_height="match_parent"/>
  923 +
  924 + <LinearLayout
  925 + android:orientation="vertical"
  926 + android:layout_weight="72"
  927 + android:layout_width="0dp"
  928 + android:layout_height="match_parent">
  929 + <TextView
  930 + android:text="学前"
  931 + android:textSize="13sp"
  932 + android:textColor="@color/white"
  933 + android:gravity="center"
  934 + android:layout_width="match_parent"
  935 + android:layout_height="24dp"/>
  936 + <View
  937 + android:background="#38B3A7"
  938 + android:layout_width="match_parent"
  939 + android:layout_height="1dp"/>
  940 + <LinearLayout
  941 + android:orientation="horizontal"
  942 + android:layout_width="match_parent"
  943 + android:layout_height="match_parent">
  944 + <TextView
  945 + android:text="程\n度"
  946 + android:textSize="13sp"
  947 + android:textColor="@color/white"
  948 + android:gravity="center"
  949 + android:layout_weight="1"
  950 + android:layout_width="0dp"
  951 + android:layout_height="wrap_content"/>
  952 + <View
  953 + android:background="#38B3A7"
  954 + android:layout_width="1dp"
  955 + android:layout_height="match_parent"/>
  956 + <TextView
  957 + android:text="状\n态"
  958 + android:textSize="13sp"
  959 + android:textColor="@color/white"
  960 + android:gravity="center"
  961 + android:layout_weight="1"
  962 + android:layout_width="0dp"
  963 + android:layout_height="wrap_content"/>
  964 + </LinearLayout>
  965 + </LinearLayout>
  966 +
  967 + <View
  968 + android:background="#38B3A7"
  969 + android:layout_width="1dp"
  970 + android:layout_height="match_parent"/>
  971 +
  972 + <LinearLayout
  973 + android:orientation="vertical"
  974 + android:layout_weight="72"
  975 + android:layout_width="0dp"
  976 + android:layout_height="match_parent">
  977 + <TextView
  978 + android:text="学后"
  979 + android:textSize="13sp"
  980 + android:textColor="@color/white"
  981 + android:gravity="center"
  982 + android:layout_width="match_parent"
  983 + android:layout_height="24dp"/>
  984 + <View
  985 + android:background="#38B3A7"
  986 + android:layout_width="match_parent"
  987 + android:layout_height="1dp"/>
  988 + <LinearLayout
  989 + android:orientation="horizontal"
  990 + android:layout_width="match_parent"
  991 + android:layout_height="match_parent">
  992 + <TextView
  993 + android:text="程\n度"
  994 + android:textSize="13sp"
  995 + android:textColor="@color/white"
  996 + android:gravity="center"
  997 + android:layout_weight="1"
  998 + android:layout_width="0dp"
  999 + android:layout_height="wrap_content"/>
  1000 + <View
  1001 + android:background="#38B3A7"
  1002 + android:layout_width="1dp"
  1003 + android:layout_height="match_parent"/>
  1004 + <TextView
  1005 + android:text="状\n态"
  1006 + android:textSize="13sp"
  1007 + android:textColor="@color/white"
  1008 + android:gravity="center"
  1009 + android:layout_weight="1"
  1010 + android:layout_width="0dp"
  1011 + android:layout_height="wrap_content"/>
  1012 + </LinearLayout>
  1013 +
  1014 + </LinearLayout>
  1015 +
  1016 + <View
  1017 + android:background="#38B3A7"
  1018 + android:layout_width="1dp"
  1019 + android:layout_height="match_parent"/>
  1020 + <TextView
  1021 + android:text="进步\n幅度"
  1022 + android:textSize="13sp"
  1023 + android:textColor="@color/white"
  1024 + android:gravity="center"
  1025 + android:layout_weight="50"
  1026 + android:layout_width="0dp"
  1027 + android:layout_height="match_parent"/>
  1028 + <View
  1029 + android:background="#38B3A7"
  1030 + android:layout_width="1dp"
  1031 + android:layout_height="match_parent"/>
  1032 + <TextView
  1033 + android:text="正答\n率"
  1034 + android:textSize="13sp"
  1035 + android:textColor="@color/white"
  1036 + android:gravity="center"
  1037 + android:layout_weight="38"
  1038 + android:layout_width="0dp"
  1039 + android:layout_height="match_parent"/>
  1040 + </LinearLayout>
  1041 + <androidx.recyclerview.widget.RecyclerView
  1042 + android:id="@+id/rvPoint"
  1043 + android:orientation="vertical"
  1044 + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
  1045 + app:reverseLayout="false"
  1046 + android:layout_width="match_parent"
  1047 + android:layout_height="wrap_content"/>
  1048 + </LinearLayout>
  1049 +
  1050 + <LinearLayout
  1051 + android:id="@+id/flPointDesc"
  1052 + android:orientation="horizontal"
  1053 + android:gravity="center_vertical"
  1054 + android:layout_marginTop="10dp"
  1055 + android:layout_width="match_parent"
  1056 + android:layout_height="wrap_content">
  1057 + <ImageView
  1058 + android:src="@drawable/png_up"
  1059 + android:layout_width="12dp"
  1060 + android:layout_height="12dp"/>
  1061 + <TextView
  1062 + android:text="代表进步幅度最大的知识点"
  1063 + android:textSize="12sp"
  1064 + android:textColor="#666"
  1065 + android:layout_marginStart="8dp"
  1066 + android:layout_width="wrap_content"
  1067 + android:layout_height="wrap_content"/>
  1068 + </LinearLayout>
  1069 +
  1070 + </LinearLayout>
  1071 + </LinearLayout>
  1072 +
  1073 +</androidx.core.widget.NestedScrollView>
  1074 +</FrameLayout>
0 1075 \ No newline at end of file
... ...
app/src/main/res/layout/activity_huyou_detail_a4.xml
... ... @@ -0,0 +1,1079 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<FrameLayout
  3 + xmlns:android="http://schemas.android.com/apk/res/android"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + xmlns:app="http://schemas.android.com/apk/res-auto"
  6 + tools:ignore="HardcodedText,ContentDescription,SmallSp,UseCompoundDrawables,RtlSymmetry"
  7 + android:layout_width="match_parent"
  8 + android:layout_height="match_parent">
  9 + <LinearLayout
  10 + android:id="@+id/root"
  11 + android:transformPivotX="0px"
  12 + android:transformPivotY="0px"
  13 + android:orientation="vertical"
  14 + android:background="@drawable/bg_huyou_a4"
  15 + android:layout_width="756dp"
  16 + android:layout_height="1069dp"
  17 + tools:ignore="UselessParent">
  18 +
  19 +
  20 + <FrameLayout
  21 + android:orientation="horizontal"
  22 + android:elevation="2dp"
  23 + android:paddingHorizontal="30dp"
  24 + android:layout_marginTop="60dp"
  25 + android:layout_width="match_parent"
  26 + android:layout_height="wrap_content">
  27 + <FrameLayout
  28 + android:id="@+id/toolbar"
  29 + android:layout_gravity="center_vertical"
  30 + android:layout_width="match_parent"
  31 + android:layout_height="wrap_content">
  32 + <TextView
  33 + android:id="@+id/btnSwitch"
  34 + android:text="看长图"
  35 + android:textSize="20sp"
  36 + android:textColor="#333"
  37 + android:layout_marginStart="48dp"
  38 + android:layout_width="wrap_content"
  39 + android:layout_height="wrap_content"/>
  40 + <TextView
  41 + android:id="@+id/btnShare"
  42 + android:text="分享"
  43 + android:textSize="20sp"
  44 + android:textColor="#333"
  45 + android:layout_width="wrap_content"
  46 + android:layout_height="wrap_content"/>
  47 + <TextView
  48 + android:id="@+id/btnSame"
  49 + android:visibility="gone"
  50 + android:text="举一反三"
  51 + android:textSize="20sp"
  52 + android:textColor="#333"
  53 + android:layout_gravity="end"
  54 + android:layout_width="wrap_content"
  55 + android:layout_height="wrap_content"/>
  56 + </FrameLayout>
  57 + <TextView
  58 + android:id="@+id/tvTitle"
  59 + android:text="周作业学习报告"
  60 + android:textSize="37sp"
  61 + android:textColor="#333"
  62 + android:textStyle="bold"
  63 + android:layout_gravity="center_horizontal"
  64 + android:layout_width="wrap_content"
  65 + android:layout_height="wrap_content" />
  66 + </FrameLayout>
  67 +
  68 +
  69 + <ImageView
  70 + android:src="@drawable/png_huyou_top_bg"
  71 + android:elevation="1dp"
  72 + android:layout_gravity="end"
  73 + android:layout_marginHorizontal="30dp"
  74 + android:layout_marginTop="-40dp"
  75 + android:layout_width="206dp"
  76 + android:layout_height="180dp"/>
  77 +
  78 + <LinearLayout
  79 + android:orientation="vertical"
  80 + android:background="@drawable/png_info_bg"
  81 + android:padding="30dp"
  82 + android:layout_marginHorizontal="30dp"
  83 + android:layout_marginTop="-120dp"
  84 + android:layout_width="match_parent"
  85 + android:layout_height="267dp">
  86 + <LinearLayout
  87 + android:orientation="horizontal"
  88 + android:layout_width="match_parent"
  89 + android:layout_height="wrap_content">
  90 + <androidx.constraintlayout.utils.widget.ImageFilterView
  91 + android:id="@+id/ivAvatar"
  92 + tools:background="#2491FF"
  93 + app:round="40dp"
  94 + android:layout_width="80dp"
  95 + android:layout_height="80dp"/>
  96 + <LinearLayout
  97 + android:orientation="vertical"
  98 + android:layout_gravity="center_vertical"
  99 + android:layout_marginStart="10dp"
  100 + android:layout_width="wrap_content"
  101 + android:layout_height="wrap_content">
  102 + <TextView
  103 + android:id="@+id/tvStuName"
  104 + tools:text="杨同学 "
  105 + android:textSize="28sp"
  106 + android:textColor="#333"
  107 + android:textStyle="bold"
  108 + android:layout_width="wrap_content"
  109 + android:layout_height="wrap_content"/>
  110 + <TextView
  111 + android:id="@+id/tvGrade"
  112 + tools:text="七年级"
  113 + android:textSize="26sp"
  114 + android:textColor="#666"
  115 + android:textStyle="bold"
  116 + android:layout_width="wrap_content"
  117 + android:layout_height="wrap_content"/>
  118 + </LinearLayout>
  119 + </LinearLayout>
  120 + <LinearLayout
  121 + android:orientation="horizontal"
  122 + android:background="@drawable/shape_radius_10"
  123 + android:backgroundTint="#F4FAFF"
  124 + android:layout_marginTop="16dp"
  125 + android:layout_width="match_parent"
  126 + android:layout_height="120dp">
  127 + <LinearLayout
  128 + android:orientation="vertical"
  129 + android:gravity="center"
  130 + android:layout_width="0dp"
  131 + android:layout_height="match_parent"
  132 + android:layout_weight="1">
  133 + <LinearLayout
  134 + android:paddingEnd="40dp"
  135 + android:gravity="center_vertical"
  136 + android:layout_width="wrap_content"
  137 + android:layout_height="wrap_content">
  138 + <ImageView
  139 + android:src="@drawable/png_iv_subject"
  140 + android:layout_marginEnd="10dp"
  141 + android:layout_width="32dp"
  142 + android:layout_height="28dp"/>
  143 + <TextView
  144 + android:text="学科"
  145 + android:textSize="24sp"
  146 + android:textColor="#333"
  147 + android:textStyle="bold"
  148 + android:layout_width="wrap_content"
  149 + android:layout_height="wrap_content"/>
  150 + </LinearLayout>
  151 + <TextView
  152 + android:id="@+id/tvSubject"
  153 + tools:text="数学"
  154 + android:textSize="24sp"
  155 + android:textColor="#3BC3B6"
  156 + android:textStyle="bold"
  157 + android:layout_marginTop="8dp"
  158 + android:layout_width="wrap_content"
  159 + android:layout_height="wrap_content"/>
  160 + </LinearLayout>
  161 + <LinearLayout
  162 + android:orientation="vertical"
  163 + android:gravity="center"
  164 + android:layout_width="0dp"
  165 + android:layout_height="match_parent"
  166 + android:layout_weight="1">
  167 + <LinearLayout
  168 + android:paddingEnd="40dp"
  169 + android:gravity="center_vertical"
  170 + android:layout_width="wrap_content"
  171 + android:layout_height="wrap_content">
  172 + <ImageView
  173 + android:src="@drawable/png_ic_during"
  174 + android:layout_marginEnd="10dp"
  175 + android:layout_width="14dp"
  176 + android:layout_height="13dp"/>
  177 + <TextView
  178 + android:text="周期"
  179 + android:textSize="24sp"
  180 + android:textColor="#333"
  181 + android:textStyle="bold"
  182 + android:layout_width="wrap_content"
  183 + android:layout_height="wrap_content"/>
  184 + </LinearLayout>
  185 + <TextView
  186 + android:id="@+id/tvDate"
  187 + tools:text="2024.09.01-2024.09.30"
  188 + android:textSize="24sp"
  189 + android:textColor="#3BC3B6"
  190 + android:textStyle="bold"
  191 + android:layout_marginTop="8dp"
  192 + android:layout_width="wrap_content"
  193 + android:layout_height="wrap_content"/>
  194 + </LinearLayout>
  195 + </LinearLayout>
  196 + </LinearLayout>
  197 + <Space
  198 + android:id="@+id/splitLine"
  199 + android:layout_width="match_parent"
  200 + android:layout_height="0dp"/>
  201 +
  202 + <HorizontalScrollView
  203 + android:scrollbars="none"
  204 + android:layout_marginTop="25dp"
  205 + android:layout_marginHorizontal="16dp"
  206 + android:layout_width="match_parent"
  207 + android:layout_height="match_parent">
  208 + <LinearLayout
  209 + android:orientation="horizontal"
  210 + android:layout_width="wrap_content"
  211 + android:layout_height="match_parent">
  212 + <LinearLayout
  213 + android:orientation="vertical"
  214 + android:background="@drawable/shape_radius_10"
  215 + android:backgroundTint="@color/white"
  216 + android:padding="12dp"
  217 + android:layout_marginHorizontal="14dp"
  218 + android:layout_width="335dp"
  219 + android:layout_height="613dp">
  220 + <TextView
  221 + android:text="薄弱知识点总评"
  222 + android:textSize="16sp"
  223 + android:textColor="#333333"
  224 + android:textStyle="bold"
  225 + android:background="@drawable/bg_hy_weak_title"
  226 + android:paddingStart="20dp"
  227 + android:paddingEnd="4dp"
  228 + android:layout_marginTop="8dp"
  229 + android:layout_gravity="center_horizontal"
  230 + android:layout_width="wrap_content"
  231 + android:layout_height="wrap_content"/>
  232 + <LinearLayout
  233 + android:orientation="vertical"
  234 + android:layout_marginTop="40dp"
  235 + android:layout_width="match_parent"
  236 + android:layout_height="wrap_content">
  237 + <TextView
  238 + android:text="学习前"
  239 + android:textSize="12sp"
  240 + android:textColor="#333"
  241 + android:layout_gravity="center_horizontal"
  242 + android:layout_width="wrap_content"
  243 + android:layout_height="wrap_content"/>
  244 + <FrameLayout
  245 + android:background="@drawable/png_huyou_progress_bg"
  246 + android:padding="10dp"
  247 + android:layout_gravity="center_horizontal"
  248 + android:layout_marginTop="16dp"
  249 + android:layout_width="172dp"
  250 + android:layout_height="172dp">
  251 + <com.littlejie.circleprogress.CircleProgress
  252 + android:id="@+id/cpBefore"
  253 + app:arcWidth="20dp"
  254 + app:bgArcWidth="20dp"
  255 + app:arcColors="#F36A27"
  256 + app:bgArcColor="#FFF1EA"
  257 + app:startAngle="-90"
  258 + app:sweepAngle="360"
  259 + app:maxValue="100"
  260 + app:value="0"
  261 + app:hintColor="@color/transparent"
  262 + app:unitColor="@color/transparent"
  263 + app:valueColor="@color/transparent"
  264 + android:layout_width="match_parent"
  265 + android:layout_height="match_parent"/>
  266 + <LinearLayout
  267 + android:orientation="vertical"
  268 + android:gravity="center_horizontal"
  269 + android:layout_gravity="center"
  270 + android:layout_width="wrap_content"
  271 + android:layout_height="wrap_content">
  272 + <LinearLayout
  273 + android:layout_width="wrap_content"
  274 + android:layout_height="wrap_content">
  275 + <TextView
  276 + android:id="@+id/pgBefore"
  277 + tools:text="88"
  278 + android:textSize="34sp"
  279 + android:textColor="#EA5127"
  280 + android:textStyle="bold"
  281 + android:layout_width="wrap_content"
  282 + android:layout_height="wrap_content"/>
  283 + <TextView
  284 + android:text="%"
  285 + android:textSize="16sp"
  286 + android:textColor="#EA5127"
  287 + android:layout_width="wrap_content"
  288 + android:layout_height="wrap_content"/>
  289 + </LinearLayout>
  290 + <TextView
  291 + android:text="整体掌握程度"
  292 + android:textSize="14sp"
  293 + android:textColor="#333"
  294 + android:textStyle="bold"
  295 + android:layout_marginTop="-2dp"
  296 + android:layout_width="wrap_content"
  297 + android:layout_height="wrap_content"/>
  298 + </LinearLayout>
  299 + </FrameLayout>
  300 + </LinearLayout>
  301 + <LinearLayout
  302 + android:orientation="vertical"
  303 + android:layout_marginTop="20dp"
  304 + android:layout_width="match_parent"
  305 + android:layout_height="wrap_content">
  306 + <TextView
  307 + android:text="学习后"
  308 + android:textSize="12sp"
  309 + android:textColor="#333"
  310 + android:layout_gravity="center_horizontal"
  311 + android:layout_width="wrap_content"
  312 + android:layout_height="wrap_content"/>
  313 + <FrameLayout
  314 + android:background="@drawable/png_huyou_progress_bg"
  315 + android:padding="10dp"
  316 + android:layout_gravity="center_horizontal"
  317 + android:layout_marginTop="16dp"
  318 + android:layout_width="172dp"
  319 + android:layout_height="172dp">
  320 + <com.littlejie.circleprogress.CircleProgress
  321 + android:id="@+id/cpAfter"
  322 + app:arcWidth="20dp"
  323 + app:bgArcWidth="20dp"
  324 + app:arcColors="#3BC3B6"
  325 + app:bgArcColor="#C2FCF6"
  326 + app:startAngle="-90"
  327 + app:sweepAngle="360"
  328 + app:maxValue="100"
  329 + app:value="0"
  330 + app:hintColor="@color/transparent"
  331 + app:unitColor="@color/transparent"
  332 + app:valueColor="@color/transparent"
  333 + android:layout_width="match_parent"
  334 + android:layout_height="match_parent"/>
  335 + <LinearLayout
  336 + android:orientation="vertical"
  337 + android:gravity="center_horizontal"
  338 + android:layout_gravity="center"
  339 + android:layout_width="wrap_content"
  340 + android:layout_height="wrap_content">
  341 + <LinearLayout
  342 + android:layout_width="wrap_content"
  343 + android:layout_height="wrap_content">
  344 + <TextView
  345 + android:id="@+id/pgAfter"
  346 + tools:text="88"
  347 + android:textSize="34sp"
  348 + android:textColor="#3BC3B6"
  349 + android:textStyle="bold"
  350 + android:layout_width="wrap_content"
  351 + android:layout_height="wrap_content"/>
  352 + <TextView
  353 + android:text="%"
  354 + android:textSize="16sp"
  355 + android:textColor="#3BC3B6"
  356 + android:layout_width="wrap_content"
  357 + android:layout_height="wrap_content"/>
  358 + </LinearLayout>
  359 + <TextView
  360 + android:text="整体掌握程度"
  361 + android:textSize="14sp"
  362 + android:textColor="#333"
  363 + android:textStyle="bold"
  364 + android:layout_marginTop="-2dp"
  365 + android:layout_width="wrap_content"
  366 + android:layout_height="wrap_content"/>
  367 + </LinearLayout>
  368 + </FrameLayout>
  369 + </LinearLayout>
  370 +
  371 + <FrameLayout
  372 + android:layout_marginTop="10dp"
  373 + android:layout_width="match_parent"
  374 + android:layout_height="wrap_content">
  375 + <ImageView
  376 + android:src="@drawable/png_hy_weak_comment"
  377 + android:layout_width="16dp"
  378 + android:layout_height="18dp"/>
  379 + <TextView
  380 + android:id="@+id/tvWeakRate"
  381 + android:textSize="14sp"
  382 + android:textColor="#333"
  383 + android:layout_marginTop="1dp"
  384 + android:lineSpacingMultiplier="1.3"
  385 + android:layout_width="wrap_content"
  386 + android:layout_height="wrap_content"/>
  387 + </FrameLayout>
  388 + </LinearLayout>
  389 +
  390 + <LinearLayout
  391 + android:orientation="vertical"
  392 + android:background="@drawable/shape_radius_10"
  393 + android:backgroundTint="@color/white"
  394 + android:padding="12dp"
  395 + android:layout_marginHorizontal="14dp"
  396 + android:layout_width="335dp"
  397 + android:layout_height="613dp">
  398 +
  399 + <TextView
  400 + android:text="作业概括"
  401 + android:textSize="16sp"
  402 + android:textColor="#333333"
  403 + android:textStyle="bold"
  404 + android:background="@drawable/bg_hy_summary_title"
  405 + android:paddingStart="28dp"
  406 + android:paddingEnd="4dp"
  407 + android:layout_marginTop="8dp"
  408 + android:layout_gravity="center_horizontal"
  409 + android:layout_width="wrap_content"
  410 + android:layout_height="wrap_content"/>
  411 + <LinearLayout
  412 + android:orientation="horizontal"
  413 + android:background="@drawable/shape_radius_5"
  414 + android:backgroundTint="#F4FAFF"
  415 + android:layout_width="match_parent"
  416 + android:layout_height="58dp"
  417 + android:layout_marginTop="40dp">
  418 + <LinearLayout
  419 + android:orientation="vertical"
  420 + android:gravity="center"
  421 + android:layout_width="0dp"
  422 + android:layout_height="match_parent"
  423 + android:layout_weight="1">
  424 + <LinearLayout
  425 + android:orientation="horizontal"
  426 + android:gravity="center_vertical"
  427 + android:layout_width="wrap_content"
  428 + android:layout_height="wrap_content">
  429 + <ImageView
  430 + android:src="@drawable/png_icon_statistical_accuracy"
  431 + android:layout_width="12dp"
  432 + android:layout_height="13dp"/>
  433 + <TextView
  434 + android:text="作业正确率"
  435 + android:textSize="11sp"
  436 + android:textColor="#333"
  437 + android:textStyle="bold"
  438 + android:layout_marginStart="5dp"
  439 + android:layout_width="wrap_content"
  440 + android:layout_height="wrap_content"/>
  441 + </LinearLayout>
  442 + <LinearLayout
  443 + android:orientation="horizontal"
  444 + android:layout_marginTop="8dp"
  445 + android:layout_width="wrap_content"
  446 + android:layout_height="wrap_content">
  447 + <TextView
  448 + android:id="@+id/tvTotalRate"
  449 + tools:text="88"
  450 + android:textSize="14sp"
  451 + android:textColor="#3BC3B6"
  452 + android:textStyle="bold"
  453 + android:layout_width="wrap_content"
  454 + android:layout_height="wrap_content"/>
  455 + <TextView
  456 + android:text="%"
  457 + android:textSize="9sp"
  458 + android:textColor="#3BC3B6"
  459 + android:textStyle="bold"
  460 + android:layout_width="wrap_content"
  461 + android:layout_height="wrap_content"/>
  462 + </LinearLayout>
  463 + </LinearLayout>
  464 + <View
  465 + android:background="#9ECAFC"
  466 + android:layout_marginVertical="8dp"
  467 + android:layout_width="1dp"
  468 + android:layout_height="match_parent"/>
  469 + <LinearLayout
  470 + android:orientation="vertical"
  471 + android:gravity="center"
  472 + android:layout_width="0dp"
  473 + android:layout_height="match_parent"
  474 + android:layout_weight="1">
  475 + <LinearLayout
  476 + android:orientation="horizontal"
  477 + android:gravity="center_vertical"
  478 + android:layout_width="wrap_content"
  479 + android:layout_height="wrap_content">
  480 + <ImageView
  481 + android:src="@drawable/png_icon_statistical_accuracy"
  482 + android:layout_width="12dp"
  483 + android:layout_height="13dp"/>
  484 + <TextView
  485 + android:text="答对题数"
  486 + android:textSize="11sp"
  487 + android:textColor="#333"
  488 + android:textStyle="bold"
  489 + android:layout_marginStart="5dp"
  490 + android:layout_width="wrap_content"
  491 + android:layout_height="wrap_content"/>
  492 + </LinearLayout>
  493 + <LinearLayout
  494 + android:orientation="horizontal"
  495 + android:layout_marginTop="8dp"
  496 + android:layout_width="wrap_content"
  497 + android:layout_height="wrap_content">
  498 + <TextView
  499 + android:id="@+id/tvTotalCorrect"
  500 + tools:text="88"
  501 + android:textSize="14sp"
  502 + android:textColor="#3BC3B6"
  503 + android:textStyle="bold"
  504 + android:layout_width="wrap_content"
  505 + android:layout_height="wrap_content"/>
  506 + <TextView
  507 + android:text="道"
  508 + android:textSize="9sp"
  509 + android:textColor="#3BC3B6"
  510 + android:textStyle="bold"
  511 + android:layout_width="wrap_content"
  512 + android:layout_height="wrap_content"/>
  513 + </LinearLayout>
  514 + </LinearLayout>
  515 + <View
  516 + android:background="#9ECAFC"
  517 + android:layout_marginVertical="8dp"
  518 + android:layout_width="1dp"
  519 + android:layout_height="match_parent"/>
  520 + <LinearLayout
  521 + android:orientation="vertical"
  522 + android:gravity="center"
  523 + android:layout_width="0dp"
  524 + android:layout_height="match_parent"
  525 + android:layout_weight="1">
  526 + <LinearLayout
  527 + android:orientation="horizontal"
  528 + android:gravity="center_vertical"
  529 + android:layout_width="wrap_content"
  530 + android:layout_height="wrap_content">
  531 + <ImageView
  532 + android:src="@drawable/png_icon_statistical_accuracy"
  533 + android:layout_width="12dp"
  534 + android:layout_height="13dp"/>
  535 + <TextView
  536 + android:text="答错题数"
  537 + android:textSize="11sp"
  538 + android:textColor="#333"
  539 + android:textStyle="bold"
  540 + android:layout_marginStart="5dp"
  541 + android:layout_width="wrap_content"
  542 + android:layout_height="wrap_content"/>
  543 + </LinearLayout>
  544 + <LinearLayout
  545 + android:orientation="horizontal"
  546 + android:layout_marginTop="8dp"
  547 + android:layout_width="wrap_content"
  548 + android:layout_height="wrap_content">
  549 + <TextView
  550 + android:id="@+id/tvTotalError"
  551 + tools:text="88"
  552 + android:textSize="14sp"
  553 + android:textColor="#3BC3B6"
  554 + android:textStyle="bold"
  555 + android:layout_width="wrap_content"
  556 + android:layout_height="wrap_content"/>
  557 + <TextView
  558 + android:text="道"
  559 + android:textSize="9sp"
  560 + android:textColor="#3BC3B6"
  561 + android:textStyle="bold"
  562 + android:layout_width="wrap_content"
  563 + android:layout_height="wrap_content"/>
  564 + </LinearLayout>
  565 + </LinearLayout>
  566 + </LinearLayout>
  567 +
  568 + <TextView
  569 + android:text="每日作业正确率"
  570 + android:textSize="13sp"
  571 + android:textColor="#333"
  572 + android:textStyle="bold"
  573 + android:layout_gravity="center_horizontal"
  574 + android:layout_marginTop="68dp"
  575 + android:layout_width="wrap_content"
  576 + android:layout_height="wrap_content"/>
  577 + <com.github.mikephil.charting.charts.LineChart
  578 + android:id="@+id/lineChart"
  579 + android:layout_width="match_parent"
  580 + android:layout_height="220dp"/>
  581 + <Space style="@style/empty_space"/>
  582 + <FrameLayout
  583 + android:layout_width="match_parent"
  584 + android:layout_height="wrap_content">
  585 + <ImageView
  586 + android:src="@drawable/png_hy_summary_comment"
  587 + android:layout_width="16dp"
  588 + android:layout_height="20dp"/>
  589 + <TextView
  590 + android:id="@+id/tvRating"
  591 + android:textSize="14sp"
  592 + android:textColor="#333"
  593 + android:lineSpacingMultiplier="1.3"
  594 + android:layout_marginTop="2dp"
  595 + android:layout_width="match_parent"
  596 + android:layout_height="wrap_content"/>
  597 + </FrameLayout>
  598 + </LinearLayout>
  599 +
  600 + <LinearLayout
  601 + android:orientation="vertical"
  602 + android:background="@drawable/shape_radius_10"
  603 + android:backgroundTint="@color/white"
  604 + android:padding="12dp"
  605 + android:layout_marginHorizontal="14dp"
  606 + android:layout_width="335dp"
  607 + android:layout_height="472dp">
  608 + <TextView
  609 + android:text="知识点掌握情况"
  610 + android:textSize="16sp"
  611 + android:textColor="#333333"
  612 + android:textStyle="bold"
  613 + android:background="@drawable/bg_hy_point_title"
  614 + android:paddingStart="28dp"
  615 + android:paddingEnd="4dp"
  616 + android:layout_marginTop="8dp"
  617 + android:layout_gravity="center_horizontal"
  618 + android:layout_width="wrap_content"
  619 + android:layout_height="wrap_content"/>
  620 +
  621 + <LinearLayout
  622 + android:orientation="horizontal"
  623 + android:layout_width="match_parent"
  624 + android:layout_height="70dp"
  625 + android:layout_marginTop="48dp">
  626 + <LinearLayout
  627 + android:orientation="vertical"
  628 + android:background="@drawable/shape_radius_10"
  629 + android:backgroundTint="#F4FAFF"
  630 + android:gravity="center_horizontal"
  631 + android:paddingTop="8dp"
  632 + android:layout_width="0dp"
  633 + android:layout_height="match_parent"
  634 + android:layout_weight="1">
  635 + <ImageView
  636 + android:src="@drawable/png_ic_excellent"
  637 + android:backgroundTint="#3BC3B6"
  638 + android:background="@drawable/bg_circle"
  639 + android:padding="4dp"
  640 + android:layout_width="20dp"
  641 + android:layout_height="20dp"/>
  642 + <TextView
  643 + android:id="@+id/tvExcellent"
  644 + android:text="-"
  645 + android:textColor="#3BC3B6"
  646 + android:textSize="13sp"
  647 + android:textStyle="bold"
  648 + android:layout_marginTop="4dp"
  649 + android:layout_width="wrap_content"
  650 + android:layout_height="wrap_content"/>
  651 + <TextView
  652 + android:text="掌握优秀"
  653 + android:textSize="10sp"
  654 + android:textColor="#333"
  655 + android:textStyle="bold"
  656 + android:layout_width="wrap_content"
  657 + android:layout_height="wrap_content"/>
  658 + </LinearLayout>
  659 + <LinearLayout
  660 + android:orientation="vertical"
  661 + android:background="@drawable/shape_radius_10"
  662 + android:backgroundTint="#F4FAFF"
  663 + android:gravity="center_horizontal"
  664 + android:paddingTop="8dp"
  665 + android:layout_marginStart="14dp"
  666 + android:layout_width="0dp"
  667 + android:layout_height="match_parent"
  668 + android:layout_weight="1">
  669 + <ImageView
  670 + android:src="@drawable/png_ic_good"
  671 + android:backgroundTint="#489AFA"
  672 + android:background="@drawable/bg_circle"
  673 + android:padding="4dp"
  674 + android:layout_width="20dp"
  675 + android:layout_height="20dp"/>
  676 + <TextView
  677 + android:id="@+id/tvGood"
  678 + android:text="-"
  679 + android:textColor="#489AFA"
  680 + android:textSize="13sp"
  681 + android:textStyle="bold"
  682 + android:layout_marginTop="4dp"
  683 + android:layout_width="wrap_content"
  684 + android:layout_height="wrap_content"/>
  685 + <TextView
  686 + android:text="掌握良好"
  687 + android:textSize="10sp"
  688 + android:textColor="#333"
  689 + android:textStyle="bold"
  690 + android:layout_width="wrap_content"
  691 + android:layout_height="wrap_content"/>
  692 + </LinearLayout>
  693 + <LinearLayout
  694 + android:orientation="vertical"
  695 + android:background="@drawable/shape_radius_10"
  696 + android:backgroundTint="#F4FAFF"
  697 + android:gravity="center_horizontal"
  698 + android:paddingTop="8dp"
  699 + android:layout_marginStart="14dp"
  700 + android:layout_width="0dp"
  701 + android:layout_height="match_parent"
  702 + android:layout_weight="1">
  703 + <ImageView
  704 + android:src="@drawable/png_ic_normal"
  705 + android:backgroundTint="#F58725"
  706 + android:background="@drawable/bg_circle"
  707 + android:padding="4dp"
  708 + android:layout_width="20dp"
  709 + android:layout_height="20dp"/>
  710 + <TextView
  711 + android:id="@+id/tvNormal"
  712 + android:text="-"
  713 + android:textColor="#F58725"
  714 + android:textSize="13sp"
  715 + android:textStyle="bold"
  716 + android:layout_marginTop="4dp"
  717 + android:layout_width="wrap_content"
  718 + android:layout_height="wrap_content"/>
  719 + <TextView
  720 + android:text="掌握一般"
  721 + android:textSize="10sp"
  722 + android:textColor="#333"
  723 + android:textStyle="bold"
  724 + android:layout_width="wrap_content"
  725 + android:layout_height="wrap_content"/>
  726 + </LinearLayout>
  727 + <LinearLayout
  728 + android:orientation="vertical"
  729 + android:background="@drawable/shape_radius_10"
  730 + android:backgroundTint="#F4FAFF"
  731 + android:gravity="center_horizontal"
  732 + android:paddingTop="8dp"
  733 + android:layout_marginStart="14dp"
  734 + android:layout_width="0dp"
  735 + android:layout_height="match_parent"
  736 + android:layout_weight="1">
  737 + <ImageView
  738 + android:src="@drawable/png_ic_weak"
  739 + android:backgroundTint="#EA5127"
  740 + android:background="@drawable/bg_circle"
  741 + android:padding="4dp"
  742 + android:layout_width="20dp"
  743 + android:layout_height="20dp"/>
  744 + <TextView
  745 + android:id="@+id/tvWeak"
  746 + android:text="-"
  747 + android:textColor="#EA5127"
  748 + android:textSize="13sp"
  749 + android:textStyle="bold"
  750 + android:layout_marginTop="4dp"
  751 + android:layout_width="wrap_content"
  752 + android:layout_height="wrap_content"/>
  753 + <TextView
  754 + android:text="掌握薄弱"
  755 + android:textSize="10sp"
  756 + android:textColor="#333"
  757 + android:textStyle="bold"
  758 + android:layout_width="wrap_content"
  759 + android:layout_height="wrap_content"/>
  760 + </LinearLayout>
  761 + </LinearLayout>
  762 +
  763 + <FrameLayout
  764 + android:layout_gravity="center_horizontal"
  765 + android:layout_marginTop="36dp"
  766 + android:layout_width="238dp"
  767 + android:layout_height="238dp">
  768 + <com.littlejie.circleprogress.CircleProgress
  769 + android:id="@+id/cpBase"
  770 + app:value="0"
  771 + app:arcWidth="48dp"
  772 + app:bgArcWidth="48dp"
  773 + app:bgArcColor="#3BC3B6"
  774 + app:startAngle="0"
  775 + app:sweepAngle="360"
  776 + app:hintColor="@color/transparent"
  777 + app:unitColor="@color/transparent"
  778 + app:valueColor="@color/transparent"
  779 + android:layout_width="match_parent"
  780 + android:layout_height="match_parent"/>
  781 + <com.littlejie.circleprogress.CircleProgress
  782 + android:id="@+id/cpGood"
  783 + app:value="0"
  784 + app:arcWidth="48dp"
  785 + app:bgArcWidth="48dp"
  786 + app:arcColors="#489AFA"
  787 + app:bgArcColor="@color/transparent"
  788 + app:startAngle="0"
  789 + app:sweepAngle="360"
  790 + app:hintColor="@color/transparent"
  791 + app:unitColor="@color/transparent"
  792 + app:valueColor="@color/transparent"
  793 + android:layout_width="match_parent"
  794 + android:layout_height="match_parent"/>
  795 + <com.littlejie.circleprogress.CircleProgress
  796 + android:id="@+id/cpNormal"
  797 + app:value="0"
  798 + app:arcWidth="48dp"
  799 + app:bgArcWidth="48dp"
  800 + app:arcColors="#F58725"
  801 + app:bgArcColor="@color/transparent"
  802 + app:startAngle="0"
  803 + app:sweepAngle="360"
  804 + app:hintColor="@color/transparent"
  805 + app:unitColor="@color/transparent"
  806 + app:valueColor="@color/transparent"
  807 + android:layout_width="match_parent"
  808 + android:layout_height="match_parent"/>
  809 + <com.littlejie.circleprogress.CircleProgress
  810 + android:id="@+id/cpWeak"
  811 + app:value="0"
  812 + app:arcWidth="48dp"
  813 + app:bgArcWidth="48dp"
  814 + app:arcColors="#EA5127"
  815 + app:bgArcColor="@color/transparent"
  816 + app:startAngle="0"
  817 + app:sweepAngle="360"
  818 + app:hintColor="@color/transparent"
  819 + app:unitColor="@color/transparent"
  820 + app:valueColor="@color/transparent"
  821 + android:layout_width="match_parent"
  822 + android:layout_height="match_parent"/>
  823 +
  824 + <LinearLayout
  825 + android:orientation="vertical"
  826 + android:gravity="center_horizontal"
  827 + android:layout_gravity="center"
  828 + android:layout_width="wrap_content"
  829 + android:layout_height="wrap_content">
  830 + <LinearLayout
  831 + android:layout_width="wrap_content"
  832 + android:layout_height="wrap_content">
  833 + <TextView
  834 + android:id="@+id/tvAvePoint"
  835 + tools:text="88"
  836 + android:textSize="34sp"
  837 + android:textColor="#3BC3B6"
  838 + android:textStyle="bold"
  839 + android:layout_width="wrap_content"
  840 + android:layout_height="wrap_content"/>
  841 + <TextView
  842 + android:text="%"
  843 + android:textSize="16sp"
  844 + android:textColor="#3BC3B6"
  845 + android:layout_width="wrap_content"
  846 + android:layout_height="wrap_content"/>
  847 + </LinearLayout>
  848 + <TextView
  849 + android:text="综合掌握程度"
  850 + android:textSize="16sp"
  851 + android:textColor="#333"
  852 + android:textStyle="bold"
  853 + android:layout_marginTop="-2dp"
  854 + android:layout_width="wrap_content"
  855 + android:layout_height="wrap_content"/>
  856 + </LinearLayout>
  857 + </FrameLayout>
  858 + </LinearLayout>
  859 +
  860 + <LinearLayout
  861 + android:orientation="vertical"
  862 + android:background="@drawable/shape_radius_10"
  863 + android:backgroundTint="@color/white"
  864 + android:padding="16dp"
  865 + android:layout_marginHorizontal="14dp"
  866 + android:layout_width="335dp"
  867 + android:layout_height="472dp">
  868 + <TextView
  869 + android:text="学习效果分析"
  870 + android:textSize="16sp"
  871 + android:textColor="#333333"
  872 + android:textStyle="bold"
  873 + android:background="@drawable/bg_hy_analyse_title"
  874 + android:paddingStart="24dp"
  875 + android:paddingEnd="4dp"
  876 + android:layout_marginTop="4dp"
  877 + android:layout_gravity="center_horizontal"
  878 + android:layout_width="wrap_content"
  879 + android:layout_height="wrap_content"/>
  880 +
  881 + <LinearLayout
  882 + android:id="@+id/flEmptyPoints"
  883 + android:visibility="gone"
  884 + android:orientation="vertical"
  885 + android:gravity="center_horizontal"
  886 + android:layout_marginTop="80dp"
  887 + android:layout_width="match_parent"
  888 + android:layout_height="wrap_content">
  889 + <ImageView
  890 + android:src="@drawable/png_huyou_points_empty"
  891 + android:layout_width="195dp"
  892 + android:layout_height="145dp"/>
  893 + <TextView
  894 + android:text="你太棒了!"
  895 + android:textSize="20sp"
  896 + android:textColor="#999"
  897 + android:layout_marginVertical="16dp"
  898 + android:layout_width="wrap_content"
  899 + android:layout_height="wrap_content"/>
  900 + </LinearLayout>
  901 +
  902 +
  903 + <LinearLayout
  904 + android:id="@+id/tableRoot"
  905 + android:orientation="vertical"
  906 + android:background="@drawable/bg_huyou_table_bg"
  907 + android:layout_marginTop="16dp"
  908 + android:layout_width="match_parent"
  909 + android:layout_height="wrap_content">
  910 + <LinearLayout
  911 + android:orientation="horizontal"
  912 + android:background="#50CEC2"
  913 + android:layout_width="match_parent"
  914 + android:layout_height="60dp">
  915 + <TextView
  916 + android:text="知识点名称"
  917 + android:textSize="13sp"
  918 + android:textColor="@color/white"
  919 + android:gravity="center"
  920 + android:layout_weight="82"
  921 + android:layout_width="0dp"
  922 + android:layout_height="match_parent"/>
  923 + <View
  924 + android:background="#38B3A7"
  925 + android:layout_width="1dp"
  926 + android:layout_height="match_parent"/>
  927 +
  928 + <LinearLayout
  929 + android:orientation="vertical"
  930 + android:layout_weight="72"
  931 + android:layout_width="0dp"
  932 + android:layout_height="match_parent">
  933 + <TextView
  934 + android:text="学前"
  935 + android:textSize="13sp"
  936 + android:textColor="@color/white"
  937 + android:gravity="center"
  938 + android:layout_width="match_parent"
  939 + android:layout_height="24dp"/>
  940 + <View
  941 + android:background="#38B3A7"
  942 + android:layout_width="match_parent"
  943 + android:layout_height="1dp"/>
  944 + <LinearLayout
  945 + android:orientation="horizontal"
  946 + android:layout_width="match_parent"
  947 + android:layout_height="match_parent">
  948 + <TextView
  949 + android:text="程\n度"
  950 + android:textSize="13sp"
  951 + android:textColor="@color/white"
  952 + android:gravity="center"
  953 + android:layout_weight="1"
  954 + android:layout_width="0dp"
  955 + android:layout_height="wrap_content"/>
  956 + <View
  957 + android:background="#38B3A7"
  958 + android:layout_width="1dp"
  959 + android:layout_height="match_parent"/>
  960 + <TextView
  961 + android:text="状\n态"
  962 + android:textSize="13sp"
  963 + android:textColor="@color/white"
  964 + android:gravity="center"
  965 + android:layout_weight="1"
  966 + android:layout_width="0dp"
  967 + android:layout_height="wrap_content"/>
  968 + </LinearLayout>
  969 + </LinearLayout>
  970 +
  971 + <View
  972 + android:background="#38B3A7"
  973 + android:layout_width="1dp"
  974 + android:layout_height="match_parent"/>
  975 +
  976 + <LinearLayout
  977 + android:orientation="vertical"
  978 + android:layout_weight="72"
  979 + android:layout_width="0dp"
  980 + android:layout_height="match_parent">
  981 + <TextView
  982 + android:text="学后"
  983 + android:textSize="13sp"
  984 + android:textColor="@color/white"
  985 + android:gravity="center"
  986 + android:layout_width="match_parent"
  987 + android:layout_height="24dp"/>
  988 + <View
  989 + android:background="#38B3A7"
  990 + android:layout_width="match_parent"
  991 + android:layout_height="1dp"/>
  992 + <LinearLayout
  993 + android:orientation="horizontal"
  994 + android:layout_width="match_parent"
  995 + android:layout_height="match_parent">
  996 + <TextView
  997 + android:text="程\n度"
  998 + android:textSize="13sp"
  999 + android:textColor="@color/white"
  1000 + android:gravity="center"
  1001 + android:layout_weight="1"
  1002 + android:layout_width="0dp"
  1003 + android:layout_height="wrap_content"/>
  1004 + <View
  1005 + android:background="#38B3A7"
  1006 + android:layout_width="1dp"
  1007 + android:layout_height="match_parent"/>
  1008 + <TextView
  1009 + android:text="状\n态"
  1010 + android:textSize="13sp"
  1011 + android:textColor="@color/white"
  1012 + android:gravity="center"
  1013 + android:layout_weight="1"
  1014 + android:layout_width="0dp"
  1015 + android:layout_height="wrap_content"/>
  1016 + </LinearLayout>
  1017 +
  1018 + </LinearLayout>
  1019 +
  1020 + <View
  1021 + android:background="#38B3A7"
  1022 + android:layout_width="1dp"
  1023 + android:layout_height="match_parent"/>
  1024 + <TextView
  1025 + android:text="进步\n幅度"
  1026 + android:textSize="13sp"
  1027 + android:textColor="@color/white"
  1028 + android:gravity="center"
  1029 + android:layout_weight="50"
  1030 + android:layout_width="0dp"
  1031 + android:layout_height="match_parent"/>
  1032 + <View
  1033 + android:background="#38B3A7"
  1034 + android:layout_width="1dp"
  1035 + android:layout_height="match_parent"/>
  1036 + <TextView
  1037 + android:text="正答\n率"
  1038 + android:textSize="13sp"
  1039 + android:textColor="@color/white"
  1040 + android:gravity="center"
  1041 + android:layout_weight="38"
  1042 + android:layout_width="0dp"
  1043 + android:layout_height="match_parent"/>
  1044 + </LinearLayout>
  1045 + <androidx.recyclerview.widget.RecyclerView
  1046 + android:id="@+id/rvPoint"
  1047 + android:orientation="vertical"
  1048 + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
  1049 + app:reverseLayout="false"
  1050 + android:layout_width="match_parent"
  1051 + android:layout_height="wrap_content"/>
  1052 + </LinearLayout>
  1053 +
  1054 + <LinearLayout
  1055 + android:id="@+id/flPointDesc"
  1056 + android:alpha="0"
  1057 + android:orientation="horizontal"
  1058 + android:gravity="center_vertical"
  1059 + android:layout_marginTop="10dp"
  1060 + android:layout_width="match_parent"
  1061 + android:layout_height="wrap_content">
  1062 + <ImageView
  1063 + android:src="@drawable/png_up"
  1064 + android:layout_width="12dp"
  1065 + android:layout_height="12dp"/>
  1066 + <TextView
  1067 + android:text="代表进步幅度最大的知识点"
  1068 + android:textSize="12sp"
  1069 + android:textColor="#666"
  1070 + android:layout_marginStart="8dp"
  1071 + android:layout_width="wrap_content"
  1072 + android:layout_height="wrap_content"/>
  1073 + </LinearLayout>
  1074 + </LinearLayout>
  1075 + </LinearLayout>
  1076 + </HorizontalScrollView>
  1077 +
  1078 + </LinearLayout>
  1079 +</FrameLayout>
0 1080 \ No newline at end of file
... ...
app/src/main/res/layout/item_huyou_point.xml
... ... @@ -0,0 +1,136 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:tools="http://schemas.android.com/tools"
  4 + android:orientation="vertical"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="36dp"
  7 + tools:ignore="SmallSp,RtlSymmetry,HardcodedText">
  8 + <View
  9 + android:background="#38B3A7"
  10 + android:layout_width="match_parent"
  11 + android:layout_height="1dp"/>
  12 +
  13 + <LinearLayout
  14 + android:orientation="horizontal"
  15 + android:layout_width="match_parent"
  16 + android:layout_height="match_parent">
  17 + <TextView
  18 + android:id="@+id/tvName"
  19 + tools:text="正数与负数"
  20 + android:textSize="12sp"
  21 + android:textColor="#333"
  22 + android:gravity="center_vertical"
  23 + android:singleLine="true"
  24 + android:paddingStart="6dp"
  25 + android:layout_weight="82"
  26 + android:layout_width="0dp"
  27 + android:layout_height="match_parent"/>
  28 + <View
  29 + android:background="#38B3A7"
  30 + android:layout_width="1dp"
  31 + android:layout_height="match_parent"/>
  32 + <LinearLayout
  33 + android:orientation="horizontal"
  34 + android:gravity="center_vertical"
  35 + android:paddingStart="4dp"
  36 + android:layout_weight="72"
  37 + android:layout_width="0dp"
  38 + android:layout_height="match_parent">
  39 + <TextView
  40 + android:id="@+id/tvBefore"
  41 + tools:text="33%"
  42 + android:textSize="12sp"
  43 + android:textColor="#333"
  44 + android:layout_width="wrap_content"
  45 + android:layout_height="wrap_content"/>
  46 + <Space style="@style/empty_space"/>
  47 + <TextView
  48 + android:id="@+id/tvBeforeState"
  49 + tools:text="掌握薄弱"
  50 + android:textSize="8sp"
  51 + android:textColor="@color/white"
  52 + android:background="@drawable/shape_radius_2"
  53 + android:backgroundTint="#EA5127"
  54 + android:paddingHorizontal="2dp"
  55 + android:singleLine="true"
  56 + android:layout_width="wrap_content"
  57 + android:layout_height="wrap_content"/>
  58 + </LinearLayout>
  59 + <View
  60 + android:background="#38B3A7"
  61 + android:layout_width="1dp"
  62 + android:layout_height="match_parent"/>
  63 + <LinearLayout
  64 + android:orientation="horizontal"
  65 + android:gravity="center_vertical"
  66 + android:paddingStart="4dp"
  67 + android:layout_weight="72"
  68 + android:layout_width="0dp"
  69 + android:layout_height="match_parent">
  70 + <TextView
  71 + android:id="@+id/tvAfter"
  72 + tools:text="33%"
  73 + android:textSize="12sp"
  74 + android:textColor="#333"
  75 + android:layout_width="wrap_content"
  76 + android:layout_height="wrap_content"/>
  77 + <Space style="@style/empty_space"/>
  78 + <TextView
  79 + android:id="@+id/tvAfterState"
  80 + tools:text="掌握薄弱"
  81 + android:textSize="8sp"
  82 + android:textColor="@color/white"
  83 + android:background="@drawable/shape_radius_2"
  84 + android:backgroundTint="#EA5127"
  85 + android:paddingHorizontal="2dp"
  86 + android:singleLine="true"
  87 + android:layout_width="wrap_content"
  88 + android:layout_height="wrap_content" />
  89 + </LinearLayout>
  90 + <View
  91 + android:background="#38B3A7"
  92 + android:layout_width="1dp"
  93 + android:layout_height="match_parent"/>
  94 + <LinearLayout
  95 + android:orientation="horizontal"
  96 + android:gravity="center_vertical"
  97 + android:paddingStart="6dp"
  98 + android:layout_weight="50"
  99 + android:layout_width="0dp"
  100 + android:layout_height="match_parent">
  101 + <TextView
  102 + android:id="@+id/tvGap"
  103 + tools:text="33"
  104 + android:textSize="15sp"
  105 + android:textColor="#333"
  106 + android:textStyle="bold"
  107 + android:layout_width="wrap_content"
  108 + android:layout_height="wrap_content"/>
  109 + <TextView
  110 + android:text="%"
  111 + android:textSize="9sp"
  112 + android:textColor="#333"
  113 + android:layout_marginTop="2dp"
  114 + android:layout_width="wrap_content"
  115 + android:layout_height="wrap_content"/>
  116 + <ImageView
  117 + android:id="@+id/ivFlag"
  118 + android:src="@drawable/png_up"
  119 + android:layout_width="10dp"
  120 + android:layout_height="10dp"/>
  121 + </LinearLayout>
  122 + <View
  123 + android:background="#38B3A7"
  124 + android:layout_width="1dp"
  125 + android:layout_height="match_parent"/>
  126 + <TextView
  127 + android:id="@+id/tvHuyou"
  128 + android:text="-"
  129 + android:textSize="12sp"
  130 + android:textColor="#333"
  131 + android:gravity="center"
  132 + android:layout_weight="38"
  133 + android:layout_width="0dp"
  134 + android:layout_height="match_parent"/>
  135 + </LinearLayout>
  136 +</LinearLayout>
0 137 \ No newline at end of file
... ...
... ... @@ -6,7 +6,7 @@ buildscript {
6 6  
7 7 androidId = [
8 8 compileSdkVersion: 32,
9   - minSdkVersion : 24,
  9 + minSdkVersion : 26,
10 10 targetSdkVersion : 32,
11 11 versionCode : 1,
12 12 versionName : "0.0.1"
... ...
libs/common/src/main/java/com/littlejie/circleprogress/CircleProgress.java
... ... @@ -0,0 +1,409 @@
  1 +package com.littlejie.circleprogress;
  2 +
  3 +import android.animation.ValueAnimator;
  4 +import android.content.Context;
  5 +import android.content.res.TypedArray;
  6 +import android.graphics.Canvas;
  7 +import android.graphics.Color;
  8 +import android.graphics.Paint;
  9 +import android.graphics.Point;
  10 +import android.graphics.RectF;
  11 +import android.graphics.SweepGradient;
  12 +import android.graphics.Typeface;
  13 +import android.text.TextPaint;
  14 +import android.util.AttributeSet;
  15 +import android.util.Log;
  16 +import android.view.View;
  17 +
  18 +import androidx.annotation.Nullable;
  19 +
  20 +import com.littlejie.circleprogress.utils.Constant;
  21 +import com.littlejie.circleprogress.utils.MiscUtil;
  22 +import com.prws.common.R;
  23 +
  24 +/**
  25 + * 圆形进度条,类似 QQ 健康中运动步数的 UI 控件
  26 + * Created by littlejie on 2017/2/21.
  27 + */
  28 +
  29 +public class CircleProgress extends View {
  30 +
  31 + private static final String TAG = CircleProgress.class.getSimpleName();
  32 + private Context mContext;
  33 +
  34 + //默认大小
  35 + private int mDefaultSize;
  36 + //是否开启抗锯齿
  37 + private boolean antiAlias;
  38 + //绘制提示
  39 + private TextPaint mHintPaint;
  40 + private CharSequence mHint;
  41 + private int mHintColor;
  42 + private float mHintSize;
  43 + private float mHintOffset;
  44 +
  45 + //绘制单位
  46 + private TextPaint mUnitPaint;
  47 + private CharSequence mUnit;
  48 + private int mUnitColor;
  49 + private float mUnitSize;
  50 + private float mUnitOffset;
  51 +
  52 + //绘制数值
  53 + private TextPaint mValuePaint;
  54 + private float mValue;
  55 + private float mMaxValue;
  56 + private float mValueOffset;
  57 + private int mPrecision;
  58 + private String mPrecisionFormat;
  59 + private int mValueColor;
  60 + private float mValueSize;
  61 +
  62 + //绘制圆弧
  63 + private Paint mArcPaint;
  64 + private float mArcWidth;
  65 + private float mStartAngle, mSweepAngle;
  66 + private RectF mRectF;
  67 + //渐变的颜色是360度,如果只显示270,那么则会缺失部分颜色
  68 + private SweepGradient mSweepGradient;
  69 + private int[] mGradientColors = {Color.GREEN, Color.YELLOW, Color.RED};
  70 + //当前进度,[0.0f,1.0f]
  71 + private float mPercent;
  72 + //动画时间
  73 + private long mAnimTime;
  74 + //属性动画
  75 + private ValueAnimator mAnimator;
  76 +
  77 + //绘制背景圆弧
  78 + private Paint mBgArcPaint;
  79 + private int mBgArcColor;
  80 + private float mBgArcWidth;
  81 +
  82 + //圆心坐标,半径
  83 + private Point mCenterPoint;
  84 + private float mRadius;
  85 + private float mTextOffsetPercentInRadius;
  86 +
  87 + public CircleProgress(Context context, @Nullable AttributeSet attrs) {
  88 + super(context, attrs);
  89 + init(context, attrs);
  90 + }
  91 +
  92 + public CircleProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  93 + super(context, attrs, defStyleAttr);
  94 + init(context, attrs);
  95 + }
  96 +
  97 + public CircleProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
  98 + super(context, attrs, defStyleAttr, defStyleRes);
  99 + init(context, attrs);
  100 + }
  101 +
  102 + private void init(Context context, AttributeSet attrs) {
  103 + mContext = context;
  104 + mDefaultSize = MiscUtil.dipToPx(mContext, Constant.DEFAULT_SIZE);
  105 + mAnimator = new ValueAnimator();
  106 + mRectF = new RectF();
  107 + mCenterPoint = new Point();
  108 + initAttrs(attrs);
  109 + initPaint();
  110 + setValue(mValue);
  111 + }
  112 +
  113 + private void initAttrs(AttributeSet attrs) {
  114 + TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);
  115 +
  116 + antiAlias = typedArray.getBoolean(R.styleable.CircleProgressBar_antiAlias, Constant.ANTI_ALIAS);
  117 +
  118 + mHint = typedArray.getString(R.styleable.CircleProgressBar_hint);
  119 + mHintColor = typedArray.getColor(R.styleable.CircleProgressBar_hintColor, Color.BLACK);
  120 + mHintSize = typedArray.getDimension(R.styleable.CircleProgressBar_hintSize, Constant.DEFAULT_HINT_SIZE);
  121 +
  122 + mValue = typedArray.getFloat(R.styleable.CircleProgressBar_value, Constant.DEFAULT_VALUE);
  123 + mMaxValue = typedArray.getFloat(R.styleable.CircleProgressBar_maxValue, Constant.DEFAULT_MAX_VALUE);
  124 + //内容数值精度格式
  125 + mPrecision = typedArray.getInt(R.styleable.CircleProgressBar_precision, 0);
  126 + mPrecisionFormat = MiscUtil.getPrecisionFormat(mPrecision);
  127 + mValueColor = typedArray.getColor(R.styleable.CircleProgressBar_valueColor, Color.BLACK);
  128 + mValueSize = typedArray.getDimension(R.styleable.CircleProgressBar_valueSize, Constant.DEFAULT_VALUE_SIZE);
  129 +
  130 + mUnit = typedArray.getString(R.styleable.CircleProgressBar_unit);
  131 + mUnitColor = typedArray.getColor(R.styleable.CircleProgressBar_unitColor, Color.BLACK);
  132 + mUnitSize = typedArray.getDimension(R.styleable.CircleProgressBar_unitSize, Constant.DEFAULT_UNIT_SIZE);
  133 +
  134 + mArcWidth = typedArray.getDimension(R.styleable.CircleProgressBar_arcWidth, Constant.DEFAULT_ARC_WIDTH);
  135 + mStartAngle = typedArray.getFloat(R.styleable.CircleProgressBar_startAngle, Constant.DEFAULT_START_ANGLE);
  136 + mSweepAngle = typedArray.getFloat(R.styleable.CircleProgressBar_sweepAngle, Constant.DEFAULT_SWEEP_ANGLE);
  137 +
  138 + mBgArcColor = typedArray.getColor(R.styleable.CircleProgressBar_bgArcColor, Color.WHITE);
  139 + mBgArcWidth = typedArray.getDimension(R.styleable.CircleProgressBar_bgArcWidth, Constant.DEFAULT_ARC_WIDTH);
  140 + mTextOffsetPercentInRadius = typedArray.getFloat(R.styleable.CircleProgressBar_textOffsetPercentInRadius, 0.33f);
  141 +
  142 + //mPercent = typedArray.getFloat(R.styleable.CircleProgressBar_percent, 0);
  143 + mAnimTime = typedArray.getInt(R.styleable.CircleProgressBar_animTime, Constant.DEFAULT_ANIM_TIME);
  144 +
  145 + int arcColor = typedArray.getColor(R.styleable.CircleProgressBar_arcColors, Color.WHITE);
  146 + mGradientColors = new int[2];
  147 + mGradientColors[0] = arcColor;
  148 + mGradientColors[1] = arcColor;
  149 +
  150 + typedArray.recycle();
  151 + }
  152 +
  153 + private void initPaint() {
  154 + mHintPaint = new TextPaint();
  155 + // 设置抗锯齿,会消耗较大资源,绘制图形速度会变慢。
  156 + mHintPaint.setAntiAlias(antiAlias);
  157 + // 设置绘制文字大小
  158 + mHintPaint.setTextSize(mHintSize);
  159 + // 设置画笔颜色
  160 + mHintPaint.setColor(mHintColor);
  161 + // 从中间向两边绘制,不需要再次计算文字
  162 + mHintPaint.setTextAlign(Paint.Align.CENTER);
  163 +
  164 + mValuePaint = new TextPaint();
  165 + mValuePaint.setAntiAlias(antiAlias);
  166 + mValuePaint.setTextSize(mValueSize);
  167 + mValuePaint.setColor(mValueColor);
  168 + // 设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等
  169 + mValuePaint.setTypeface(Typeface.DEFAULT_BOLD);
  170 + mValuePaint.setTextAlign(Paint.Align.CENTER);
  171 +
  172 + mUnitPaint = new TextPaint();
  173 + mUnitPaint.setAntiAlias(antiAlias);
  174 + mUnitPaint.setTextSize(mUnitSize);
  175 + mUnitPaint.setColor(mUnitColor);
  176 + mUnitPaint.setTextAlign(Paint.Align.CENTER);
  177 +
  178 + mArcPaint = new Paint();
  179 + mArcPaint.setAntiAlias(antiAlias);
  180 + // 设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE
  181 + mArcPaint.setStyle(Paint.Style.STROKE);
  182 + // 设置画笔粗细
  183 + mArcPaint.setStrokeWidth(mArcWidth);
  184 + // 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式
  185 + // Cap.ROUND,或方形样式 Cap.SQUARE
  186 + mArcPaint.setStrokeCap(Paint.Cap.ROUND);
  187 +
  188 + mBgArcPaint = new Paint();
  189 + mBgArcPaint.setAntiAlias(antiAlias);
  190 + mBgArcPaint.setColor(mBgArcColor);
  191 + mBgArcPaint.setStyle(Paint.Style.STROKE);
  192 + mBgArcPaint.setStrokeWidth(mBgArcWidth);
  193 + mBgArcPaint.setStrokeCap(Paint.Cap.ROUND);
  194 + }
  195 +
  196 + @Override
  197 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  198 + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  199 + setMeasuredDimension(MiscUtil.measure(widthMeasureSpec, mDefaultSize),
  200 + MiscUtil.measure(heightMeasureSpec, mDefaultSize));
  201 + }
  202 +
  203 + @Override
  204 + protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  205 + super.onSizeChanged(w, h, oldw, oldh);
  206 + Log.d(TAG, "onSizeChanged: w = " + w + "; h = " + h + "; oldw = " + oldw + "; oldh = " + oldh);
  207 + //求圆弧和背景圆弧的最大宽度
  208 + float maxArcWidth = Math.max(mArcWidth, mBgArcWidth);
  209 + //求最小值作为实际值
  210 + int minSize = Math.min(w - getPaddingLeft() - getPaddingRight() - 2 * (int) maxArcWidth,
  211 + h - getPaddingTop() - getPaddingBottom() - 2 * (int) maxArcWidth);
  212 + //减去圆弧的宽度,否则会造成部分圆弧绘制在外围
  213 + mRadius = minSize / 2;
  214 + //获取圆的相关参数
  215 + mCenterPoint.x = w / 2;
  216 + mCenterPoint.y = h / 2;
  217 + //绘制圆弧的边界
  218 + mRectF.left = mCenterPoint.x - mRadius - maxArcWidth / 2;
  219 + mRectF.top = mCenterPoint.y - mRadius - maxArcWidth / 2;
  220 + mRectF.right = mCenterPoint.x + mRadius + maxArcWidth / 2;
  221 + mRectF.bottom = mCenterPoint.y + mRadius + maxArcWidth / 2;
  222 + //计算文字绘制时的 baseline
  223 + //由于文字的baseline、descent、ascent等属性只与textSize和typeface有关,所以此时可以直接计算
  224 + //若value、hint、unit由同一个画笔绘制或者需要动态设置文字的大小,则需要在每次更新后再次计算
  225 + mValueOffset = mCenterPoint.y + getBaselineOffsetFromY(mValuePaint);
  226 + mHintOffset = mCenterPoint.y - mRadius * mTextOffsetPercentInRadius + getBaselineOffsetFromY(mHintPaint);
  227 + mUnitOffset = mCenterPoint.y + mRadius * mTextOffsetPercentInRadius + getBaselineOffsetFromY(mUnitPaint);
  228 + updateArcPaint();
  229 + Log.d(TAG, "onSizeChanged: 控件大小 = " + "(" + w + ", " + h + ")"
  230 + + "圆心坐标 = " + mCenterPoint.toString()
  231 + + ";圆半径 = " + mRadius
  232 + + ";圆的外接矩形 = " + mRectF.toString());
  233 + }
  234 +
  235 + private float getBaselineOffsetFromY(Paint paint) {
  236 + return MiscUtil.measureTextHeight(paint) / 2;
  237 + }
  238 +
  239 + @Override
  240 + protected void onDraw(Canvas canvas) {
  241 + super.onDraw(canvas);
  242 + drawText(canvas);
  243 + drawArc(canvas);
  244 + }
  245 +
  246 + /**
  247 + * 绘制内容文字
  248 + *
  249 + * @param canvas
  250 + */
  251 + private void drawText(Canvas canvas) {
  252 + // 计算文字宽度,由于Paint已设置为居中绘制,故此处不需要重新计算
  253 + // float textWidth = mValuePaint.measureText(mValue.toString());
  254 + // float x = mCenterPoint.x - textWidth / 2;
  255 + canvas.drawText(String.format(mPrecisionFormat, mValue), mCenterPoint.x, mValueOffset, mValuePaint);
  256 +
  257 + if (mHint != null) {
  258 + canvas.drawText(mHint.toString(), mCenterPoint.x, mHintOffset, mHintPaint);
  259 + }
  260 +
  261 + if (mUnit != null) {
  262 + canvas.drawText(mUnit.toString(), mCenterPoint.x, mUnitOffset, mUnitPaint);
  263 + }
  264 + }
  265 +
  266 + private void drawArc(Canvas canvas) {
  267 + // 绘制背景圆弧
  268 + // 从进度圆弧结束的地方开始重新绘制,优化性能
  269 + canvas.save();
  270 + float currentAngle = mSweepAngle * mPercent;
  271 + canvas.rotate(mStartAngle, mCenterPoint.x, mCenterPoint.y);
  272 + canvas.drawArc(mRectF, currentAngle, mSweepAngle - currentAngle + 2, false, mBgArcPaint);
  273 + // 第一个参数 oval 为 RectF 类型,即圆弧显示区域
  274 + // startAngle 和 sweepAngle 均为 float 类型,分别表示圆弧起始角度和圆弧度数
  275 + // 3点钟方向为0度,顺时针递增
  276 + // 如果 startAngle < 0 或者 > 360,则相当于 startAngle % 360
  277 + // useCenter:如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形
  278 + canvas.drawArc(mRectF, 2, currentAngle, false, mArcPaint);
  279 + canvas.restore();
  280 + }
  281 +
  282 + /**
  283 + * 更新圆弧画笔
  284 + */
  285 + private void updateArcPaint() {
  286 + // 设置渐变
  287 + mSweepGradient = new SweepGradient(mCenterPoint.x, mCenterPoint.y, mGradientColors, null);
  288 + mArcPaint.setShader(mSweepGradient);
  289 + }
  290 +
  291 + public boolean isAntiAlias() {
  292 + return antiAlias;
  293 + }
  294 +
  295 + public CharSequence getHint() {
  296 + return mHint;
  297 + }
  298 +
  299 + public void setHint(CharSequence hint) {
  300 + mHint = hint;
  301 + }
  302 +
  303 + public CharSequence getUnit() {
  304 + return mUnit;
  305 + }
  306 +
  307 + public void setUnit(CharSequence unit) {
  308 + mUnit = unit;
  309 + }
  310 +
  311 + public float getValue() {
  312 + return mValue;
  313 + }
  314 +
  315 + /**
  316 + * 设置当前值
  317 + *
  318 + * @param value
  319 + */
  320 + public void setValue(float value) {
  321 + if (value > mMaxValue) {
  322 + value = mMaxValue;
  323 + }
  324 + float start = mPercent;
  325 + float end = value / mMaxValue;
  326 + startAnimator(start, end, mAnimTime);
  327 + }
  328 +
  329 + private void startAnimator(float start, float end, long animTime) {
  330 + mAnimator = ValueAnimator.ofFloat(start, end);
  331 + mAnimator.setDuration(animTime);
  332 + mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  333 + @Override
  334 + public void onAnimationUpdate(ValueAnimator animation) {
  335 + mPercent = (float) animation.getAnimatedValue();
  336 + mValue = mPercent * mMaxValue;
  337 + invalidate();
  338 + }
  339 + });
  340 + mAnimator.start();
  341 + }
  342 +
  343 + /**
  344 + * 获取最大值
  345 + *
  346 + * @return
  347 + */
  348 + public float getMaxValue() {
  349 + return mMaxValue;
  350 + }
  351 +
  352 + /**
  353 + * 设置最大值
  354 + *
  355 + * @param maxValue
  356 + */
  357 + public void setMaxValue(float maxValue) {
  358 + mMaxValue = maxValue;
  359 + }
  360 +
  361 + /**
  362 + * 获取精度
  363 + *
  364 + * @return
  365 + */
  366 + public int getPrecision() {
  367 + return mPrecision;
  368 + }
  369 +
  370 + public void setPrecision(int precision) {
  371 + mPrecision = precision;
  372 + mPrecisionFormat = MiscUtil.getPrecisionFormat(precision);
  373 + }
  374 +
  375 + public int[] getGradientColors() {
  376 + return mGradientColors;
  377 + }
  378 +
  379 + /**
  380 + * 设置渐变
  381 + *
  382 + * @param gradientColors
  383 + */
  384 + public void setGradientColors(int[] gradientColors) {
  385 + mGradientColors = gradientColors;
  386 + updateArcPaint();
  387 + }
  388 +
  389 + public long getAnimTime() {
  390 + return mAnimTime;
  391 + }
  392 +
  393 + public void setAnimTime(long animTime) {
  394 + mAnimTime = animTime;
  395 + }
  396 +
  397 + /**
  398 + * 重置
  399 + */
  400 + public void reset() {
  401 + startAnimator(mPercent, 0.0f, 1000L);
  402 + }
  403 +
  404 + @Override
  405 + protected void onDetachedFromWindow() {
  406 + super.onDetachedFromWindow();
  407 + //释放资源
  408 + }
  409 +}
... ...
libs/common/src/main/java/com/littlejie/circleprogress/DialProgress.java
... ... @@ -0,0 +1,343 @@
  1 +package com.littlejie.circleprogress;
  2 +
  3 +import android.animation.ValueAnimator;
  4 +import android.content.Context;
  5 +import android.content.res.Resources;
  6 +import android.content.res.TypedArray;
  7 +import android.graphics.Canvas;
  8 +import android.graphics.Color;
  9 +import android.graphics.Paint;
  10 +import android.graphics.Point;
  11 +import android.graphics.RectF;
  12 +import android.graphics.SweepGradient;
  13 +import android.graphics.Typeface;
  14 +import android.text.TextPaint;
  15 +import android.util.AttributeSet;
  16 +import android.util.Log;
  17 +import android.view.View;
  18 +
  19 +import com.prws.common.R;
  20 +import com.littlejie.circleprogress.utils.Constant;
  21 +import com.littlejie.circleprogress.utils.MiscUtil;
  22 +
  23 +/**
  24 + * 带有刻度的圆形进度条
  25 + * Created by littlejie on 2017/2/26.
  26 + */
  27 +
  28 +public class DialProgress extends View {
  29 +
  30 + private static final String TAG = DialProgress.class.getSimpleName();
  31 + private Context mContext;
  32 +
  33 + //圆心坐标
  34 + private Point mCenterPoint;
  35 + private float mRadius;
  36 + private float mTextOffsetPercentInRadius;
  37 +
  38 + private boolean antiAlias;
  39 + //绘制提示
  40 + private TextPaint mHintPaint;
  41 + private CharSequence mHint;
  42 + private int mHintColor;
  43 + private float mHintSize;
  44 + private float mHintOffset;
  45 +
  46 + //绘制数值
  47 + private Paint mValuePaint;
  48 + private int mValueColor;
  49 + private float mMaxValue;
  50 + private float mValue;
  51 + private float mValueSize;
  52 + private float mValueOffset;
  53 + private String mPrecisionFormat;
  54 +
  55 + //绘制单位
  56 + private Paint mUnitPaint;
  57 + private float mUnitSize;
  58 + private int mUnitColor;
  59 + private float mUnitOffset;
  60 + private CharSequence mUnit;
  61 + //前景圆弧
  62 + private Paint mArcPaint;
  63 + private float mArcWidth;
  64 + private int mDialIntervalDegree;
  65 + private float mStartAngle, mSweepAngle;
  66 + private RectF mRectF;
  67 + //渐变
  68 + private int[] mGradientColors = {Color.GREEN, Color.YELLOW, Color.RED};
  69 + //当前进度,[0.0f,1.0f]
  70 + private float mPercent;
  71 + //动画时间
  72 + private long mAnimTime;
  73 + //属性动画
  74 + private ValueAnimator mAnimator;
  75 +
  76 + //背景圆弧
  77 + private Paint mBgArcPaint;
  78 + private int mBgArcColor;
  79 +
  80 + //刻度线颜色
  81 + private Paint mDialPaint;
  82 + private float mDialWidth;
  83 + private int mDialColor;
  84 +
  85 + private int mDefaultSize;
  86 +
  87 + public DialProgress(Context context, AttributeSet attrs) {
  88 + super(context, attrs);
  89 + init(context, attrs);
  90 + }
  91 +
  92 + private void init(Context context, AttributeSet attrs) {
  93 + mContext = context;
  94 + mDefaultSize = MiscUtil.dipToPx(context, Constant.DEFAULT_SIZE);
  95 + mRectF = new RectF();
  96 + mCenterPoint = new Point();
  97 + initConfig(context, attrs);
  98 + initPaint();
  99 + setValue(mValue);
  100 + }
  101 +
  102 + private void initConfig(Context context, AttributeSet attrs) {
  103 + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DialProgress);
  104 +
  105 + antiAlias = typedArray.getBoolean(R.styleable.DialProgress_antiAlias, true);
  106 + mMaxValue = typedArray.getFloat(R.styleable.DialProgress_maxValue, Constant.DEFAULT_MAX_VALUE);
  107 + mValue = typedArray.getFloat(R.styleable.DialProgress_value, Constant.DEFAULT_VALUE);
  108 + mValueSize = typedArray.getDimension(R.styleable.DialProgress_valueSize, Constant.DEFAULT_VALUE_SIZE);
  109 + mValueColor = typedArray.getColor(R.styleable.DialProgress_valueColor, Color.BLACK);
  110 + mDialIntervalDegree = typedArray.getInt(R.styleable.DialProgress_dialIntervalDegree, 10);
  111 + int precision = typedArray.getInt(R.styleable.DialProgress_precision, 0);
  112 + mPrecisionFormat = MiscUtil.getPrecisionFormat(precision);
  113 +
  114 + mUnit = typedArray.getString(R.styleable.DialProgress_unit);
  115 + mUnitColor = typedArray.getColor(R.styleable.DialProgress_unitColor, Color.BLACK);
  116 + mUnitSize = typedArray.getDimension(R.styleable.DialProgress_unitSize, Constant.DEFAULT_UNIT_SIZE);
  117 +
  118 + mHint = typedArray.getString(R.styleable.DialProgress_hint);
  119 + mHintColor = typedArray.getColor(R.styleable.DialProgress_hintColor, Color.BLACK);
  120 + mHintSize = typedArray.getDimension(R.styleable.DialProgress_hintSize, Constant.DEFAULT_HINT_SIZE);
  121 +
  122 + mArcWidth = typedArray.getDimension(R.styleable.DialProgress_arcWidth, Constant.DEFAULT_ARC_WIDTH);
  123 +
  124 + mStartAngle = typedArray.getFloat(R.styleable.DialProgress_startAngle, Constant.DEFAULT_START_ANGLE);
  125 + mSweepAngle = typedArray.getFloat(R.styleable.DialProgress_sweepAngle, Constant.DEFAULT_SWEEP_ANGLE);
  126 +
  127 + mAnimTime = typedArray.getInt(R.styleable.DialProgress_animTime, Constant.DEFAULT_ANIM_TIME);
  128 +
  129 + mBgArcColor = typedArray.getColor(R.styleable.DialProgress_bgArcColor, Color.GRAY);
  130 + mDialWidth = typedArray.getDimension(R.styleable.DialProgress_dialWidth, 2);
  131 + mDialColor = typedArray.getColor(R.styleable.DialProgress_dialColor, Color.WHITE);
  132 +
  133 + mTextOffsetPercentInRadius = typedArray.getFloat(R.styleable.DialProgress_textOffsetPercentInRadius, 0.33f);
  134 +
  135 + int gradientArcColors = typedArray.getResourceId(R.styleable.DialProgress_arcColors, 0);
  136 + if (gradientArcColors != 0) {
  137 + try {
  138 + int[] gradientColors = getResources().getIntArray(gradientArcColors);
  139 + if (gradientColors.length == 0) {
  140 + int color = getResources().getColor(gradientArcColors);
  141 + mGradientColors = new int[2];
  142 + mGradientColors[0] = color;
  143 + mGradientColors[1] = color;
  144 + } else if (gradientColors.length == 1) {
  145 + mGradientColors = new int[2];
  146 + mGradientColors[0] = gradientColors[0];
  147 + mGradientColors[1] = gradientColors[0];
  148 + } else {
  149 + mGradientColors = gradientColors;
  150 + }
  151 + } catch (Resources.NotFoundException e) {
  152 + throw new Resources.NotFoundException("the give resource not found.");
  153 + }
  154 + }
  155 + typedArray.recycle();
  156 + }
  157 +
  158 + private void initPaint() {
  159 + mHintPaint = new TextPaint();
  160 + // 设置抗锯齿,会消耗较大资源,绘制图形速度会变慢。
  161 + mHintPaint.setAntiAlias(antiAlias);
  162 + // 设置绘制文字大小
  163 + mHintPaint.setTextSize(mHintSize);
  164 + // 设置画笔颜色
  165 + mHintPaint.setColor(mHintColor);
  166 + // 从中间向两边绘制,不需要再次计算文字
  167 + mHintPaint.setTextAlign(Paint.Align.CENTER);
  168 +
  169 + mValuePaint = new Paint();
  170 + mValuePaint.setAntiAlias(antiAlias);
  171 + mValuePaint.setTextSize(mValueSize);
  172 + mValuePaint.setColor(mValueColor);
  173 + mValuePaint.setTypeface(Typeface.DEFAULT_BOLD);
  174 + mValuePaint.setTextAlign(Paint.Align.CENTER);
  175 +
  176 + mUnitPaint = new Paint();
  177 + mUnitPaint.setAntiAlias(antiAlias);
  178 + mUnitPaint.setTextSize(mUnitSize);
  179 + mUnitPaint.setColor(mUnitColor);
  180 + mUnitPaint.setTextAlign(Paint.Align.CENTER);
  181 +
  182 + mArcPaint = new Paint();
  183 + mArcPaint.setAntiAlias(antiAlias);
  184 + mArcPaint.setStyle(Paint.Style.STROKE);
  185 + mArcPaint.setStrokeWidth(mArcWidth);
  186 + mArcPaint.setStrokeCap(Paint.Cap.BUTT);
  187 +
  188 + mBgArcPaint = new Paint();
  189 + mBgArcPaint.setAntiAlias(antiAlias);
  190 + mBgArcPaint.setStyle(Paint.Style.STROKE);
  191 + mBgArcPaint.setStrokeWidth(mArcWidth);
  192 + mBgArcPaint.setStrokeCap(Paint.Cap.BUTT);
  193 + mBgArcPaint.setColor(mBgArcColor);
  194 +
  195 + mDialPaint = new Paint();
  196 + mDialPaint.setAntiAlias(antiAlias);
  197 + mDialPaint.setColor(mDialColor);
  198 + mDialPaint.setStrokeWidth(mDialWidth);
  199 + }
  200 +
  201 + /**
  202 + * 更新圆弧画笔
  203 + */
  204 + private void updateArcPaint() {
  205 + // 设置渐变
  206 + // 渐变的颜色是360度,如果只显示270,那么则会缺失部分颜色
  207 + SweepGradient sweepGradient = new SweepGradient(mCenterPoint.x, mCenterPoint.y, mGradientColors, null);
  208 + mArcPaint.setShader(sweepGradient);
  209 + }
  210 +
  211 + @Override
  212 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  213 + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  214 + setMeasuredDimension(MiscUtil.measure(widthMeasureSpec, mDefaultSize),
  215 + MiscUtil.measure(heightMeasureSpec, mDefaultSize));
  216 + }
  217 +
  218 + @Override
  219 + protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  220 + super.onSizeChanged(w, h, oldw, oldh);
  221 + Log.d(TAG, "onSizeChanged: w = " + w + "; h = " + h + "; oldw = " + oldw + "; oldh = " + oldh);
  222 + int minSize = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - 2 * (int) mArcWidth,
  223 + getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - 2 * (int) mArcWidth);
  224 + mRadius = minSize / 2;
  225 + mCenterPoint.x = getMeasuredWidth() / 2;
  226 + mCenterPoint.y = getMeasuredHeight() / 2;
  227 + //绘制圆弧的边界
  228 + mRectF.left = mCenterPoint.x - mRadius - mArcWidth / 2;
  229 + mRectF.top = mCenterPoint.y - mRadius - mArcWidth / 2;
  230 + mRectF.right = mCenterPoint.x + mRadius + mArcWidth / 2;
  231 + mRectF.bottom = mCenterPoint.y + mRadius + mArcWidth / 2;
  232 +
  233 + mValueOffset = mCenterPoint.y + getBaselineOffsetFromY(mValuePaint);
  234 + mHintOffset = mCenterPoint.y - mRadius * mTextOffsetPercentInRadius + getBaselineOffsetFromY(mHintPaint);
  235 + mUnitOffset = mCenterPoint.y + mRadius * mTextOffsetPercentInRadius + getBaselineOffsetFromY(mUnitPaint);
  236 +
  237 + updateArcPaint();
  238 + Log.d(TAG, "onMeasure: 控件大小 = " + "(" + getMeasuredWidth() + ", " + getMeasuredHeight() + ")"
  239 + + ";圆心坐标 = " + mCenterPoint.toString()
  240 + + ";圆半径 = " + mRadius
  241 + + ";圆的外接矩形 = " + mRectF.toString());
  242 + }
  243 +
  244 + private float getBaselineOffsetFromY(Paint paint) {
  245 + return MiscUtil.measureTextHeight(paint) / 2;
  246 + }
  247 +
  248 + @Override
  249 + protected void onDraw(Canvas canvas) {
  250 + super.onDraw(canvas);
  251 + drawArc(canvas);
  252 + drawDial(canvas);
  253 + drawText(canvas);
  254 + }
  255 +
  256 + private void drawArc(Canvas canvas) {
  257 + // 绘制背景圆弧
  258 + // 从进度圆弧结束的地方开始重新绘制,优化性能
  259 + float currentAngle = mSweepAngle * mPercent;
  260 + canvas.save();
  261 + canvas.rotate(mStartAngle, mCenterPoint.x, mCenterPoint.y);
  262 + canvas.drawArc(mRectF, currentAngle, mSweepAngle - currentAngle, false, mBgArcPaint);
  263 + // 第一个参数 oval 为 RectF 类型,即圆弧显示区域
  264 + // startAngle 和 sweepAngle 均为 float 类型,分别表示圆弧起始角度和圆弧度数
  265 + // 3点钟方向为0度,顺时针递增
  266 + // 如果 startAngle < 0 或者 > 360,则相当于 startAngle % 360
  267 + // useCenter:如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形
  268 + canvas.drawArc(mRectF, 0, currentAngle, false, mArcPaint);
  269 + canvas.restore();
  270 + }
  271 +
  272 + private void drawDial(Canvas canvas) {
  273 + int total = (int) (mSweepAngle / mDialIntervalDegree);
  274 + canvas.save();
  275 + canvas.rotate(mStartAngle, mCenterPoint.x, mCenterPoint.y);
  276 + for (int i = 0; i <= total; i++) {
  277 + canvas.drawLine(mCenterPoint.x + mRadius, mCenterPoint.y, mCenterPoint.x + mRadius + mArcWidth, mCenterPoint.y, mDialPaint);
  278 + canvas.rotate(mDialIntervalDegree, mCenterPoint.x, mCenterPoint.y);
  279 + }
  280 + canvas.restore();
  281 + }
  282 +
  283 + private void drawText(Canvas canvas) {
  284 + canvas.drawText(String.format(mPrecisionFormat, mValue), mCenterPoint.x, mValueOffset, mValuePaint);
  285 +
  286 + if (mUnit != null) {
  287 + canvas.drawText(mUnit.toString(), mCenterPoint.x, mUnitOffset, mUnitPaint);
  288 + }
  289 +
  290 + if (mHint != null) {
  291 + canvas.drawText(mHint.toString(), mCenterPoint.x, mHintOffset, mHintPaint);
  292 + }
  293 + }
  294 +
  295 + public float getMaxValue() {
  296 + return mMaxValue;
  297 + }
  298 +
  299 + public void setMaxValue(float maxValue) {
  300 + mMaxValue = maxValue;
  301 + }
  302 +
  303 + /**
  304 + * 设置当前值
  305 + *
  306 + * @param value
  307 + */
  308 + public void setValue(float value) {
  309 + if (value > mMaxValue) {
  310 + value = mMaxValue;
  311 + }
  312 + float start = mPercent;
  313 + float end = value / mMaxValue;
  314 + startAnimator(start, end, mAnimTime);
  315 + }
  316 +
  317 + private void startAnimator(float start, float end, long animTime) {
  318 + mAnimator = ValueAnimator.ofFloat(start, end);
  319 + mAnimator.setDuration(animTime);
  320 + mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  321 + @Override
  322 + public void onAnimationUpdate(ValueAnimator animation) {
  323 + mPercent = (float) animation.getAnimatedValue();
  324 + mValue = mPercent * mMaxValue;
  325 + invalidate();
  326 + }
  327 + });
  328 + mAnimator.start();
  329 + }
  330 +
  331 + public int[] getGradientColors() {
  332 + return mGradientColors;
  333 + }
  334 +
  335 + public void setGradientColors(int[] gradientColors) {
  336 + mGradientColors = gradientColors;
  337 + updateArcPaint();
  338 + }
  339 +
  340 + public void reset() {
  341 + startAnimator(mPercent, 0.0f, 1000L);
  342 + }
  343 +}
... ...
libs/common/src/main/java/com/littlejie/circleprogress/WaveProgress.java
... ... @@ -0,0 +1,506 @@
  1 +package com.littlejie.circleprogress;
  2 +
  3 +import android.animation.Animator;
  4 +import android.animation.ValueAnimator;
  5 +import android.annotation.TargetApi;
  6 +import android.content.Context;
  7 +import android.content.res.TypedArray;
  8 +import android.graphics.Canvas;
  9 +import android.graphics.Color;
  10 +import android.graphics.Paint;
  11 +import android.graphics.Path;
  12 +import android.graphics.Point;
  13 +import android.graphics.RectF;
  14 +import android.os.Build;
  15 +import android.text.TextPaint;
  16 +import android.util.AttributeSet;
  17 +import android.util.Log;
  18 +import android.view.View;
  19 +import android.view.animation.LinearInterpolator;
  20 +
  21 +import com.prws.common.R;
  22 +import com.littlejie.circleprogress.utils.Constant;
  23 +import com.littlejie.circleprogress.utils.MiscUtil;
  24 +
  25 +/**
  26 + * 水波进度条
  27 + * Created by littlejie on 2017/2/26.
  28 + */
  29 +
  30 +public class WaveProgress extends View {
  31 +
  32 + private static final String TAG = WaveProgress.class.getSimpleName();
  33 +
  34 + //浅色波浪方向
  35 + private static final int L2R = 0;
  36 + private static final int R2L = 1;
  37 +
  38 + private int mDefaultSize;
  39 + //圆心
  40 + private Point mCenterPoint;
  41 + //半径
  42 + private float mRadius;
  43 + //圆的外接矩形
  44 + private RectF mRectF;
  45 + //深色波浪移动距离
  46 + private float mDarkWaveOffset;
  47 + //浅色波浪移动距离
  48 + private float mLightWaveOffset;
  49 + //浅色波浪方向
  50 + private boolean isR2L;
  51 + //是否锁定波浪不随进度移动
  52 + private boolean lockWave;
  53 +
  54 + //是否开启抗锯齿
  55 + private boolean antiAlias;
  56 + //最大值
  57 + private float mMaxValue;
  58 + //当前值
  59 + private float mValue;
  60 + //当前进度
  61 + private float mPercent;
  62 +
  63 + //绘制提示
  64 + private TextPaint mHintPaint;
  65 + private CharSequence mHint;
  66 + private int mHintColor;
  67 + private float mHintSize;
  68 +
  69 + private Paint mPercentPaint;
  70 + private float mValueSize;
  71 + private int mValueColor;
  72 +
  73 + //圆环宽度
  74 + private float mCircleWidth;
  75 + //圆环
  76 + private Paint mCirclePaint;
  77 + //圆环颜色
  78 + private int mCircleColor;
  79 + //背景圆环颜色
  80 + private int mBgCircleColor;
  81 +
  82 + //水波路径
  83 + private Path mWaveLimitPath;
  84 + private Path mWavePath;
  85 + //水波高度
  86 + private float mWaveHeight;
  87 + //水波数量
  88 + private int mWaveNum;
  89 + //深色水波
  90 + private Paint mWavePaint;
  91 + //深色水波颜色
  92 + private int mDarkWaveColor;
  93 + //浅色水波颜色
  94 + private int mLightWaveColor;
  95 +
  96 + //深色水波贝塞尔曲线上的起始点、控制点
  97 + private Point[] mDarkPoints;
  98 + //浅色水波贝塞尔曲线上的起始点、控制点
  99 + private Point[] mLightPoints;
  100 +
  101 + //贝塞尔曲线点的总个数
  102 + private int mAllPointCount;
  103 + private int mHalfPointCount;
  104 +
  105 + private ValueAnimator mProgressAnimator;
  106 + private long mDarkWaveAnimTime;
  107 + private ValueAnimator mDarkWaveAnimator;
  108 + private long mLightWaveAnimTime;
  109 + private ValueAnimator mLightWaveAnimator;
  110 +
  111 + public WaveProgress(Context context, AttributeSet attrs) {
  112 + super(context, attrs);
  113 + init(context, attrs);
  114 + }
  115 +
  116 + private void init(Context context, AttributeSet attrs) {
  117 + mDefaultSize = MiscUtil.dipToPx(context, Constant.DEFAULT_SIZE);
  118 + mRectF = new RectF();
  119 + mCenterPoint = new Point();
  120 +
  121 + initAttrs(context, attrs);
  122 + initPaint();
  123 + initPath();
  124 + }
  125 +
  126 + private void initAttrs(Context context, AttributeSet attrs) {
  127 + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaveProgress);
  128 +
  129 + antiAlias = typedArray.getBoolean(R.styleable.WaveProgress_antiAlias, true);
  130 + mDarkWaveAnimTime = typedArray.getInt(R.styleable.WaveProgress_darkWaveAnimTime, Constant.DEFAULT_ANIM_TIME);
  131 + mLightWaveAnimTime = typedArray.getInt(R.styleable.WaveProgress_lightWaveAnimTime, Constant.DEFAULT_ANIM_TIME);
  132 + mMaxValue = typedArray.getFloat(R.styleable.WaveProgress_maxValue, Constant.DEFAULT_MAX_VALUE);
  133 + mValue = typedArray.getFloat(R.styleable.WaveProgress_value, Constant.DEFAULT_VALUE);
  134 + mValueSize = typedArray.getDimension(R.styleable.WaveProgress_valueSize, Constant.DEFAULT_VALUE_SIZE);
  135 + mValueColor = typedArray.getColor(R.styleable.WaveProgress_valueColor, Color.BLACK);
  136 +
  137 + mHint = typedArray.getString(R.styleable.WaveProgress_hint);
  138 + mHintColor = typedArray.getColor(R.styleable.WaveProgress_hintColor, Color.BLACK);
  139 + mHintSize = typedArray.getDimension(R.styleable.WaveProgress_hintSize, Constant.DEFAULT_HINT_SIZE);
  140 +
  141 + mCircleWidth = typedArray.getDimension(R.styleable.WaveProgress_circleWidth, Constant.DEFAULT_ARC_WIDTH);
  142 + mCircleColor = typedArray.getColor(R.styleable.WaveProgress_circleColor, Color.GREEN);
  143 + mBgCircleColor = typedArray.getColor(R.styleable.WaveProgress_bgCircleColor, Color.WHITE);
  144 +
  145 + mWaveHeight = typedArray.getDimension(R.styleable.WaveProgress_waveHeight, Constant.DEFAULT_WAVE_HEIGHT);
  146 + mWaveNum = typedArray.getInt(R.styleable.WaveProgress_waveNum, 1);
  147 + mDarkWaveColor = typedArray.getColor(R.styleable.WaveProgress_darkWaveColor,
  148 + getResources().getColor(android.R.color.holo_blue_dark));
  149 + mLightWaveColor = typedArray.getColor(R.styleable.WaveProgress_lightWaveColor,
  150 + getResources().getColor(android.R.color.holo_green_light));
  151 +
  152 + isR2L = typedArray.getInt(R.styleable.WaveProgress_lightWaveDirect, R2L) == R2L;
  153 + lockWave = typedArray.getBoolean(R.styleable.WaveProgress_lockWave, false);
  154 +
  155 + typedArray.recycle();
  156 + }
  157 +
  158 + private void initPaint() {
  159 + mHintPaint = new TextPaint();
  160 + // 设置抗锯齿,会消耗较大资源,绘制图形速度会变慢。
  161 + mHintPaint.setAntiAlias(antiAlias);
  162 + // 设置绘制文字大小
  163 + mHintPaint.setTextSize(mHintSize);
  164 + // 设置画笔颜色
  165 + mHintPaint.setColor(mHintColor);
  166 + // 从中间向两边绘制,不需要再次计算文字
  167 + mHintPaint.setTextAlign(Paint.Align.CENTER);
  168 +
  169 + mCirclePaint = new Paint();
  170 + mCirclePaint.setAntiAlias(antiAlias);
  171 + mCirclePaint.setStrokeWidth(mCircleWidth);
  172 + mCirclePaint.setStyle(Paint.Style.STROKE);
  173 + mCirclePaint.setStrokeCap(Paint.Cap.ROUND);
  174 +
  175 + mWavePaint = new Paint();
  176 + mWavePaint.setAntiAlias(antiAlias);
  177 + mWavePaint.setStyle(Paint.Style.FILL);
  178 +
  179 + mPercentPaint = new Paint();
  180 + mPercentPaint.setTextAlign(Paint.Align.CENTER);
  181 + mPercentPaint.setAntiAlias(antiAlias);
  182 + mPercentPaint.setColor(mValueColor);
  183 + mPercentPaint.setTextSize(mValueSize);
  184 + }
  185 +
  186 + private void initPath() {
  187 + mWaveLimitPath = new Path();
  188 + mWavePath = new Path();
  189 + }
  190 +
  191 + @Override
  192 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  193 + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  194 + setMeasuredDimension(MiscUtil.measure(widthMeasureSpec, mDefaultSize),
  195 + MiscUtil.measure(heightMeasureSpec, mDefaultSize));
  196 + }
  197 +
  198 + @Override
  199 + protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  200 + super.onSizeChanged(w, h, oldw, oldh);
  201 + Log.d(TAG, "onSizeChanged: w = " + w + "; h = " + h + "; oldw = " + oldw + "; oldh = " + oldh);
  202 + int minSize = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - 2 * (int) mCircleWidth,
  203 + getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - 2 * (int) mCircleWidth);
  204 + mRadius = minSize / 2;
  205 + mCenterPoint.x = getMeasuredWidth() / 2;
  206 + mCenterPoint.y = getMeasuredHeight() / 2;
  207 + //绘制圆弧的边界
  208 + mRectF.left = mCenterPoint.x - mRadius - mCircleWidth / 2;
  209 + mRectF.top = mCenterPoint.y - mRadius - mCircleWidth / 2;
  210 + mRectF.right = mCenterPoint.x + mRadius + mCircleWidth / 2;
  211 + mRectF.bottom = mCenterPoint.y + mRadius + mCircleWidth / 2;
  212 + Log.d(TAG, "onSizeChanged: 控件大小 = " + "(" + getMeasuredWidth() + ", " + getMeasuredHeight() + ")"
  213 + + ";圆心坐标 = " + mCenterPoint.toString()
  214 + + ";圆半径 = " + mRadius
  215 + + ";圆的外接矩形 = " + mRectF.toString());
  216 + initWavePoints();
  217 + //开始动画
  218 + setValue(mValue);
  219 + startWaveAnimator();
  220 + }
  221 +
  222 + private void initWavePoints() {
  223 + //当前波浪宽度
  224 + float waveWidth = (mRadius * 2) / mWaveNum;
  225 + mAllPointCount = 8 * mWaveNum + 1;
  226 + mHalfPointCount = mAllPointCount / 2;
  227 + mDarkPoints = getPoint(false, waveWidth);
  228 + mLightPoints = getPoint(isR2L, waveWidth);
  229 + }
  230 +
  231 + /**
  232 + * 从左往右或者从右往左获取贝塞尔点
  233 + *
  234 + * @return
  235 + */
  236 + private Point[] getPoint(boolean isR2L, float waveWidth) {
  237 + Point[] points = new Point[mAllPointCount];
  238 + //第1个点特殊处理,即数组的中点
  239 + points[mHalfPointCount] = new Point((int) (mCenterPoint.x + (isR2L ? mRadius : -mRadius)), mCenterPoint.y);
  240 + //屏幕内的贝塞尔曲线点
  241 + for (int i = mHalfPointCount + 1; i < mAllPointCount; i += 4) {
  242 + float width = points[mHalfPointCount].x + waveWidth * (i / 4 - mWaveNum);
  243 + points[i] = new Point((int) (waveWidth / 4 + width), (int) (mCenterPoint.y - mWaveHeight));
  244 + points[i + 1] = new Point((int) (waveWidth / 2 + width), mCenterPoint.y);
  245 + points[i + 2] = new Point((int) (waveWidth * 3 / 4 + width), (int) (mCenterPoint.y + mWaveHeight));
  246 + points[i + 3] = new Point((int) (waveWidth + width), mCenterPoint.y);
  247 + }
  248 + //屏幕外的贝塞尔曲线点
  249 + for (int i = 0; i < mHalfPointCount; i++) {
  250 + int reverse = mAllPointCount - i - 1;
  251 + points[i] = new Point((isR2L ? 2 : 1) * points[mHalfPointCount].x - points[reverse].x,
  252 + points[mHalfPointCount].y * 2 - points[reverse].y);
  253 + }
  254 + //对从右向左的贝塞尔点数组反序,方便后续处理
  255 + return isR2L ? MiscUtil.reverse(points) : points;
  256 + }
  257 +
  258 + @Override
  259 + protected void onDraw(Canvas canvas) {
  260 + super.onDraw(canvas);
  261 + drawCircle(canvas);
  262 + drawLightWave(canvas);
  263 + drawDarkWave(canvas);
  264 + drawProgress(canvas);
  265 + }
  266 +
  267 + /**
  268 + * 绘制圆环
  269 + *
  270 + * @param canvas
  271 + */
  272 + private void drawCircle(Canvas canvas) {
  273 + canvas.save();
  274 + canvas.rotate(270, mCenterPoint.x, mCenterPoint.y);
  275 + int currentAngle = (int) (360 * mPercent);
  276 + //画背景圆环
  277 + mCirclePaint.setColor(mBgCircleColor);
  278 + canvas.drawArc(mRectF, currentAngle, 360 - currentAngle, false, mCirclePaint);
  279 + //画圆环
  280 + mCirclePaint.setColor(mCircleColor);
  281 + canvas.drawArc(mRectF, 0, currentAngle, false, mCirclePaint);
  282 + canvas.restore();
  283 + }
  284 +
  285 + /**
  286 + * 绘制深色波浪(贝塞尔曲线)
  287 + *
  288 + * @param canvas
  289 + */
  290 + private void drawDarkWave(Canvas canvas) {
  291 + mWavePaint.setColor(mDarkWaveColor);
  292 + drawWave(canvas, mWavePaint, mDarkPoints, mDarkWaveOffset);
  293 + }
  294 +
  295 + /**
  296 + * 绘制浅色波浪(贝塞尔曲线)
  297 + *
  298 + * @param canvas
  299 + */
  300 + private void drawLightWave(Canvas canvas) {
  301 + mWavePaint.setColor(mLightWaveColor);
  302 + //从右向左的水波位移应该被减去
  303 + drawWave(canvas, mWavePaint, mLightPoints, isR2L ? -mLightWaveOffset : mLightWaveOffset);
  304 + }
  305 +
  306 + @TargetApi(Build.VERSION_CODES.KITKAT)
  307 + private void drawWave(Canvas canvas, Paint paint, Point[] points, float waveOffset) {
  308 + mWaveLimitPath.reset();
  309 + mWavePath.reset();
  310 + float height = lockWave ? 0 : mRadius - 2 * mRadius * mPercent;
  311 + //moveTo和lineTo绘制出水波区域矩形
  312 + mWavePath.moveTo(points[0].x + waveOffset, points[0].y + height);
  313 +
  314 + for (int i = 1; i < mAllPointCount; i += 2) {
  315 + mWavePath.quadTo(points[i].x + waveOffset, points[i].y + height,
  316 + points[i + 1].x + waveOffset, points[i + 1].y + height);
  317 + }
  318 + //mWavePath.lineTo(points[mAllPointCount - 1].x, points[mAllPointCount - 1].y + height);
  319 + //不管如何移动,波浪与圆路径的交集底部永远固定,否则会造成上移的时候底部为空的情况
  320 + mWavePath.lineTo(points[mAllPointCount - 1].x, mCenterPoint.y + mRadius);
  321 + mWavePath.lineTo(points[0].x, mCenterPoint.y + mRadius);
  322 + mWavePath.close();
  323 + mWaveLimitPath.addCircle(mCenterPoint.x, mCenterPoint.y, mRadius, Path.Direction.CW);
  324 + //取该圆与波浪路径的交集,形成波浪在圆内的效果
  325 + mWaveLimitPath.op(mWavePath, Path.Op.INTERSECT);
  326 + canvas.drawPath(mWaveLimitPath, paint);
  327 + }
  328 +
  329 + //前一次绘制时的进度
  330 + private float mPrePercent;
  331 + //当前进度值
  332 + private String mPercentValue;
  333 +
  334 + private void drawProgress(Canvas canvas) {
  335 + float y = mCenterPoint.y - (mPercentPaint.descent() + mPercentPaint.ascent()) / 2;
  336 + if (mPrePercent == 0.0f || Math.abs(mPercent - mPrePercent) >= 0.01f) {
  337 + mPercentValue = String.format("%.0f%%", mPercent * 100);
  338 + mPrePercent = mPercent;
  339 + }
  340 + canvas.drawText(mPercentValue, mCenterPoint.x, y, mPercentPaint);
  341 +
  342 + if (mHint != null) {
  343 + float hy = mCenterPoint.y * 2 / 3 - (mHintPaint.descent() + mHintPaint.ascent()) / 2;
  344 + canvas.drawText(mHint.toString(), mCenterPoint.x, hy, mHintPaint);
  345 + }
  346 + }
  347 +
  348 + public float getMaxValue() {
  349 + return mMaxValue;
  350 + }
  351 +
  352 + public void setMaxValue(float maxValue) {
  353 + mMaxValue = maxValue;
  354 + }
  355 +
  356 + public float getValue() {
  357 + return mValue;
  358 + }
  359 +
  360 + /**
  361 + * 设置当前值
  362 + *
  363 + * @param value
  364 + */
  365 + public void setValue(float value) {
  366 + if (value > mMaxValue) {
  367 + value = mMaxValue;
  368 + }
  369 + float start = mPercent;
  370 + float end = value / mMaxValue;
  371 + Log.d(TAG, "setValue, value = " + value + ";start = " + start + "; end = " + end);
  372 + startAnimator(start, end, mDarkWaveAnimTime);
  373 + }
  374 +
  375 + private void startAnimator(final float start, float end, long animTime) {
  376 + Log.d(TAG, "startAnimator,value = " + mValue
  377 + + ";start = " + start + ";end = " + end + ";time = " + animTime);
  378 + //当start=0且end=0时,不需要启动动画
  379 + if (start == 0 && end == 0) {
  380 + return;
  381 + }
  382 + mProgressAnimator = ValueAnimator.ofFloat(start, end);
  383 + mProgressAnimator.setDuration(animTime);
  384 + mProgressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  385 + @Override
  386 + public void onAnimationUpdate(ValueAnimator animation) {
  387 + mPercent = (float) animation.getAnimatedValue();
  388 + if (mPercent == 0.0f || mPercent == 1.0f) {
  389 + stopWaveAnimator();
  390 + } else {
  391 + startWaveAnimator();
  392 + }
  393 + mValue = mPercent * mMaxValue;
  394 + invalidate();
  395 + }
  396 + });
  397 + mProgressAnimator.start();
  398 + }
  399 +
  400 + private void startWaveAnimator() {
  401 + startLightWaveAnimator();
  402 + startDarkWaveAnimator();
  403 + }
  404 +
  405 + private void stopWaveAnimator() {
  406 + if (mDarkWaveAnimator != null && mDarkWaveAnimator.isRunning()) {
  407 + mDarkWaveAnimator.cancel();
  408 + mDarkWaveAnimator.removeAllUpdateListeners();
  409 + mDarkWaveAnimator = null;
  410 + }
  411 + if (mLightWaveAnimator != null && mLightWaveAnimator.isRunning()) {
  412 + mLightWaveAnimator.cancel();
  413 + mLightWaveAnimator.removeAllUpdateListeners();
  414 + mLightWaveAnimator = null;
  415 + }
  416 + }
  417 +
  418 + private void startLightWaveAnimator() {
  419 + if (mLightWaveAnimator != null && mLightWaveAnimator.isRunning()) {
  420 + return;
  421 + }
  422 + mLightWaveAnimator = ValueAnimator.ofFloat(0, 2 * mRadius);
  423 + mLightWaveAnimator.setDuration(mLightWaveAnimTime);
  424 + mLightWaveAnimator.setRepeatCount(ValueAnimator.INFINITE);
  425 + mLightWaveAnimator.setInterpolator(new LinearInterpolator());
  426 + mLightWaveAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  427 + @Override
  428 + public void onAnimationUpdate(ValueAnimator animation) {
  429 + mLightWaveOffset = (float) animation.getAnimatedValue();
  430 + postInvalidate();
  431 + }
  432 + });
  433 + mLightWaveAnimator.addListener(new Animator.AnimatorListener() {
  434 + @Override
  435 + public void onAnimationStart(Animator animation) {
  436 + mLightWaveOffset = 0;
  437 + }
  438 +
  439 + @Override
  440 + public void onAnimationEnd(Animator animation) {
  441 +
  442 + }
  443 +
  444 + @Override
  445 + public void onAnimationCancel(Animator animation) {
  446 +
  447 + }
  448 +
  449 + @Override
  450 + public void onAnimationRepeat(Animator animation) {
  451 +
  452 + }
  453 + });
  454 + mLightWaveAnimator.start();
  455 + }
  456 +
  457 + private void startDarkWaveAnimator() {
  458 + if (mDarkWaveAnimator != null && mDarkWaveAnimator.isRunning()) {
  459 + return;
  460 + }
  461 + mDarkWaveAnimator = ValueAnimator.ofFloat(0, 2 * mRadius);
  462 + mDarkWaveAnimator.setDuration(mDarkWaveAnimTime);
  463 + mDarkWaveAnimator.setRepeatCount(ValueAnimator.INFINITE);
  464 + mDarkWaveAnimator.setInterpolator(new LinearInterpolator());
  465 + mDarkWaveAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  466 + @Override
  467 + public void onAnimationUpdate(ValueAnimator animation) {
  468 + mDarkWaveOffset = (float) animation.getAnimatedValue();
  469 + postInvalidate();
  470 + }
  471 + });
  472 + mDarkWaveAnimator.addListener(new Animator.AnimatorListener() {
  473 + @Override
  474 + public void onAnimationStart(Animator animation) {
  475 + mDarkWaveOffset = 0;
  476 + }
  477 +
  478 + @Override
  479 + public void onAnimationEnd(Animator animation) {
  480 +
  481 + }
  482 +
  483 + @Override
  484 + public void onAnimationCancel(Animator animation) {
  485 +
  486 + }
  487 +
  488 + @Override
  489 + public void onAnimationRepeat(Animator animation) {
  490 +
  491 + }
  492 + });
  493 + mDarkWaveAnimator.start();
  494 + }
  495 +
  496 + @Override
  497 + protected void onDetachedFromWindow() {
  498 + super.onDetachedFromWindow();
  499 + stopWaveAnimator();
  500 + if (mProgressAnimator != null && mProgressAnimator.isRunning()) {
  501 + mProgressAnimator.cancel();
  502 + mProgressAnimator.removeAllUpdateListeners();
  503 + mProgressAnimator = null;
  504 + }
  505 + }
  506 +}
... ...
libs/common/src/main/java/com/littlejie/circleprogress/utils/Constant.java
... ... @@ -0,0 +1,26 @@
  1 +package com.littlejie.circleprogress.utils;
  2 +
  3 +/**
  4 + * Created by littlejie on 2017/2/26.
  5 + */
  6 +public class Constant {
  7 +
  8 + public static final boolean ANTI_ALIAS = true;
  9 +
  10 + public static final int DEFAULT_SIZE = 150;
  11 + public static final int DEFAULT_START_ANGLE = 270;
  12 + public static final int DEFAULT_SWEEP_ANGLE = 360;
  13 +
  14 + public static final int DEFAULT_ANIM_TIME = 1000;
  15 +
  16 + public static final int DEFAULT_MAX_VALUE = 100;
  17 + public static final int DEFAULT_VALUE = 50;
  18 +
  19 + public static final int DEFAULT_HINT_SIZE = 15;
  20 + public static final int DEFAULT_UNIT_SIZE = 30;
  21 + public static final int DEFAULT_VALUE_SIZE = 15;
  22 +
  23 + public static final int DEFAULT_ARC_WIDTH = 15;
  24 +
  25 + public static final int DEFAULT_WAVE_HEIGHT = 40;
  26 +}
... ...
libs/common/src/main/java/com/littlejie/circleprogress/utils/MiscUtil.java
... ... @@ -0,0 +1,83 @@
  1 +package com.littlejie.circleprogress.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Paint;
  5 +import android.view.View;
  6 +
  7 +/**
  8 + * Created by littlejie on 2017/2/22.
  9 + */
  10 +
  11 +public class MiscUtil {
  12 +
  13 + /**
  14 + * 测量 View
  15 + *
  16 + * @param measureSpec
  17 + * @param defaultSize View 的默认大小
  18 + * @return
  19 + */
  20 + public static int measure(int measureSpec, int defaultSize) {
  21 + int result = defaultSize;
  22 + int specMode = View.MeasureSpec.getMode(measureSpec);
  23 + int specSize = View.MeasureSpec.getSize(measureSpec);
  24 +
  25 + if (specMode == View.MeasureSpec.EXACTLY) {
  26 + result = specSize;
  27 + } else if (specMode == View.MeasureSpec.AT_MOST) {
  28 + result = Math.min(result, specSize);
  29 + }
  30 + return result;
  31 + }
  32 +
  33 + /**
  34 + * dip 转换成px
  35 + *
  36 + * @param dip
  37 + * @return
  38 + */
  39 + public static int dipToPx(Context context, float dip) {
  40 + float density = context.getResources().getDisplayMetrics().density;
  41 + return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
  42 + }
  43 +
  44 + /**
  45 + * 获取数值精度格式化字符串
  46 + *
  47 + * @param precision
  48 + * @return
  49 + */
  50 + public static String getPrecisionFormat(int precision) {
  51 + return "%." + precision + "f";
  52 + }
  53 +
  54 + /**
  55 + * 反转数组
  56 + *
  57 + * @param arrays
  58 + * @param <T>
  59 + * @return
  60 + */
  61 + public static <T> T[] reverse(T[] arrays) {
  62 + if (arrays == null) {
  63 + return null;
  64 + }
  65 + int length = arrays.length;
  66 + for (int i = 0; i < length / 2; i++) {
  67 + T t = arrays[i];
  68 + arrays[i] = arrays[length - i - 1];
  69 + arrays[length - i - 1] = t;
  70 + }
  71 + return arrays;
  72 + }
  73 +
  74 + /**
  75 + * 测量文字高度
  76 + * @param paint
  77 + * @return
  78 + */
  79 + public static float measureTextHeight(Paint paint) {
  80 + Paint.FontMetrics fontMetrics = paint.getFontMetrics();
  81 + return (Math.abs(fontMetrics.ascent) - fontMetrics.descent);
  82 + }
  83 +}
0 84 \ No newline at end of file
... ...
libs/common/src/main/res/values/attrs_circle_progress.xml
... ... @@ -0,0 +1,139 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- 是否开启抗锯齿 -->
  4 + <attr name="antiAlias" format="boolean" />
  5 + <!-- 圆弧起始角度,3点钟方向为0,顺时针递增,小于0或大于360进行取余 -->
  6 + <attr name="startAngle" format="float" />
  7 + <!-- 圆弧度数 -->
  8 + <attr name="sweepAngle" format="float" />
  9 + <!-- 设置动画时间 -->
  10 + <attr name="animTime" format="integer" />
  11 + <!-- 绘制内容的数值 -->
  12 + <attr name="maxValue" format="float" />
  13 + <attr name="value" format="float" />
  14 + <!-- 绘制内容的单位 -->
  15 + <attr name="unit" format="string|reference" />
  16 + <attr name="unitSize" format="dimension" />
  17 + <attr name="unitColor" format="color|reference" />
  18 + <!-- 绘制内容相应的提示语 -->
  19 + <attr name="hint" format="string|reference" />
  20 + <attr name="hintSize" format="dimension" />
  21 + <attr name="hintColor" format="color|reference" />
  22 + <!-- 精度,默认为0 -->
  23 + <attr name="precision" format="integer" />
  24 + <attr name="valueSize" format="dimension" />
  25 + <attr name="valueColor" format="color|reference" />
  26 +
  27 + <!-- 背景圆弧颜色,默认白色 -->
  28 + <attr name="bgArcColor" format="color|reference" />
  29 + <!-- 圆弧宽度 -->
  30 + <attr name="arcWidth" format="dimension" />
  31 + <!-- 圆弧颜色, -->
  32 + <attr name="arcColors" format="color|reference" />
  33 + <!-- 文字的偏移量。相对于圆半径而言,默认三分之一 -->
  34 + <attr name="textOffsetPercentInRadius" format="float" />
  35 +
  36 + <!-- 圆形进度条 -->
  37 + <declare-styleable name="CircleProgressBar">
  38 + <attr name="antiAlias" />
  39 + <attr name="startAngle" />
  40 + <attr name="sweepAngle" />
  41 + <attr name="animTime" />
  42 + <attr name="maxValue" />
  43 + <attr name="value" />
  44 + <attr name="precision" />
  45 + <attr name="valueSize" />
  46 + <attr name="valueColor" />
  47 + <attr name="textOffsetPercentInRadius" />
  48 + <!-- 绘制内容相应的提示语 -->
  49 + <attr name="hint" />
  50 + <attr name="hintSize" />
  51 + <attr name="hintColor" />
  52 + <!-- 绘制内容的单位 -->
  53 + <attr name="unit" />
  54 + <attr name="unitSize" />
  55 + <attr name="unitColor" />
  56 + <!-- 圆弧宽度 -->
  57 + <attr name="arcWidth" />
  58 + <attr name="arcColors" />
  59 + <!-- 背景圆弧颜色 -->
  60 + <attr name="bgArcColor" />
  61 + <!-- 背景圆弧宽度 -->
  62 + <attr name="bgArcWidth" format="dimension" />
  63 + </declare-styleable>
  64 +
  65 + <declare-styleable name="DialProgress">
  66 + <attr name="antiAlias" />
  67 + <attr name="startAngle" />
  68 + <attr name="sweepAngle" />
  69 + <attr name="animTime" />
  70 + <attr name="maxValue" />
  71 + <attr name="value" />
  72 + <attr name="precision" />
  73 + <attr name="valueSize" />
  74 + <attr name="valueColor" />
  75 + <attr name="textOffsetPercentInRadius" />
  76 + <!-- 绘制内容的单位 -->
  77 + <attr name="unit" />
  78 + <attr name="unitSize" />
  79 + <attr name="unitColor" />
  80 + <!-- 绘制内容相应的提示语 -->
  81 + <attr name="hint" />
  82 + <attr name="hintSize" />
  83 + <attr name="hintColor" />
  84 + <!-- 圆弧的宽度 -->
  85 + <attr name="arcWidth" />
  86 + <!-- 刻度的宽度 -->
  87 + <attr name="dialWidth" format="dimension|reference" />
  88 + <!-- 刻度之间的间隔 -->
  89 + <attr name="dialIntervalDegree" format="integer" />
  90 + <!-- 圆弧颜色, -->
  91 + <attr name="arcColors" />
  92 + <!-- 背景圆弧线颜色 -->
  93 + <attr name="bgArcColor" />
  94 + <!-- 刻度线颜色 -->
  95 + <attr name="dialColor" format="color|reference" />
  96 + </declare-styleable>
  97 +
  98 + <declare-styleable name="WaveProgress">
  99 + <!-- 是否开启抗锯齿 -->
  100 + <attr name="antiAlias" />
  101 + <!-- 深色水波动画时间 -->
  102 + <attr name="darkWaveAnimTime" format="integer" />
  103 + <!-- 浅色水波动画时间 -->
  104 + <attr name="lightWaveAnimTime" format="integer" />
  105 + <!-- 最大值 -->
  106 + <attr name="maxValue" />
  107 + <!-- 当前值 -->
  108 + <attr name="value" />
  109 + <attr name="valueColor" />
  110 + <attr name="valueSize" />
  111 + <!-- 绘制内容相应的提示语 -->
  112 + <attr name="hint" />
  113 + <attr name="hintSize" />
  114 + <attr name="hintColor" />
  115 + <!-- 圆环宽度 -->
  116 + <attr name="circleWidth" format="dimension" />
  117 + <!-- 圆环颜色 -->
  118 + <attr name="circleColor" format="color|reference" />
  119 + <!-- 背景圆环颜色 -->
  120 + <attr name="bgCircleColor" format="color|reference" />
  121 + <!-- 锁定水波不随圆环进度改变,默认锁定在50%处 -->
  122 + <attr name="lockWave" format="boolean" />
  123 + <!-- 水波数量 -->
  124 + <attr name="waveNum" format="integer" />
  125 + <!-- 水波高度,峰值和谷值之和 -->
  126 + <attr name="waveHeight" format="dimension" />
  127 + <!-- 深色水波颜色 -->
  128 + <attr name="darkWaveColor" format="color|reference" />
  129 + <!-- 是否显示浅色水波 -->
  130 + <attr name="showLightWave" format="boolean" />
  131 + <!-- 浅色水波颜色 -->
  132 + <attr name="lightWaveColor" format="color|reference" />
  133 + <!-- 浅色水波的方向 -->
  134 + <attr name="lightWaveDirect" format="enum">
  135 + <enum name="L2R" value="0" />
  136 + <enum name="R2L" value="1" />
  137 + </attr>
  138 + </declare-styleable>
  139 +</resources>
0 140 \ No newline at end of file
... ...