Browse Source

feat: 🔗 列表视图

master
niushuai233 1 year ago
parent
commit
849bab9187
  1. 80
      app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java
  2. 8
      app/src/main/java/cc/niushuai/dididone/biz/dao/RecordDao.java
  3. 49
      app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java
  4. 23
      app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/BaseChartFragment.java
  5. 99
      app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/ListFragment.java
  6. 62
      app/src/main/res/layout/fragment_stat_list.xml

80
app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java

@ -1,15 +1,30 @@ @@ -1,15 +1,30 @@
package cc.niushuai.dididone.biz;
import android.content.Context;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.mikepenz.iconics.IconicsDrawable;
import com.mikepenz.iconics.view.IconicsImageView;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import cc.niushuai.dididone.R;
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.biz.vo.ProjectCount;
import cc.niushuai.dididone.util.IntSnowflake;
import cc.niushuai.dididone.util.XLog;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -30,6 +45,10 @@ public class BizGlobal { @@ -30,6 +45,10 @@ public class BizGlobal {
public static void buildCache() {
if (!CACHE_PROJECT.isEmpty()) {
return;
}
// 打卡项缓存
buildProjectCache();
@ -72,4 +91,65 @@ public class BizGlobal { @@ -72,4 +91,65 @@ public class BizGlobal {
public static Map<Long, Project> getAvailableProjectMap() {
return CACHE_PROJECT.values().stream().filter(item -> item.getDeleted().equals(0)).collect(Collectors.toMap(Project::getId, Function.identity()));
}
public static List<Project> getAvailableProjectList() {
return CACHE_PROJECT.values()
.stream()
.filter(item -> item.getDeleted().equals(0))
.sorted((e1, e2) -> e2.getCreateDate().compareTo(e1.getCreateDate()))
.collect(Collectors.toList());
}
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);
// 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;
}
private static TextView getTextView(Context context, int id, String text, ViewGroup.LayoutParams textLayoutParams, int textColor, int textSize, int gravity) {
TextView textView = new TextView(context);
textView.setId(id);
textView.setLayoutParams(textLayoutParams);
textView.setText(text);
textView.setTextColor(context.getResources().getColor(textColor));
textView.setTextSize(textSize);
textView.setGravity(gravity);
return textView;
}
}

8
app/src/main/java/cc/niushuai/dididone/biz/dao/RecordDao.java

@ -4,7 +4,9 @@ import androidx.room.Dao; @@ -4,7 +4,9 @@ import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.RoomWarnings;
import java.util.Iterator;
import java.util.List;
import cc.niushuai.dididone.biz.entity.Record;
@ -39,6 +41,10 @@ public interface RecordDao { @@ -39,6 +41,10 @@ public interface RecordDao {
@Query("select b.id, b.name, count(a.id) as count from t_record a left join t_project b on b.id = a.project_id and b.deleted = 0 where a.deleted = 0 group by b.id, b.name")
Flowable<List<ProjectCount>> groupCountProject();
@Query("select check_date from t_record where deleted = 0 and create_date >= :startTime and create_date <= :endTime order by check_date asc")
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Query("select check_date from t_record where deleted = 0 and check_date >= :startTime and check_date <= :endTime order by check_date asc")
Flowable<List<Record>> queryPointByDate(long startTime, long endTime);
@Query("select * from t_record where deleted = 0 and project_id = :projectId and check_date >= :startDate and check_date <= :endDate order by check_date desc")
Flowable<List<Record>> queryByProjectAndDate(Long projectId, long startDate, long endDate);
}

49
app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java

@ -305,43 +305,7 @@ public class CalendarFragment extends Fragment { @@ -305,43 +305,7 @@ public class CalendarFragment extends Fragment {
}
private void add2Top(Project project, Record record) {
// 外层layout 白色背景 存在边距
RelativeLayout itemLayout = new RelativeLayout(getContext());
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(getContext());
int iconViewId = IntSnowflake.next_id();
iconView.setId(iconViewId);
iconView.setLayoutParams(iconLayout);
IconicsDrawable icon = new IconicsDrawable(getContext());
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 = this.getTextView(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 = this.getTextView(IntSnowflake.next_id(), DateUtil.date(record.getCreateDate()).toString(DatePattern.NORM_DATETIME_PATTERN), dateLayout, R.color._666666, 12, Gravity.TOP);
itemLayout.addView(dateTextView);
RelativeLayout itemLayout = BizGlobal.getItemLayout(getContext(), project, record);
itemLayout.setOnLongClickListener(new View.OnLongClickListener() {
@Override
@ -378,17 +342,6 @@ public class CalendarFragment extends Fragment { @@ -378,17 +342,6 @@ public class CalendarFragment extends Fragment {
DBManager.INSTANCE.recordDao().deleteById(record.getId());
}
private TextView getTextView(int id, String text, ViewGroup.LayoutParams textLayoutParams, int textColor, int textSize, int gravity) {
TextView textView = new TextView(getContext());
textView.setId(id);
textView.setLayoutParams(textLayoutParams);
textView.setText(text);
textView.setTextColor(getResources().getColor(textColor));
textView.setTextSize(textSize);
textView.setGravity(gravity);
return textView;
}
@Override
public void onDestroyView() {

23
app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/BaseChartFragment.java

@ -1,11 +1,25 @@ @@ -1,11 +1,25 @@
package cc.niushuai.dididone.ui.statistic.charts;
import java.util.Iterator;
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 {
private String mTitle;
private List<Record> recordList;
public BaseChartFragment(String mTitle) {
this.mTitle = mTitle;
}
@ -13,4 +27,13 @@ public class BaseChartFragment extends BaseFragment { @@ -13,4 +27,13 @@ public class BaseChartFragment extends BaseFragment {
public String getTitle() {
return mTitle;
}
public List<Record> getRecordList() {
return recordList;
}
protected long dateStr2mills(String date) {
return DateUtil.parseDate(date).getTime();
}
}

99
app/src/main/java/cc/niushuai/dididone/ui/statistic/charts/ListFragment.java

@ -4,14 +4,33 @@ import android.os.Bundle; @@ -4,14 +4,33 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.List;
import java.util.stream.Collectors;
import cc.niushuai.dididone.R;
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.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;
public class ListFragment extends BaseChartFragment {
private FragmentStatListBinding binding;
public ListFragment() {
super("列表视图");
@ -21,7 +40,87 @@ public class ListFragment extends BaseChartFragment { @@ -21,7 +40,87 @@ public class ListFragment extends BaseChartFragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_stat_list, container, false);
binding = FragmentStatListBinding.bind(view);
return view;
}
@Override
public void init() {
// 初始化初始日期
initDate(binding.statListStartDate, binding.statListEndDate);
// 初始化spinner
initSpinner(binding.statListSpinnerProject);
}
private void initDate(TextView startDate, TextView endDate) {
String today = DateUtil.date().toDateStr();
startDate.setText(today);
endDate.setText(today);
}
private void initSpinner(Spinner spinner) {
List<String> items = BizGlobal.getAvailableProjectList().stream().map(item -> item.getName()).collect(Collectors.toList());
spinner.setAdapter(new ArrayAdapter<>(getContext(), androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, items));
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
onConditionChange(position, binding.statListStartDate.getText(), binding.statListEndDate.getText());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setSelection(0);
}
private void onConditionChange(int position, CharSequence startDate, CharSequence endDate) {
Flowable<List<Record>> listFlowable = DBManager.INSTANCE.recordDao().queryByProjectAndDate(
BizGlobal.getAvailableProjectList().get(position).getId(),
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()));
onRecordDataList(recordList);
});
}
private void onRecordDataList(List<Record> recordList) {
// 更新视图
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);
});
}
}
private void add2Top(Project project, Record record) {
RelativeLayout itemLayout = BizGlobal.getItemLayout(getContext(), project, record);
binding.statListCheckInList.addView(itemLayout, 0);
binding.statListSpinnerProject.requestLayout();
}
@Override
public void setListeners() {
binding.statListStartDate.setOnClickListener(v -> {
});
binding.statListEndDate.setOnClickListener(v -> {
});
}
}

62
app/src/main/res/layout/fragment_stat_list.xml

@ -1,12 +1,62 @@ @@ -1,12 +1,62 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="50dp"
android:background="@color/gray_light_more"
>
<Spinner
android:id="@+id/stat_list_spinner_project"
android:layout_width="0dp"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:layout_weight="0.3" />
<TextView
android:id="@+id/stat_list_start_date"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.3"
android:gravity="center"
android:text="2024-11-11"
android:textSize="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="50sp"
android:text="list"/>
android:gravity="center"
android:text="~"
android:textSize="16dp" />
<TextView
android:id="@+id/stat_list_end_date"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="20dp"
android:layout_weight="0.3"
android:gravity="center"
android:text="2024-11-11"
android:textSize="16dp" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray_light_less">
<LinearLayout
android:id="@+id/stat_list_check_in_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
Loading…
Cancel
Save