diff --git a/Notesmaster/.idea/deploymentTargetSelector.xml b/Notesmaster/.idea/deploymentTargetSelector.xml index b268ef3..fc8303f 100644 --- a/Notesmaster/.idea/deploymentTargetSelector.xml +++ b/Notesmaster/.idea/deploymentTargetSelector.xml @@ -5,6 +5,9 @@ + + \ No newline at end of file diff --git a/Notesmaster/.idea/misc.xml b/Notesmaster/.idea/misc.xml index 74dd639..b2c751a 100644 --- a/Notesmaster/.idea/misc.xml +++ b/Notesmaster/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java index 3a2050b..bc86b1d 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java @@ -24,12 +24,13 @@ import net.micode.notes.tool.GTaskStringUtils; import org.json.JSONException; import org.json.JSONObject; - +// 该类继承自Task类,用于处理与Google任务相关的元数据 public class MetaData extends Task { private final static String TAG = MetaData.class.getSimpleName(); private String mRelatedGid = null; + // 设置元数据信息,包括Google任务ID和元数据信息 public void setMeta(String gid, JSONObject metaInfo) { try { metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); @@ -40,15 +41,18 @@ public class MetaData extends Task { setName(GTaskStringUtils.META_NOTE_NAME); } + // 获取相关的Google任务ID public String getRelatedGid() { return mRelatedGid; } + // 判断该元数据是否值得保存 @Override public boolean isWorthSaving() { return getNotes() != null; } + // 通过远程JSON数据设置内容 @Override public void setContentByRemoteJSON(JSONObject js) { super.setContentByRemoteJSON(js); @@ -63,17 +67,20 @@ public class MetaData extends Task { } } + // 该方法不应用于MetaData类,调用时会抛出异常 @Override public void setContentByLocalJSON(JSONObject js) { // this function should not be called throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); } + // 该方法不应用于MetaData类,调用时会抛出异常 @Override public JSONObject getLocalJSONFromContent() { throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); } + // 该方法不应用于MetaData类,调用时会抛出异常 @Override public int getSyncAction(Cursor c) { throw new IllegalAccessError("MetaData:getSyncAction should not be called"); diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java index 85723be..0d9ca0b 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -41,98 +41,133 @@ import java.io.IOException; public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + // 存储当前提醒便签的ID private long mNoteId; + // 存储便签的摘要内容 private String mSnippet; + // 定义便签摘要显示的最大长度 private static final int SNIPPET_PREW_MAX_LEN = 60; + // 媒体播放器,用于播放闹钟提醒声音 MediaPlayer mPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // 不显示Activity的标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); final Window win = getWindow(); + // 添加窗口标志,使Activity在锁屏状态下也能显示 win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + // 如果屏幕当前处于关闭状态 if (!isScreenOn()) { + // 添加窗口标志,点亮屏幕并保持常亮,同时允许在屏幕开启时锁屏 win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); } + // 获取启动Activity的Intent Intent intent = getIntent(); try { + // 从Intent的Data中解析出便签ID mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); + // 通过ContentResolver获取便签的摘要内容 mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + // 如果摘要内容超过最大长度,进行截断并添加省略标记 mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) : mSnippet; } catch (IllegalArgumentException e) { + // 处理参数异常,打印堆栈信息并结束Activity e.printStackTrace(); return; } + // 创建媒体播放器实例 mPlayer = new MediaPlayer(); + // 检查便签是否存在且为普通便签类型 if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + // 显示提醒对话框 showActionDialog(); + // 播放闹钟提醒声音 playAlarmSound(); } else { + // 便签不存在或类型不符,结束Activity finish(); } } + // 检查屏幕是否处于开启状态 private boolean isScreenOn() { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); return pm.isScreenOn(); } + // 播放闹钟提醒声音 private void playAlarmSound() { + // 获取系统默认闹钟铃声的URI Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + // 获取设置中静默模式影响的音频流 int silentModeStreams = Settings.System.getInt(getContentResolver(), Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + // 根据静默模式设置音频流类型 if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { mPlayer.setAudioStreamType(silentModeStreams); } else { mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); } try { + // 设置音频数据源 mPlayer.setDataSource(this, url); + // 准备播放器 mPlayer.prepare(); + // 设置循环播放 mPlayer.setLooping(true); + // 开始播放 mPlayer.start(); } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block + // 参数异常处理 e.printStackTrace(); } catch (SecurityException e) { - // TODO Auto-generated catch block + // 安全异常处理 e.printStackTrace(); } catch (IllegalStateException e) { - // TODO Auto-generated catch block + // 状态异常处理 e.printStackTrace(); } catch (IOException e) { - // TODO Auto-generated catch block + // IO异常处理 e.printStackTrace(); } } + // 显示提醒操作对话框 private void showActionDialog() { AlertDialog.Builder dialog = new AlertDialog.Builder(this); + // 设置对话框标题为应用名称 dialog.setTitle(R.string.app_name); + // 设置对话框内容为便签摘要 dialog.setMessage(mSnippet); + // 添加"确定"按钮,并设置点击监听器 dialog.setPositiveButton(R.string.notealert_ok, this); + // 如果屏幕已开启,添加"进入"按钮 if (isScreenOn()) { dialog.setNegativeButton(R.string.notealert_enter, this); } + // 显示对话框并设置消失监听器 dialog.show().setOnDismissListener(this); } + // 对话框按钮点击事件处理 public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_NEGATIVE: + // 点击"进入"按钮,启动便签编辑Activity查看便签详情 Intent intent = new Intent(this, NoteEditActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.putExtra(Intent.EXTRA_UID, mNoteId); @@ -143,15 +178,22 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } + // 对话框消失时的回调处理 public void onDismiss(DialogInterface dialog) { + // 停止闹钟声音播放 stopAlarmSound(); + // 结束当前Activity finish(); } + // 停止闹钟声音并释放资源 private void stopAlarmSound() { if (mPlayer != null) { + // 停止播放 mPlayer.stop(); + // 释放媒体播放器资源 mPlayer.release(); + // 将引用置为null,便于垃圾回收 mPlayer = null; } } diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java index f221202..2d18852 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -28,38 +28,65 @@ import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; +/** + * 闹钟初始化广播接收器,用于在系统启动后重新设置所有待提醒的便签闹钟 + */ public class AlarmInitReceiver extends BroadcastReceiver { + // 查询闹钟提醒相关便签数据时使用的列投影 private static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.ALERTED_DATE + NoteColumns.ID, // 便签ID + NoteColumns.ALERTED_DATE // 提醒日期时间 }; - private static final int COLUMN_ID = 0; - private static final int COLUMN_ALERTED_DATE = 1; + // 投影列索引常量,便于代码引用 + private static final int COLUMN_ID = 0; // ID列索引 + private static final int COLUMN_ALERTED_DATE = 1; // 提醒日期列索引 + /** + * 接收广播时的处理逻辑 + * @param context 上下文对象 + * @param intent 接收到的Intent对象 + */ @Override public void onReceive(Context context, Intent intent) { + // 获取当前时间戳 long currentDate = System.currentTimeMillis(); + + // 查询所有提醒时间在当前时间之后的普通便签 Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, + // 查询条件:提醒时间大于当前时间且类型为普通便签 NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, - new String[] { String.valueOf(currentDate) }, - null); + new String[] { String.valueOf(currentDate) }, // 查询参数 + null); // 不指定排序 + // 处理查询结果 if (c != null) { if (c.moveToFirst()) { + // 遍历所有符合条件的便签 do { + // 获取便签的提醒时间 long alertDate = c.getLong(COLUMN_ALERTED_DATE); + + // 创建一个将在提醒时间触发的广播Intent Intent sender = new Intent(context, AlarmReceiver.class); + // 设置Intent的数据为便签的URI,以便在广播接收器中识别具体便签 sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + + // 创建一个PendingIntent,用于在指定时间触发广播 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + + // 获取系统闹钟服务 AlarmManager alermManager = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); + + // 设置一个精确的闹钟,当到达提醒时间时唤醒设备并触发广播 alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); } while (c.moveToNext()); } + // 关闭Cursor,释放资源 c.close(); } } -} +} \ No newline at end of file diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePicker.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePicker.java index 496b0cd..07e5983 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePicker.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -227,6 +227,17 @@ public class DateTimePicker extends FrameLayout { mIsEnabled = enabled; } + + + + + + + + + + + @Override public boolean isEnabled() { return mIsEnabled; diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java index 2c47ba4..bccdde9 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java @@ -31,60 +31,113 @@ import android.text.format.DateUtils; public class DateTimePickerDialog extends AlertDialog implements OnClickListener { + // 存储当前选择的日期和时间 private Calendar mDate = Calendar.getInstance(); + // 是否使用24小时制 private boolean mIs24HourView; + // 日期时间设置监听器,用于回调选择结果 private OnDateTimeSetListener mOnDateTimeSetListener; + // 自定义的日期时间选择器视图 private DateTimePicker mDateTimePicker; + /** + * 日期时间设置回调接口 + */ public interface OnDateTimeSetListener { + /** + * 当日期时间设置完成时调用 + * @param dialog 对话框实例 + * @param date 选择的日期时间(毫秒值) + */ void OnDateTimeSet(AlertDialog dialog, long date); } + /** + * 构造函数,创建日期时间选择对话框 + * @param context 上下文对象 + * @param date 初始显示的日期时间(毫秒值) + */ public DateTimePickerDialog(Context context, long date) { super(context); + // 创建自定义的日期时间选择器 mDateTimePicker = new DateTimePicker(context); + // 设置对话框的视图为日期时间选择器 setView(mDateTimePicker); + + // 设置日期时间变化监听器 mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { public void onDateTimeChanged(DateTimePicker view, int year, int month, - int dayOfMonth, int hourOfDay, int minute) { + int dayOfMonth, int hourOfDay, int minute) { + // 更新Calendar对象中的日期时间 mDate.set(Calendar.YEAR, year); mDate.set(Calendar.MONTH, month); mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); mDate.set(Calendar.MINUTE, minute); + // 更新对话框标题,显示当前选择的日期时间 updateTitle(mDate.getTimeInMillis()); } }); + + // 设置初始日期时间,并将秒数设为0 mDate.setTimeInMillis(date); mDate.set(Calendar.SECOND, 0); + + // 在日期时间选择器中显示初始日期时间 mDateTimePicker.setCurrentDate(mDate.getTimeInMillis()); + + // 设置对话框按钮 setButton(context.getString(R.string.datetime_dialog_ok), this); setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null); + + // 根据系统设置确定是否使用24小时制 set24HourView(DateFormat.is24HourFormat(this.getContext())); + // 更新对话框标题 updateTitle(mDate.getTimeInMillis()); } + /** + * 设置是否使用24小时制显示时间 + * @param is24HourView true表示使用24小时制,false表示使用12小时制 + */ public void set24HourView(boolean is24HourView) { mIs24HourView = is24HourView; } + /** + * 设置日期时间选择完成后的回调监听器 + * @param callBack 实现了OnDateTimeSetListener接口的回调对象 + */ public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { mOnDateTimeSetListener = callBack; } + /** + * 更新对话框标题,显示当前选择的日期时间 + * @param date 日期时间(毫秒值) + */ private void updateTitle(long date) { + // 设置日期时间显示格式标志 int flag = - DateUtils.FORMAT_SHOW_YEAR | - DateUtils.FORMAT_SHOW_DATE | - DateUtils.FORMAT_SHOW_TIME; + DateUtils.FORMAT_SHOW_YEAR | + DateUtils.FORMAT_SHOW_DATE | + DateUtils.FORMAT_SHOW_TIME; + // 根据是否使用24小时制添加相应的格式标志 flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; + + // 更新对话框标题 setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); } + /** + * 处理对话框按钮点击事件 + * @param arg0 对话框接口 + * @param arg1 按钮标识 + */ public void onClick(DialogInterface arg0, int arg1) { + // 当点击"确定"按钮时,调用回调函数通知日期时间已设置 if (mOnDateTimeSetListener != null) { mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); } } - } \ No newline at end of file diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/DropdownMenu.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/DropdownMenu.java index 613dc74..3f36130 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/DropdownMenu.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/DropdownMenu.java @@ -33,11 +33,16 @@ public class DropdownMenu { private Menu mMenu; public DropdownMenu(Context context, Button button, int menuId) { + // 保存按钮引用并设置下拉图标背景 mButton = button; mButton.setBackgroundResource(R.drawable.dropdown_icon); + + // 创建PopupMenu实例并加载菜单资源 mPopupMenu = new PopupMenu(context, mButton); mMenu = mPopupMenu.getMenu(); mPopupMenu.getMenuInflater().inflate(menuId, mMenu); + + // 设置按钮点击事件,点击时显示菜单 mButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mPopupMenu.show(); diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java index 96b77da..9836f92 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java @@ -29,52 +29,97 @@ import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; +/** + * 文件夹列表适配器,用于在ListView等控件中展示文件夹列表 + */ public class FoldersListAdapter extends CursorAdapter { + // 查询文件夹数据时使用的列投影,指定需要查询的数据库列 public static final String [] PROJECTION = { - NoteColumns.ID, - NoteColumns.SNIPPET + NoteColumns.ID, // 文件夹ID + NoteColumns.SNIPPET // 文件夹名称(摘要) }; - public static final int ID_COLUMN = 0; - public static final int NAME_COLUMN = 1; + // 列索引常量,方便后续代码引用 + public static final int ID_COLUMN = 0; // ID列的索引 + public static final int NAME_COLUMN = 1; // 名称列的索引 + /** + * 构造函数 + * @param context 上下文对象 + * @param c 包含文件夹数据的Cursor对象 + */ public FoldersListAdapter(Context context, Cursor c) { super(context, c); // TODO Auto-generated constructor stub } + /** + * 创建新的列表项视图 + * @param context 上下文对象 + * @param cursor 当前位置的数据游标 + * @param parent 父视图 + * @return 新创建的视图 + */ @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { + // 创建自定义的文件夹列表项视图 return new FolderListItem(context); } + /** + * 将数据绑定到已有的视图上 + * @param view 要绑定数据的视图 + * @param context 上下文对象 + * @param cursor 当前位置的数据游标 + */ @Override public void bindView(View view, Context context, Cursor cursor) { if (view instanceof FolderListItem) { + // 如果是根文件夹,则显示"上级文件夹"文本,否则显示实际文件夹名称 String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + // 将文件夹名称绑定到视图上 ((FolderListItem) view).bind(folderName); } } + /** + * 获取指定位置的文件夹名称 + * @param context 上下文对象 + * @param position 列表位置 + * @return 文件夹名称 + */ public String getFolderName(Context context, int position) { Cursor cursor = (Cursor) getItem(position); + // 如果是根文件夹,则显示"上级文件夹"文本,否则显示实际文件夹名称 return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); } + /** + * 自定义的文件夹列表项视图 + */ private class FolderListItem extends LinearLayout { - private TextView mName; + private TextView mName; // 文件夹名称显示文本视图 + /** + * 构造函数 + * @param context 上下文对象 + */ public FolderListItem(Context context) { super(context); + // 加载布局文件 inflate(context, R.layout.folder_list_item, this); + // 获取文件夹名称文本视图引用 mName = (TextView) findViewById(R.id.tv_folder_name); } + /** + * 将文件夹名称绑定到视图上 + * @param name 文件夹名称 + */ public void bind(String name) { mName.setText(name); } } - -} +} \ No newline at end of file diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java index 96a9ff8..b49eca0 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java @@ -430,7 +430,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, if (id == R.id.btn_set_bg_color) { mNoteBgColorSelector.setVisibility(View.VISIBLE); findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( - - View.VISIBLE); + View.VISIBLE); } else if (sBgSelectorBtnsMap.containsKey(id)) { findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.GONE); @@ -623,7 +623,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, if (mWorkingNote.getNoteId() > 0) { Intent intent = new Intent(this, AlarmReceiver.class); intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId())); - PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); + PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE); AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE)); showAlertHeader(); if(!set) { diff --git a/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java b/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java index 1221e80..2664d05 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java @@ -49,6 +49,7 @@ public class NotesListItem extends LinearLayout { } public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { + // 根据选择模式和笔记类型决定是否显示复选框 if (choiceMode && data.getType() == Notes.TYPE_NOTE) { mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(checked); @@ -56,36 +57,49 @@ public class NotesListItem extends LinearLayout { mCheckBox.setVisibility(View.GONE); } + // 保存笔记数据引用 mItemData = data; + + // 处理通话记录文件夹 if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { mCallName.setVisibility(View.GONE); mAlert.setVisibility(View.VISIBLE); mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + // 设置文件夹名称和包含的文件数量 mTitle.setText(context.getString(R.string.call_record_folder_name) + context.getString(R.string.format_folder_files_count, data.getNotesCount())); mAlert.setImageResource(R.drawable.call_record); - } else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) { + } + // 处理通话记录子项 + else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) { mCallName.setVisibility(View.VISIBLE); mCallName.setText(data.getCallName()); mTitle.setTextAppearance(context,R.style.TextAppearanceSecondaryItem); mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + // 根据是否有提醒设置提醒图标 if (data.hasAlert()) { mAlert.setImageResource(R.drawable.clock); mAlert.setVisibility(View.VISIBLE); } else { mAlert.setVisibility(View.GONE); } - } else { + } + // 处理普通笔记和文件夹 + else { mCallName.setVisibility(View.GONE); mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + // 处理文件夹 if (data.getType() == Notes.TYPE_FOLDER) { mTitle.setText(data.getSnippet() + context.getString(R.string.format_folder_files_count, - data.getNotesCount())); + data.getNotesCount())); mAlert.setVisibility(View.GONE); - } else { + } + // 处理普通笔记 + else { mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + // 根据是否有提醒设置提醒图标 if (data.hasAlert()) { mAlert.setImageResource(R.drawable.clock); mAlert.setVisibility(View.VISIBLE); @@ -94,11 +108,13 @@ public class NotesListItem extends LinearLayout { } } } + + // 设置修改时间,使用相对时间格式(如"1小时前") mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); + // 根据笔记状态设置背景 setBackground(data); } - private void setBackground(NoteItemData data) { int id = data.getBgColorId(); if (data.getType() == Notes.TYPE_NOTE) { diff --git a/Notesmaster/app/src/main/res/layout/note_edit.xml b/Notesmaster/app/src/main/res/layout/note_edit.xml index 10b2aa7..cf341e2 100644 --- a/Notesmaster/app/src/main/res/layout/note_edit.xml +++ b/Notesmaster/app/src/main/res/layout/note_edit.xml @@ -56,7 +56,7 @@ android:layout_marginRight="8dip" android:textAppearance="@style/TextAppearanceSecondaryItem" /> - \ No newline at end of file diff --git a/doc/小米便签阅读报告.md b/doc/小米便签阅读报告.md deleted file mode 100644 index e69de29..0000000 diff --git a/doc/开源代码质量分析报告.docx b/doc/开源代码质量分析报告.docx new file mode 100644 index 0000000..1790294 Binary files /dev/null and b/doc/开源代码质量分析报告.docx differ diff --git a/doc/开源软件维护方案及成果.docx b/doc/开源软件维护方案及成果.docx new file mode 100644 index 0000000..7b928e0 Binary files /dev/null and b/doc/开源软件维护方案及成果.docx differ diff --git a/doc/软件设计规格说明书.doc b/doc/软件设计规格说明书.doc new file mode 100644 index 0000000..20e1150 Binary files /dev/null and b/doc/软件设计规格说明书.doc differ diff --git a/doc/软件需求构思及描述.docx b/doc/软件需求构思及描述.docx new file mode 100644 index 0000000..4f0cb21 Binary files /dev/null and b/doc/软件需求构思及描述.docx differ diff --git a/doc/软件需求规格说明书.docx b/doc/软件需求规格说明书.docx new file mode 100644 index 0000000..de6ea3c Binary files /dev/null and b/doc/软件需求规格说明书.docx differ