mirror of
https://gitea.winboll.cc/ZhanGSKen/MyWinBoLL.git
synced 2026-08-15 05:52:09 +08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ad264c4aa | |||
| 81c2b781b6 | |||
| de63acc114 | |||
| 02c27c37f7 |
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Mon May 18 19:22:43 HKT 2026
|
||||
stageCount=3
|
||||
#Thu May 21 00:15:15 HKT 2026
|
||||
stageCount=4
|
||||
libraryProject=
|
||||
baseVersion=15.20
|
||||
publishVersion=15.20.2
|
||||
publishVersion=15.20.3
|
||||
buildCount=0
|
||||
baseBetaVersion=15.20.3
|
||||
baseBetaVersion=15.20.4
|
||||
|
||||
+211
-60
@@ -11,6 +11,7 @@ import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
@@ -39,25 +40,6 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
ArrayList<TaskSchedulerBean> mTaskList;
|
||||
TaskSchedulerAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.add(0, 1001, 0, "编辑任务内容");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == 1001) {
|
||||
View triggerView = item.getActionView();
|
||||
if (triggerView != null && triggerView.getTag() instanceof Integer) {
|
||||
int position = (Integer) triggerView.getTag();
|
||||
showEditTaskDialog(position);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
@@ -75,13 +57,22 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
|
||||
// 初始化任务列表
|
||||
mTaskList = new ArrayList<TaskSchedulerBean>();
|
||||
initSampleData();
|
||||
loadTaskData();
|
||||
|
||||
// 设置 RecyclerView
|
||||
RecyclerView recyclerView = findViewById(R.id.task_scheduler_recycler_view);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
|
||||
mAdapter = new TaskSchedulerAdapter(mTaskList);
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
|
||||
// 设置悬浮按钮点击事件
|
||||
Button fabAddTask = findViewById(R.id.fab_add_task);
|
||||
fabAddTask.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showAddTaskDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,6 +83,30 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件加载任务数据
|
||||
*/
|
||||
private void loadTaskData() {
|
||||
boolean loadSuccess = TaskSchedulerBean.loadBeanList(this, mTaskList, TaskSchedulerBean.class);
|
||||
if (loadSuccess) {
|
||||
LogUtils.i(TAG, "loadTaskData: 成功加载 " + mTaskList.size() + " 条任务数据");
|
||||
} else {
|
||||
LogUtils.i(TAG, "loadTaskData: 未找到已保存的任务数据,使用空列表");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存任务数据到文件
|
||||
*/
|
||||
private void saveTaskData() {
|
||||
boolean saveSuccess = TaskSchedulerBean.saveBeanList(this, mTaskList, TaskSchedulerBean.class);
|
||||
if (saveSuccess) {
|
||||
LogUtils.i(TAG, "saveTaskData: 成功保存 " + mTaskList.size() + " 条任务数据");
|
||||
} else {
|
||||
LogUtils.e(TAG, "saveTaskData: 任务数据保存失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间戳为年月日和小时
|
||||
* @param timestamp 时间戳
|
||||
@@ -129,13 +144,11 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
* 初始化示例数据
|
||||
*/
|
||||
private void initSampleData() {
|
||||
// 创建今天的日期作为基础
|
||||
java.util.Calendar calendar = java.util.Calendar.getInstance();
|
||||
calendar.set(java.util.Calendar.MINUTE, 0);
|
||||
calendar.set(java.util.Calendar.SECOND, 0);
|
||||
calendar.set(java.util.Calendar.MILLISECOND, 0);
|
||||
|
||||
// 设置不同的小时
|
||||
calendar.set(java.util.Calendar.HOUR_OF_DAY, 9);
|
||||
long time9 = calendar.getTimeInMillis();
|
||||
|
||||
@@ -220,7 +233,6 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(R.layout.dialog_task_edit);
|
||||
|
||||
// 初始化对话框控件
|
||||
final EditText etTaskName = dialog.findViewById(R.id.dialog_et_task_name);
|
||||
final EditText etCurrentScheduleTime = dialog.findViewById(R.id.dialog_et_start_time);
|
||||
final EditText etMonth = dialog.findViewById(R.id.dialog_et_month);
|
||||
@@ -230,12 +242,10 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
Button btnCancel = dialog.findViewById(R.id.dialog_btn_cancel);
|
||||
Button btnSave = dialog.findViewById(R.id.dialog_btn_save);
|
||||
|
||||
// 填充现有数据 - 将分钟转换为月、天、小时
|
||||
etTaskName.setText(task.getTaskName());
|
||||
etCurrentScheduleTime.setText(formatTimestamp(task.getCurrentScheduleTime()));
|
||||
etRemark.setText(task.getRemark());
|
||||
|
||||
// 反向转换:将分钟转换为月、天、小时
|
||||
int totalMinutes = task.getDurationMinutes();
|
||||
int totalHours = totalMinutes / MINUTES_PER_HOUR;
|
||||
int totalDays = totalHours / HOURS_PER_DAY;
|
||||
@@ -253,7 +263,6 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
etHour.setText(Integer.toString(hour));
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
btnCancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -261,11 +270,9 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
}
|
||||
});
|
||||
|
||||
// 保存按钮
|
||||
btnSave.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// 获取输入的数据
|
||||
String taskName = etTaskName.getText().toString().trim();
|
||||
String currentScheduleTime = etCurrentScheduleTime.getText().toString().trim();
|
||||
String monthStr = etMonth.getText().toString().trim();
|
||||
@@ -273,7 +280,6 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
String hourStr = etHour.getText().toString().trim();
|
||||
String remark = etRemark.getText().toString().trim();
|
||||
|
||||
// 验证输入
|
||||
if (taskName.isEmpty()) {
|
||||
etTaskName.setError("请输入任务名称");
|
||||
return;
|
||||
@@ -283,50 +289,185 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析时间字符串为时间戳
|
||||
long timestamp = parseTimeString(currentScheduleTime);
|
||||
if (timestamp == 0) {
|
||||
etCurrentScheduleTime.setError("时间格式不正确,请使用 yyyy-MM-dd HH 格式");
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析排档幅度 - 月、天、小时
|
||||
int month = 0;
|
||||
int day = 0;
|
||||
int hour = 0;
|
||||
|
||||
int month = 0, day = 0, hour = 0;
|
||||
try {
|
||||
if (!monthStr.isEmpty()) {
|
||||
month = Integer.parseInt(monthStr);
|
||||
}
|
||||
if (!dayStr.isEmpty()) {
|
||||
day = Integer.parseInt(dayStr);
|
||||
}
|
||||
if (!hourStr.isEmpty()) {
|
||||
hour = Integer.parseInt(hourStr);
|
||||
}
|
||||
if (!monthStr.isEmpty()) month = Integer.parseInt(monthStr);
|
||||
if (!dayStr.isEmpty()) day = Integer.parseInt(dayStr);
|
||||
if (!hourStr.isEmpty()) hour = Integer.parseInt(hourStr);
|
||||
} catch (NumberFormatException e) {
|
||||
LogUtils.e(TAG, "showEditTaskDialog: 数字解析错误", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// 转换为总分钟数
|
||||
int durationMinutes = convertToTotalMinutes(month, day, hour);
|
||||
|
||||
// 更新任务数据
|
||||
task.setTaskName(taskName);
|
||||
task.setCurrentScheduleTime(timestamp);
|
||||
task.setDurationMinutes(durationMinutes);
|
||||
task.setRemark(remark);
|
||||
|
||||
// 刷新列表
|
||||
mAdapter.notifyItemChanged(position);
|
||||
saveTaskData();
|
||||
LogUtils.i(TAG, "showEditTaskDialog: 任务 [" + taskName + "] 数据已更新,排档幅度=" + durationMinutes + "分钟");
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示添加任务对话框
|
||||
*/
|
||||
private void showAddTaskDialog() {
|
||||
final Dialog dialog = new Dialog(this);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(R.layout.dialog_task_edit);
|
||||
|
||||
final EditText etTaskName = dialog.findViewById(R.id.dialog_et_task_name);
|
||||
final EditText etCurrentScheduleTime = dialog.findViewById(R.id.dialog_et_start_time);
|
||||
final EditText etMonth = dialog.findViewById(R.id.dialog_et_month);
|
||||
final EditText etDay = dialog.findViewById(R.id.dialog_et_day);
|
||||
final EditText etHour = dialog.findViewById(R.id.dialog_et_hour);
|
||||
final EditText etRemark = dialog.findViewById(R.id.dialog_et_remark);
|
||||
Button btnCancel = dialog.findViewById(R.id.dialog_btn_cancel);
|
||||
Button btnSave = dialog.findViewById(R.id.dialog_btn_save);
|
||||
|
||||
// 设置默认时间为当前时间
|
||||
java.util.Calendar calendar = java.util.Calendar.getInstance();
|
||||
calendar.set(java.util.Calendar.MINUTE, 0);
|
||||
calendar.set(java.util.Calendar.SECOND, 0);
|
||||
calendar.set(java.util.Calendar.MILLISECOND, 0);
|
||||
etCurrentScheduleTime.setText(formatTimestamp(calendar.getTimeInMillis()));
|
||||
|
||||
btnCancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
btnSave.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String taskName = etTaskName.getText().toString().trim();
|
||||
String currentScheduleTime = etCurrentScheduleTime.getText().toString().trim();
|
||||
String monthStr = etMonth.getText().toString().trim();
|
||||
String dayStr = etDay.getText().toString().trim();
|
||||
String hourStr = etHour.getText().toString().trim();
|
||||
String remark = etRemark.getText().toString().trim();
|
||||
|
||||
if (taskName.isEmpty()) {
|
||||
etTaskName.setError("请输入任务名称");
|
||||
return;
|
||||
}
|
||||
if (currentScheduleTime.isEmpty()) {
|
||||
etCurrentScheduleTime.setError("请输入当前排档时间");
|
||||
return;
|
||||
}
|
||||
|
||||
long timestamp = parseTimeString(currentScheduleTime);
|
||||
if (timestamp == 0) {
|
||||
etCurrentScheduleTime.setError("时间格式不正确,请使用 yyyy-MM-dd HH 格式");
|
||||
return;
|
||||
}
|
||||
|
||||
int month = 0, day = 0, hour = 0;
|
||||
try {
|
||||
if (!monthStr.isEmpty()) month = Integer.parseInt(monthStr);
|
||||
if (!dayStr.isEmpty()) day = Integer.parseInt(dayStr);
|
||||
if (!hourStr.isEmpty()) hour = Integer.parseInt(hourStr);
|
||||
} catch (NumberFormatException e) {
|
||||
LogUtils.e(TAG, "showAddTaskDialog: 数字解析错误", e);
|
||||
return;
|
||||
}
|
||||
|
||||
int durationMinutes = convertToTotalMinutes(month, day, hour);
|
||||
TaskSchedulerBean newTask = new TaskSchedulerBean(taskName, remark, timestamp, durationMinutes);
|
||||
mTaskList.add(newTask);
|
||||
mAdapter.notifyItemInserted(mTaskList.size() - 1);
|
||||
saveTaskData();
|
||||
LogUtils.i(TAG, "showAddTaskDialog: 任务 [" + taskName + "] 已添加,排档幅度=" + durationMinutes + "分钟");
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示删除确认对话框
|
||||
* @param position 要删除的任务位置
|
||||
*/
|
||||
private void showDeleteConfirmDialog(final int position) {
|
||||
if (position < 0 || position >= mTaskList.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final TaskSchedulerBean task = mTaskList.get(position);
|
||||
final Dialog dialog = new Dialog(this);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(R.layout.dialog_task_edit);
|
||||
|
||||
// 修改对话框布局,只保留必要的按钮
|
||||
// 隐藏不需要的视图
|
||||
android.view.View etTaskName = dialog.findViewById(R.id.dialog_et_task_name);
|
||||
android.view.View etCurrentScheduleTime = dialog.findViewById(R.id.dialog_et_start_time);
|
||||
android.view.View etMonth = dialog.findViewById(R.id.dialog_et_month);
|
||||
android.view.View etDay = dialog.findViewById(R.id.dialog_et_day);
|
||||
android.view.View etHour = dialog.findViewById(R.id.dialog_et_hour);
|
||||
android.view.View etRemark = dialog.findViewById(R.id.dialog_et_remark);
|
||||
|
||||
if (etTaskName != null) etTaskName.setVisibility(View.GONE);
|
||||
if (etCurrentScheduleTime != null) etCurrentScheduleTime.setVisibility(View.GONE);
|
||||
if (etMonth != null) etMonth.setVisibility(View.GONE);
|
||||
if (etDay != null) etDay.setVisibility(View.GONE);
|
||||
if (etHour != null) etHour.setVisibility(View.GONE);
|
||||
if (etRemark != null) etRemark.setVisibility(View.GONE);
|
||||
|
||||
// 添加提示文本
|
||||
android.widget.TextView tvMessage = new android.widget.TextView(this);
|
||||
tvMessage.setText("确定要删除任务 \"" + task.getTaskName() + "\" 吗?");
|
||||
tvMessage.setPadding(40, 40, 40, 20);
|
||||
tvMessage.setTextSize(16);
|
||||
|
||||
android.view.ViewGroup rootView = dialog.findViewById(android.R.id.content);
|
||||
if (rootView != null) {
|
||||
android.view.ViewGroup.LayoutParams params = new android.view.ViewGroup.LayoutParams(
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
rootView.addView(tvMessage, 0, params);
|
||||
}
|
||||
|
||||
Button btnCancel = dialog.findViewById(R.id.dialog_btn_cancel);
|
||||
Button btnSave = dialog.findViewById(R.id.dialog_btn_save);
|
||||
|
||||
if (btnSave != null) {
|
||||
btnSave.setText("确定删除");
|
||||
}
|
||||
|
||||
btnCancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
btnSave.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String taskName = task.getTaskName();
|
||||
mTaskList.remove(position);
|
||||
mAdapter.notifyItemRemoved(position);
|
||||
saveTaskData();
|
||||
LogUtils.i(TAG, "showDeleteConfirmDialog: 任务 [" + taskName + "] 已删除");
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@@ -338,16 +479,11 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
if (position < 0 || position >= mTaskList.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TaskSchedulerBean currentTask = mTaskList.get(position);
|
||||
long currentTime = currentTask.getCurrentScheduleTime();
|
||||
int duration = currentTask.getDurationMinutes();
|
||||
|
||||
// 计算新的时间(时间戳加上分钟数)
|
||||
long newTime = currentTime + duration * 60 * 1000L;
|
||||
LogUtils.i(TAG, "performSchedule: 当前时间 " + formatTimestamp(currentTime) + " + " + duration + "分钟 = " + formatTimestamp(newTime));
|
||||
|
||||
// 更新下一个任务的时间(如果有)
|
||||
if (position + 1 < mTaskList.size()) {
|
||||
TaskSchedulerBean nextTask = mTaskList.get(position + 1);
|
||||
nextTask.setCurrentScheduleTime(newTime);
|
||||
@@ -379,22 +515,37 @@ public class TaskSchedulerActivity extends WinBoLLActivity {
|
||||
|
||||
viewHolder.mtvTaskName.setText(item.getTaskName());
|
||||
viewHolder.mtvCurrentScheduleTime.setText(formatTimestamp(item.getCurrentScheduleTime()));
|
||||
// 格式化显示排档幅度
|
||||
viewHolder.mtvDuration.setText(formatDurationToString(item.getDurationMinutes()));
|
||||
viewHolder.mtvRemark.setText(item.getRemark());
|
||||
|
||||
// mllMain长按存入当前条目独立位置Tag,互不干扰
|
||||
// 长按直接内置菜单,直接使用当前position
|
||||
viewHolder.mllMain.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
v.setTag(position);
|
||||
registerForContextMenu(v);
|
||||
openContextMenu(v);
|
||||
public boolean onLongClick(final View v) {
|
||||
// 使用PopupMenu替代ContextMenu
|
||||
PopupMenu popup = new PopupMenu(TaskSchedulerActivity.this, v);
|
||||
popup.getMenu().add("编辑任务内容");
|
||||
popup.getMenu().add("删除任务");
|
||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
String title = item.getTitle().toString();
|
||||
if ("编辑任务内容".equals(title)) {
|
||||
showEditTaskDialog(position);
|
||||
return true;
|
||||
} else if ("删除任务".equals(title)) {
|
||||
showDeleteConfirmDialog(position);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// 弹出菜单
|
||||
popup.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// 设置排档按钮点击事件
|
||||
viewHolder.mbtnSchedule.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/activityBackgroundColor">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/toolbarBackgroundColor"
|
||||
android:id="@+id/toolbar"/>
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:id="@+id/task_scheduler_recycler_view"/>
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/toolbarBackgroundColor"
|
||||
android:id="@+id/toolbar"/>
|
||||
|
||||
</LinearLayout>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:id="@+id/task_scheduler_recycler_view"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/fab_add_task"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
android:text="+"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
Reference in New Issue
Block a user