From 3940ae91b5d0dd7a6ebfed873241bf0f5d20be20 Mon Sep 17 00:00:00 2001 From: niushuai233 Date: Fri, 19 Apr 2024 11:51:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20:x:=20=E5=AD=98=E5=9C=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E7=9A=84=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 + .../cc/niushuai/dididone/biz/BizGlobal.java | 121 ++++++++++++------ .../dididone/ui/base/BaseFragment.java | 4 + .../ui/calendar/CalendarFragment.java | 2 + .../dididone/ui/statistic/MyPagerAdapter.java | 5 +- .../ui/statistic/StatisticFragment.java | 27 ++-- .../statistic/charts/BaseChartFragment.java | 46 ++++++- .../ui/statistic/charts/ListFragment.java | 48 ++++++- .../main/res/layout/fragment_stat_list.xml | 19 ++- .../main/res/layout/fragment_statistic.xml | 11 +- 10 files changed, 217 insertions(+), 68 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 44ab81d..7ef20d0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,6 +67,8 @@ dependencies { // calendar 组件 // implementation 'com.github.angcyo:CalendarView:3.7.1.37' implementation 'com.necer.ncalendar:ncalendar:5.0.2' + // 时间选择器组件 + implementation 'com.github.loper7:DateTimePicker:0.6.3' // 颜色选择器 implementation "com.github.skydoves:colorpickerview:2.3.0" // fab 组件 diff --git a/app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java b/app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java index 5c45d9f..2320fff 100644 --- a/app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java +++ b/app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java @@ -7,9 +7,12 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; +import com.loper7.date_time_picker.DateTimeConfig; +import com.loper7.date_time_picker.dialog.CardDatePickerDialog; import com.mikepenz.iconics.IconicsDrawable; import com.mikepenz.iconics.view.IconicsImageView; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,6 +31,8 @@ import cn.hutool.core.date.DateUtil; import io.reactivex.Flowable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; +import kotlin.Unit; +import kotlin.jvm.functions.Function1; /** * 业务全局对象 @@ -101,44 +106,44 @@ public class BizGlobal { } public static RelativeLayout getItemLayout(Context context, Project project, Record record) { - // 外层layout 白色背景 存在边距 - RelativeLayout itemLayout = new RelativeLayout(context); - RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 175); - layoutParams.setMargins(25, 20, 25, 15); - - itemLayout.setId(IntSnowflake.next_id()); - itemLayout.setLayoutParams(layoutParams); - itemLayout.setPadding(15, 15, 15, 5); - itemLayout.setBackgroundResource(R.drawable.bg_miui10); + // 外层layout 白色背景 存在边距 + RelativeLayout itemLayout = new RelativeLayout(context); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 175); + layoutParams.setMargins(25, 20, 25, 15); + + itemLayout.setId(IntSnowflake.next_id()); + itemLayout.setLayoutParams(layoutParams); + itemLayout.setPadding(15, 15, 15, 5); + itemLayout.setBackgroundResource(R.drawable.bg_miui10); // itemLayout.setOrientation(LinearLayout.VERTICAL); - // projectIcon layout - RelativeLayout.LayoutParams iconLayout = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); - iconLayout.setMargins(10, 5, 0, 0); - IconicsImageView iconView = new IconicsImageView(context); - int iconViewId = IntSnowflake.next_id(); - iconView.setId(iconViewId); - iconView.setLayoutParams(iconLayout); - IconicsDrawable icon = new IconicsDrawable(context); - icon.icon(project.getIcon()).color(project.getIconColor()).sizeDp(50); - iconView.setIcon(icon); - - itemLayout.addView(iconView); - - RelativeLayout.LayoutParams projectLayout = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); - projectLayout.setMargins(20, 5, 0, 0); - projectLayout.addRule(RelativeLayout.RIGHT_OF, iconViewId); - int projectNameViewId = IntSnowflake.next_id(); - TextView projectTextView = getTextView(context, projectNameViewId, record.getName(), projectLayout, R.color._333333, 16, Gravity.CENTER_VERTICAL); - itemLayout.addView(projectTextView); - - RelativeLayout.LayoutParams dateLayout = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); - dateLayout.setMargins(20, 25, 0, 0); - dateLayout.addRule(RelativeLayout.RIGHT_OF, iconViewId); - dateLayout.addRule(RelativeLayout.BELOW, projectNameViewId); - TextView dateTextView = getTextView(context, IntSnowflake.next_id(), DateUtil.date(record.getCreateDate()).toString(DatePattern.NORM_DATETIME_PATTERN), dateLayout, R.color._666666, 12, Gravity.TOP); - itemLayout.addView(dateTextView); - return itemLayout; + // projectIcon layout + RelativeLayout.LayoutParams iconLayout = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + iconLayout.setMargins(10, 5, 0, 0); + IconicsImageView iconView = new IconicsImageView(context); + int iconViewId = IntSnowflake.next_id(); + iconView.setId(iconViewId); + iconView.setLayoutParams(iconLayout); + IconicsDrawable icon = new IconicsDrawable(context); + icon.icon(project.getIcon()).color(project.getIconColor()).sizeDp(50); + iconView.setIcon(icon); + + itemLayout.addView(iconView); + + RelativeLayout.LayoutParams projectLayout = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + projectLayout.setMargins(20, 5, 0, 0); + projectLayout.addRule(RelativeLayout.RIGHT_OF, iconViewId); + int projectNameViewId = IntSnowflake.next_id(); + TextView projectTextView = getTextView(context, projectNameViewId, record.getName(), projectLayout, R.color._333333, 16, Gravity.CENTER_VERTICAL); + itemLayout.addView(projectTextView); + + RelativeLayout.LayoutParams dateLayout = new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + dateLayout.setMargins(20, 25, 0, 0); + dateLayout.addRule(RelativeLayout.RIGHT_OF, iconViewId); + dateLayout.addRule(RelativeLayout.BELOW, projectNameViewId); + TextView dateTextView = getTextView(context, IntSnowflake.next_id(), DateUtil.date(record.getCreateDate()).toString(DatePattern.NORM_DATETIME_PATTERN), dateLayout, R.color._666666, 12, Gravity.TOP); + itemLayout.addView(dateTextView); + return itemLayout; } private static TextView getTextView(Context context, int id, String text, ViewGroup.LayoutParams textLayoutParams, int textColor, int textSize, int gravity) { @@ -152,4 +157,48 @@ public class BizGlobal { textView.setGravity(gravity); return textView; } + + public static void buildCardDatePickerDialog(Context context, String title, + Long defaultDate, Long minDate, Long maxDate, boolean showTime, + String confirmTxt, Function1 unitFunction) { + + CardDatePickerDialog.Builder builder = new CardDatePickerDialog.Builder(context); + builder.setTitle(title) + .setBackGroundModel(CardDatePickerDialog.STACK) + .showBackNow(false) + .setWrapSelectorWheel(false) + .showDateLabel(true) + .showFocusDateInfo(true) + .setOnChoose(confirmTxt, unitFunction); + + if (null != defaultDate) { + builder.setDefaultTime(defaultDate); + } + + List displayTypeList = new ArrayList<>(6); + displayTypeList.add(DateTimeConfig.YEAR); + displayTypeList.add(DateTimeConfig.MONTH); + displayTypeList.add(DateTimeConfig.DAY); + + if (showTime) { + displayTypeList.add(DateTimeConfig.HOUR); + displayTypeList.add(DateTimeConfig.MIN); + displayTypeList.add(DateTimeConfig.SECOND); + } + + builder.setDisplayType(displayTypeList); + + if (null != minDate) { + builder.setMinTime(minDate); + } + if (null != maxDate) { + builder.setMaxTime(maxDate); + } + + builder.build().show(); + } + + public static Long getTextViewDate(TextView textView) { + return DateUtil.parseDate(textView.getText().toString()).getTime(); + } } diff --git a/app/src/main/java/cc/niushuai/dididone/ui/base/BaseFragment.java b/app/src/main/java/cc/niushuai/dididone/ui/base/BaseFragment.java index 8ee81d8..ecb973d 100644 --- a/app/src/main/java/cc/niushuai/dididone/ui/base/BaseFragment.java +++ b/app/src/main/java/cc/niushuai/dididone/ui/base/BaseFragment.java @@ -9,6 +9,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import cc.niushuai.dididone.util.XLog; + public abstract class BaseFragment extends Fragment implements InitAndSetListener { @@ -26,6 +28,8 @@ public abstract class BaseFragment extends Fragment implements InitAndSetListene init(); setListeners(); + + XLog.d("{} onViewCreated", getId()); } } diff --git a/app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java b/app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java index 4bedb42..943630c 100644 --- a/app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java +++ b/app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java @@ -85,6 +85,8 @@ public class CalendarFragment extends Fragment { private void init() { initPointList(); + binding.miui10Calendar.setInitializeDate(DateUtil.date().toDateStr()); + // 构建弹出框内容 // fetchNewestActionButtonData(); diff --git a/app/src/main/java/cc/niushuai/dididone/ui/statistic/MyPagerAdapter.java b/app/src/main/java/cc/niushuai/dididone/ui/statistic/MyPagerAdapter.java index fdcb69d..004863d 100644 --- a/app/src/main/java/cc/niushuai/dididone/ui/statistic/MyPagerAdapter.java +++ b/app/src/main/java/cc/niushuai/dididone/ui/statistic/MyPagerAdapter.java @@ -1,15 +1,18 @@ package cc.niushuai.dididone.ui.statistic; +import android.view.ViewGroup; + import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; +import androidx.fragment.app.FragmentStatePagerAdapter; import java.util.List; import cc.niushuai.dididone.ui.statistic.charts.BaseChartFragment; -public class MyPagerAdapter extends FragmentPagerAdapter { +public class MyPagerAdapter extends FragmentStatePagerAdapter { List fragmentList; //构造方法,方便之后赋值调用 diff --git a/app/src/main/java/cc/niushuai/dididone/ui/statistic/StatisticFragment.java b/app/src/main/java/cc/niushuai/dididone/ui/statistic/StatisticFragment.java index 1b96a03..7356db1 100644 --- a/app/src/main/java/cc/niushuai/dididone/ui/statistic/StatisticFragment.java +++ b/app/src/main/java/cc/niushuai/dididone/ui/statistic/StatisticFragment.java @@ -6,11 +6,11 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.viewpager.widget.ViewPager; -import com.flyco.tablayout.SlidingTabLayout; import com.google.android.material.tabs.TabLayout; import java.util.ArrayList; @@ -27,6 +27,7 @@ import cc.niushuai.dididone.ui.statistic.charts.WeekFragment; public class StatisticFragment extends Fragment { private FragmentStatisticBinding binding; + List fragments = new ArrayList<>(4);; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -36,23 +37,31 @@ public class StatisticFragment extends Fragment { binding = FragmentStatisticBinding.inflate(inflater, container, false); View root = binding.getRoot(); - ViewPager viewPager = binding.statViewpager; - SlidingTabLayout tabLayout = binding.statTabLayout; +// SlidingTabLayout tabLayout = binding.statTabLayout; + TabLayout tabLayout = binding.statTabLayout; // 初始化所有的fragment - List fragments = new ArrayList<>(); - fragments.add(new ListFragment()); - fragments.add(new WeekFragment()); - fragments.add(new MonthFragment()); - fragments.add(new OtherFragment()); + if (fragments.isEmpty()) { + fragments.add(new ListFragment()); + fragments.add(new WeekFragment()); + fragments.add(new MonthFragment()); + fragments.add(new OtherFragment()); + } + + viewPager.setOffscreenPageLimit(1); MyPagerAdapter adapter = new MyPagerAdapter(getActivity().getSupportFragmentManager(), fragments); //绑定adapter viewPager.setAdapter(adapter); //绑定viewPager List titles = fragments.stream().map(BaseChartFragment::getTitle).collect(Collectors.toList()); - tabLayout.setViewPager(viewPager, titles.toArray(new String[0])); + tabLayout.setupWithViewPager(viewPager); + + //设置标题 + for (int i = 0; i < titles.size(); i++) { + tabLayout.getTabAt(i).setText(titles.get(i)); + } return root; } diff --git a/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/BaseChartFragment.java b/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/BaseChartFragment.java index adc112e..6add08b 100644 --- a/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/BaseChartFragment.java +++ b/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/BaseChartFragment.java @@ -1,18 +1,19 @@ package cc.niushuai.dididone.ui.statistic.charts; -import java.util.Iterator; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.util.List; -import cc.niushuai.dididone.biz.BizGlobal; -import cc.niushuai.dididone.biz.entity.Project; import cc.niushuai.dididone.biz.entity.Record; -import cc.niushuai.dididone.biz.roomx.DBManager; import cc.niushuai.dididone.ui.base.BaseFragment; import cc.niushuai.dididone.util.XLog; import cn.hutool.core.date.DateUtil; -import io.reactivex.Flowable; -import io.reactivex.Single; -import io.reactivex.android.schedulers.AndroidSchedulers; public class BaseChartFragment extends BaseFragment { @@ -36,4 +37,35 @@ public class BaseChartFragment extends BaseFragment { return DateUtil.parseDate(date).getTime(); } + @Override + public void onStart() { + super.onStart(); + XLog.d("{} onStart", getTitle()); + } + + @Override + public void onDestroy() { + super.onDestroy(); + XLog.d("{} onDestroy", getTitle()); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + XLog.d("{} onDestroyView", getTitle()); + } + + @Override + public void onViewStateRestored(@Nullable Bundle savedInstanceState) { + super.onViewStateRestored(savedInstanceState); + XLog.d("{} onViewStateRestored", getTitle()); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + setRetainInstance(true); + super.onCreate(savedInstanceState); + XLog.d("{} onCreate", getTitle()); + } + } diff --git a/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/ListFragment.java b/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/ListFragment.java index cecbea6..c99e215 100644 --- a/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/ListFragment.java +++ b/app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/ListFragment.java @@ -1,5 +1,7 @@ package cc.niushuai.dididone.ui.statistic.charts; +import static cc.niushuai.dididone.biz.BizGlobal.getTextViewDate; + import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -25,8 +27,9 @@ import cc.niushuai.dididone.databinding.FragmentStatListBinding; import cc.niushuai.dididone.util.XLog; import cn.hutool.core.date.DateUtil; import io.reactivex.Flowable; -import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; +import kotlin.Unit; +import kotlin.jvm.functions.Function1; public class ListFragment extends BaseChartFragment { @@ -39,9 +42,10 @@ public class ListFragment extends BaseChartFragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + XLog.d("{} onCreateView", getTitle()); View view = inflater.inflate(R.layout.fragment_stat_list, container, false); binding = FragmentStatListBinding.bind(view); - return view; + return binding.getRoot(); } @Override @@ -84,6 +88,8 @@ public class ListFragment extends BaseChartFragment { dateStr2mills(startDate.toString()), dateStr2mills(endDate.toString())); + + listFlowable.subscribeOn(Schedulers.io()).subscribe(recordList -> { XLog.d("recordList: {}", recordList.size()); recordList.forEach(item -> XLog.d("{} at {}", item.getName(), DateUtil.date(item.getCheckDate()).toDateStr())); @@ -93,14 +99,17 @@ public class ListFragment extends BaseChartFragment { } private void onRecordDataList(List recordList) { + + getActivity().runOnUiThread(() -> { + binding.statTotalMsg.setText("总计: " + recordList.size() + "条记录"); + binding.statListCheckInList.removeAllViews(); + }); + // 更新视图 for (int i = recordList.size() - 1; i >= 0; i--) { // 查出来的数据是倒叙的 Record record = recordList.get(i); - getActivity().runOnUiThread(() -> { - binding.statListCheckInList.removeAllViews(); - add2Top(BizGlobal.CACHE_PROJECT.get(record.getProjectId()), record); - }); + getActivity().runOnUiThread(() -> add2Top(BizGlobal.CACHE_PROJECT.get(record.getProjectId()), record)); } } @@ -116,11 +125,38 @@ public class ListFragment extends BaseChartFragment { public void setListeners() { binding.statListStartDate.setOnClickListener(v -> { + Function1 unitFunction = millisecond -> { + String dateStr = DateUtil.date(millisecond).toDateStr(); + XLog.d("select date = {}", dateStr); + + binding.statListStartDate.setText(dateStr); + + onConditionChange(binding.statListSpinnerProject.getSelectedItemPosition(), binding.statListStartDate.getText(), binding.statListEndDate.getText()); + return null; + }; + + BizGlobal.buildCardDatePickerDialog(getContext(), "选择起始日期", getTextViewDate(binding.statListStartDate), null, getTextViewDate(binding.statListEndDate), + false, "确定", unitFunction); }); binding.statListEndDate.setOnClickListener(v -> { + Function1 unitFunction = millisecond -> { + String dateStr = DateUtil.date(millisecond).toDateStr(); + XLog.d("select date = {}", dateStr); + + binding.statListEndDate.setText(dateStr); + + onConditionChange(binding.statListSpinnerProject.getSelectedItemPosition(), binding.statListStartDate.getText(), binding.statListEndDate.getText()); + + return null; + }; + BizGlobal.buildCardDatePickerDialog(getContext(), "选择结束日期", getTextViewDate(binding.statListEndDate), getTextViewDate(binding.statListStartDate), null, + false, "确定", unitFunction); }); + } + + } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_stat_list.xml b/app/src/main/res/layout/fragment_stat_list.xml index 9ddf6a7..ca96a1f 100644 --- a/app/src/main/res/layout/fragment_stat_list.xml +++ b/app/src/main/res/layout/fragment_stat_list.xml @@ -1,19 +1,17 @@ + android:orientation="vertical"> + android:background="@color/gray_light_more"> @@ -46,6 +44,15 @@ + + + android:orientation="vertical" /> diff --git a/app/src/main/res/layout/fragment_statistic.xml b/app/src/main/res/layout/fragment_statistic.xml index 55d7eef..cc9e38c 100644 --- a/app/src/main/res/layout/fragment_statistic.xml +++ b/app/src/main/res/layout/fragment_statistic.xml @@ -4,10 +4,15 @@ android:layout_height="match_parent" android:orientation="vertical"> - - + +