Browse Source

feat: 打卡支持选择时间

master
niushuai233 15 hours ago
parent
commit
d41bfb6b24
  1. 2
      app/src/main/java/cc/niushuai/dididone/biz/BizGlobal.java
  2. 9
      app/src/main/java/cc/niushuai/dididone/ui/calendar/CalendarFragment.java
  3. 56
      app/src/main/java/cc/niushuai/dididone/ui/component/ProjectPopupView.java
  4. 64
      app/src/main/java/cc/niushuai/dididone/ui/component/TimeNotePopupView.java
  5. 56
      app/src/main/res/layout/time_note_popup_view.xml
  6. 40
      app/src/main/res/values-land/strings.xml
  7. 40
      app/src/main/res/values-night/strings.xml
  8. 40
      app/src/main/res/values-w1240dp/strings.xml
  9. 40
      app/src/main/res/values-w600dp/strings.xml

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

@ -45,6 +45,8 @@ public class BizGlobal { @@ -45,6 +45,8 @@ public class BizGlobal {
public static final String PROJECT_ICON_COLOR = "projectIconColor";
public static final Map<Long, Project> CACHE_PROJECT = new HashMap<>();
public static final Map<Long, Integer> CACHE_PROJECT_COUNT = new HashMap<>();
public static final Map<Long, Integer> CACHE_PROJECT_TODAY_COUNT = new HashMap<>();
public static final Map<String, List<Record>> CACHE_RECORD_LIST = new HashMap<>();
public static final String EMPTY_PROJECT_TIPS = "先去添加打卡项吧~";
public static final String EMPTY_PROJECT_TIPS_ICON = "cmd_alert_decagram_outline";
public static final int REQUEST_CODE_GENERAL = 1;

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

@ -38,6 +38,7 @@ import org.reactivestreams.Subscription; @@ -38,6 +38,7 @@ import org.reactivestreams.Subscription;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import cc.niushuai.dididone.R;
@ -161,9 +162,9 @@ public class CalendarFragment extends BaseFragment { @@ -161,9 +162,9 @@ public class CalendarFragment extends BaseFragment {
.hasShadowBg(true)
.isViewMode(true)
.isDestroyOnDismiss(true)
.asCustom(new ProjectPopupView(getContext(), project -> {
.asCustom(new ProjectPopupView(getContext(), (project, extraMap) -> {
// item click callback
add2Top(project);
add2Top(project, extraMap);
}))
.show();
@ -294,7 +295,7 @@ public class CalendarFragment extends BaseFragment { @@ -294,7 +295,7 @@ public class CalendarFragment extends BaseFragment {
}
private void add2Top(Project project) {
private void add2Top(Project project, Map<String, String> extraMap) {
// 过滤掉empty选项
if (BizGlobal.EMPTY_PROJECT_TIPS.equals(project.getName())) {
return;
@ -304,6 +305,8 @@ public class CalendarFragment extends BaseFragment { @@ -304,6 +305,8 @@ public class CalendarFragment extends BaseFragment {
record.setProjectId(project.getId());
record.setName(project.getName());
record.setCheckDate(DateUtil.parseDate(lastDate).getTime());
record.setCreateDate(DateUtil.parseDateTime(extraMap.get("time")).getTime());
record.setDescription(extraMap.getOrDefault("note", ""));
// 插入数据库
Completable completable = DBManager.INSTANCE.recordDao().insertAll(record);

56
app/src/main/java/cc/niushuai/dididone/ui/component/ProjectPopupView.java

@ -12,19 +12,27 @@ import androidx.recyclerview.widget.RecyclerView; @@ -12,19 +12,27 @@ import androidx.recyclerview.widget.RecyclerView;
import com.lxj.easyadapter.EasyAdapter;
import com.lxj.easyadapter.MultiItemTypeAdapter;
import com.lxj.easyadapter.ViewHolder;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BottomPopupView;
import com.lxj.xpopup.util.XPopupUtils;
import com.lxj.xpopup.widget.VerticalRecyclerView;
import com.mikepenz.iconics.IconicsDrawable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import cc.niushuai.dididone.R;
import cc.niushuai.dididone.biz.BizGlobal;
import cc.niushuai.dididone.biz.entity.Project;
import cc.niushuai.dididone.util.GsonUtil;
import cc.niushuai.dididone.util.XLog;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
public class ProjectPopupView extends BottomPopupView {
@ -33,14 +41,14 @@ public class ProjectPopupView extends BottomPopupView { @@ -33,14 +41,14 @@ public class ProjectPopupView extends BottomPopupView {
private List<Project> data;
private EasyAdapter<Project> commonAdapter;
private Consumer<Project> callback;
private BiConsumer<Project, Map<String, String>> callback;
public ProjectPopupView(@NonNull Context context) {
super(context);
}
public ProjectPopupView(@NonNull Context context, Consumer<Project> callback) {
public ProjectPopupView(@NonNull Context context, BiConsumer<Project, Map<String, String>> callback) {
super(context);
this.callback = callback;
}
@ -58,9 +66,23 @@ public class ProjectPopupView extends BottomPopupView { @@ -58,9 +66,23 @@ public class ProjectPopupView extends BottomPopupView {
// 构建data
data = CollUtil.list(false, BizGlobal.getAvailableProjectMap().values());
// data.sort(Comparator.comparing(Project::getCreateDate));
data.sort((e1, e2) -> e2.getCreateDate().compareTo(e1.getCreateDate()));
// data.sort((e1, e2) -> e2.getCreateDate().compareTo(e1.getCreateDate()));
int projectCount = data.size();
Map<String, Integer> countMap = new HashMap<>();
for (Project item : data) {
Integer val = countMap.getOrDefault(item.getName(), 0);
countMap.put(item.getName(), val + 1);
}
XLog.d("构建出打卡项目: " + GsonUtil.toJson(countMap));
// 排序
data.sort((e1, e2) -> {
int diff = countMap.getOrDefault(e2.getName(), 0) - countMap.getOrDefault(e1.getName(), 0);
if (diff != 0) {
return diff;
}
return e2.getCreateDate().compareTo(e1.getCreateDate());
});
if (data.isEmpty()) {
Project e = new Project();
@ -68,10 +90,9 @@ public class ProjectPopupView extends BottomPopupView { @@ -68,10 +90,9 @@ public class ProjectPopupView extends BottomPopupView {
e.setIcon(BizGlobal.EMPTY_PROJECT_TIPS_ICON);
e.setIconColor(Color.RED);
data.add(e);
projectCount = 0;
}
((TextView) findViewById(R.id.ppv_title)).setText(StrUtil.format("全部{}条打卡项", projectCount));
((TextView) findViewById(R.id.ppv_title)).setText(StrUtil.format("全部{}条打卡项", data.size()));
commonAdapter = new EasyAdapter<Project>(data, R.layout.project_popup_view_item) {
@Override
protected void bind(@NonNull ViewHolder holder, @NonNull Project item, final int position) {
@ -90,17 +111,32 @@ public class ProjectPopupView extends BottomPopupView { @@ -90,17 +111,32 @@ public class ProjectPopupView extends BottomPopupView {
TextView descView = holder.getView(R.id.ppv_item_desc);
String count = BizGlobal.CACHE_PROJECT_COUNT.getOrDefault(project.getId(), 0).toString();
descView.setText(StrUtil.format("累计打卡{}次", count));
Integer todayCount = BizGlobal.CACHE_PROJECT_TODAY_COUNT.getOrDefault(project.getId(), 0);
descView.setText(StrUtil.format("今日打卡{}次, 累计打卡{}次", todayCount, count));
}
};
commonAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
@Override
public void onItemClick(@NonNull View view, @NonNull RecyclerView.ViewHolder viewHolder, int position) {
// 打卡 - 先显示时间和备注弹窗
Project selectedProject = data.get(position);
new XPopup.Builder(getContext())
.asCustom(new TimeNotePopupView(getContext(), (selectedTime, note) -> {
// 处理选择的时间和输入的备注(例如保存到数据库)
// 示例: saveCheckInInfo(selectedProject, selectedTime, note);
// 执行原回调
Map<String, String> map = new HashMap<>();
map.put("time", DateUtil.date(selectedTime).toString(DatePattern.NORM_DATETIME_FORMAT));
map.put("note", note);
callback.accept(selectedProject, map);
dismiss();
}))
.show();
// 打卡
callback.accept(data.get(position));
dismiss();
// callback.accept(data.get(position));
// dismiss();
}
@Override

64
app/src/main/java/cc/niushuai/dididone/ui/component/TimeNotePopupView.java

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
package cc.niushuai.dididone.ui.component;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TimePicker;
import androidx.annotation.NonNull;
import com.lxj.xpopup.core.CenterPopupView;
import cc.niushuai.dididone.R;
import java.util.Calendar;
public class TimeNotePopupView extends CenterPopupView {
private TimePicker timePicker;
private EditText etNote;
private Button btnConfirm, btnCancel;
private TimeNoteCallback callback;
// 回调接口传递选择的时间和备注
public interface TimeNoteCallback {
void onConfirm(long selectedTime, String note);
}
public TimeNotePopupView(@NonNull Context context, TimeNoteCallback callback) {
super(context);
this.callback = callback;
}
@Override
protected int getImplLayoutId() {
return R.layout.time_note_popup_view; // 需要创建对应的布局文件
}
@Override
protected void onCreate() {
super.onCreate();
timePicker = findViewById(R.id.time_picker);
etNote = findViewById(R.id.et_note);
btnConfirm = findViewById(R.id.btn_confirm);
btnCancel = findViewById(R.id.btn_cancel);
// 初始化时间选择器为当前时间
Calendar calendar = Calendar.getInstance();
timePicker.setHour(calendar.get(Calendar.HOUR_OF_DAY));
timePicker.setMinute(calendar.get(Calendar.MINUTE));
btnConfirm.setOnClickListener(v -> {
// 获取选择的时间(转换为毫秒时间戳)
Calendar selectedCalendar = Calendar.getInstance();
selectedCalendar.set(Calendar.HOUR_OF_DAY, timePicker.getHour());
selectedCalendar.set(Calendar.MINUTE, timePicker.getMinute());
long selectedTime = selectedCalendar.getTimeInMillis();
// 获取输入的备注
String note = etNote.getText().toString().trim();
// 调用回调传递结果
callback.onConfirm(selectedTime, note);
dismiss();
});
btnCancel.setOnClickListener(v -> dismiss());
}
}

56
app/src/main/res/layout/time_note_popup_view.xml

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp"
android:background="@color/white"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="选择打卡时间和备注"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="16dp"/>
<!-- 时间选择器 -->
<TimePicker
android:id="@+id/time_picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:timePickerMode="clock"/>
<!-- 备注输入框 -->
<EditText
android:id="@+id/et_note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入备注(可选)"
android:layout_marginTop="16dp"
android:inputType="textMultiLine"
/>
<!-- 按钮区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="20dp"
android:gravity="end">
<Button
android:id="@+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消"
android:layout_marginEnd="10dp"/>
<Button
android:id="@+id/btn_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>

40
app/src/main/res/values-land/strings.xml

@ -1,4 +1,42 @@ @@ -1,4 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">滴滴打卡</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="menu_home">Home</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_slideshow">Slideshow</string>
<string name="n_nav_header_title">...</string>
<string name="n_nav_header_subtitle">......</string>
<string name="n_menu_name_calendar">日历</string>
<string name="n_menu_name_statistic">统计</string>
<string name="n_menu_name_setting">设置</string>
<string name="s_set_target">目标</string>
<string name="s_set_app">App</string>
<string name="s_set_backup_restore">备份与恢复</string>
<string name="s_set_backup">备份</string>
<string name="s_set_restore">恢复</string>
<string name="s_set_icon">图标</string>
<string name="s_set_project">打卡项</string>
<string name="n_menu_name_icon">ICON</string>
<string name="icon_name_FontAwesome">FontAwesome</string>
<string name="n_menu_name_project">打卡项</string>
<string name="np_project_name">项目</string>
<string name="np_icon_name">图标</string>
<string name="np_color_name">颜色</string>
<string name="np_color_picker">点我选颜色</string>
<string name="np_button_back">返回</string>
<string name="np_button_confirm">保存</string>
<string name="cp_color_confirm">选择该颜色</string>
<string name="cancel">取消</string>
<string name="stat_header_list">列表视图</string>
<string name="stat_header_week">周视图</string>
<string name="stat_header_month">月视图</string>
<string name="stat_header_other">其他</string>
</resources>

40
app/src/main/res/values-night/strings.xml

@ -1,4 +1,42 @@ @@ -1,4 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">滴滴打卡</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="menu_home">Home</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_slideshow">Slideshow</string>
<string name="n_nav_header_title">...</string>
<string name="n_nav_header_subtitle">......</string>
<string name="n_menu_name_calendar">日历</string>
<string name="n_menu_name_statistic">统计</string>
<string name="n_menu_name_setting">设置</string>
<string name="s_set_target">目标</string>
<string name="s_set_app">App</string>
<string name="s_set_backup_restore">备份与恢复</string>
<string name="s_set_backup">备份</string>
<string name="s_set_restore">恢复</string>
<string name="s_set_icon">图标</string>
<string name="s_set_project">打卡项</string>
<string name="n_menu_name_icon">ICON</string>
<string name="icon_name_FontAwesome">FontAwesome</string>
<string name="n_menu_name_project">打卡项</string>
<string name="np_project_name">项目</string>
<string name="np_icon_name">图标</string>
<string name="np_color_name">颜色</string>
<string name="np_color_picker">点我选颜色</string>
<string name="np_button_back">返回</string>
<string name="np_button_confirm">保存</string>
<string name="cp_color_confirm">选择该颜色</string>
<string name="cancel">取消</string>
<string name="stat_header_list">列表视图</string>
<string name="stat_header_week">周视图</string>
<string name="stat_header_month">月视图</string>
<string name="stat_header_other">其他</string>
</resources>

40
app/src/main/res/values-w1240dp/strings.xml

@ -1,4 +1,42 @@ @@ -1,4 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">滴滴打卡</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="menu_home">Home</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_slideshow">Slideshow</string>
<string name="n_nav_header_title">...</string>
<string name="n_nav_header_subtitle">......</string>
<string name="n_menu_name_calendar">日历</string>
<string name="n_menu_name_statistic">统计</string>
<string name="n_menu_name_setting">设置</string>
<string name="s_set_target">目标</string>
<string name="s_set_app">App</string>
<string name="s_set_backup_restore">备份与恢复</string>
<string name="s_set_backup">备份</string>
<string name="s_set_restore">恢复</string>
<string name="s_set_icon">图标</string>
<string name="s_set_project">打卡项</string>
<string name="n_menu_name_icon">ICON</string>
<string name="icon_name_FontAwesome">FontAwesome</string>
<string name="n_menu_name_project">打卡项</string>
<string name="np_project_name">项目</string>
<string name="np_icon_name">图标</string>
<string name="np_color_name">颜色</string>
<string name="np_color_picker">点我选颜色</string>
<string name="np_button_back">返回</string>
<string name="np_button_confirm">保存</string>
<string name="cp_color_confirm">选择该颜色</string>
<string name="cancel">取消</string>
<string name="stat_header_list">列表视图</string>
<string name="stat_header_week">周视图</string>
<string name="stat_header_month">月视图</string>
<string name="stat_header_other">其他</string>
</resources>

40
app/src/main/res/values-w600dp/strings.xml

@ -1,4 +1,42 @@ @@ -1,4 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">滴滴打卡</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="menu_home">Home</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_slideshow">Slideshow</string>
<string name="n_nav_header_title">...</string>
<string name="n_nav_header_subtitle">......</string>
<string name="n_menu_name_calendar">日历</string>
<string name="n_menu_name_statistic">统计</string>
<string name="n_menu_name_setting">设置</string>
<string name="s_set_target">目标</string>
<string name="s_set_app">App</string>
<string name="s_set_backup_restore">备份与恢复</string>
<string name="s_set_backup">备份</string>
<string name="s_set_restore">恢复</string>
<string name="s_set_icon">图标</string>
<string name="s_set_project">打卡项</string>
<string name="n_menu_name_icon">ICON</string>
<string name="icon_name_FontAwesome">FontAwesome</string>
<string name="n_menu_name_project">打卡项</string>
<string name="np_project_name">项目</string>
<string name="np_icon_name">图标</string>
<string name="np_color_name">颜色</string>
<string name="np_color_picker">点我选颜色</string>
<string name="np_button_back">返回</string>
<string name="np_button_confirm">保存</string>
<string name="cp_color_confirm">选择该颜色</string>
<string name="cancel">取消</string>
<string name="stat_header_list">列表视图</string>
<string name="stat_header_week">周视图</string>
<string name="stat_header_month">月视图</string>
<string name="stat_header_other">其他</string>
</resources>
Loading…
Cancel
Save