曹馨语 1 month ago
parent 4332edee3d
commit 758794b7ef

@ -0,0 +1,175 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 包声明,表明该类属于 net.micode.notes.ui 包
package net.micode.notes.ui;
// 导入 Java 标准库中的 Calendar 类,用于处理日期和时间
import java.util.Calendar;
// 导入项目中的资源类 R
import net.micode.notes.R;
// 导入自定义的 DateTimePicker 类
import net.micode.notes.ui.DateTimePicker;
// 导入自定义的 DateTimePicker 类中的 OnDateTimeChangedListener 接口
import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener;
// 导入 Android 系统的 AlertDialog 类,用于创建对话框
import android.app.AlertDialog;
// 导入 Android 系统的 Context 类,用于获取应用程序的上下文信息
import android.content.Context;
// 导入 Android 系统的 DialogInterface 类,用于处理对话框的交互事件
import android.content.DialogInterface;
// 导入 DialogInterface 中的 OnClickListener 接口,用于处理点击事件
import android.content.DialogInterface.OnClickListener;
// 导入 Android 系统的 DateFormat 类,用于格式化日期和时间
import android.text.format.DateFormat;
// 导入 Android 系统的 DateUtils 类,用于处理日期和时间的工具类
import android.text.format.DateUtils;
/**
* DateTimePickerDialog AlertDialog
* OnDateTimeSetListener
*/
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
// 用于存储当前选择的日期和时间
private Calendar mDate = Calendar.getInstance();
// 标记是否使用 24 小时制显示时间
private boolean mIs24HourView;
// 日期和时间选择完成后的回调接口
private OnDateTimeSetListener mOnDateTimeSetListener;
// 自定义的日期和时间选择器视图
private DateTimePicker mDateTimePicker;
/**
* OnDateTimeSetListener OnDateTimeSet
*
*/
public interface OnDateTimeSetListener {
/**
*
* @param dialog
* @param date
*/
void OnDateTimeSet(AlertDialog dialog, long date);
}
/**
* DateTimePickerDialog
* @param context
* @param date
*/
public DateTimePickerDialog(Context context, long date) {
// 调用父类 AlertDialog 的构造函数
super(context);
// 创建自定义的 DateTimePicker 实例
mDateTimePicker = new DateTimePicker(context);
// 将 DateTimePicker 设置为对话框的视图
setView(mDateTimePicker);
// 为 DateTimePicker 设置日期和时间改变的监听器
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() {
/**
* mDate
* @param view DateTimePicker
* @param year
* @param month
* @param dayOfMonth
* @param hourOfDay
* @param minute
*/
public void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
// 更新 mDate 对象的年份
mDate.set(Calendar.YEAR, year);
// 更新 mDate 对象的月份
mDate.set(Calendar.MONTH, month);
// 更新 mDate 对象的日期
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
// 更新 mDate 对象的小时
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
// 更新 mDate 对象的分钟
mDate.set(Calendar.MINUTE, minute);
// 调用 updateTitle 方法更新对话框的标题
updateTitle(mDate.getTimeInMillis());
}
});
// 设置 mDate 对象的时间为传入的日期和时间
mDate.setTimeInMillis(date);
// 将秒数设置为 0
mDate.set(Calendar.SECOND, 0);
// 设置 DateTimePicker 的当前日期和时间
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 方法更新对话框的标题
updateTitle(mDate.getTimeInMillis());
}
/**
* 使 24
* @param is24HourView 使 24
*/
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;
// 根据是否使用 24 小时制添加相应的标志
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;
// 使用 DateUtils 格式化日期和时间,并设置为对话框的标题
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
}
/**
*
* OnDateTimeSet
* @param arg0 DialogInterface
* @param arg1
*/
public void onClick(DialogInterface arg0, int arg1) {
// 检查回调接口是否为空
if (mOnDateTimeSetListener != null) {
// 调用回调接口的 OnDateTimeSet 方法传递选择的日期和时间
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}
}
}

@ -0,0 +1,116 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 声明该类所在的包,表明该类属于 net.micode.notes.ui 模块
package net.micode.notes.ui;
// 导入 Android 上下文类,用于获取应用程序环境信息
import android.content.Context;
// 导入 Android 菜单类,用于创建和管理菜单
import android.view.Menu;
// 导入 Android 菜单项类,用于表示菜单中的每一项
import android.view.MenuItem;
// 导入 Android 视图类,是所有 UI 组件的基类
import android.view.View;
// 导入 Android 视图点击监听器接口,用于处理视图的点击事件
import android.view.View.OnClickListener;
// 导入 Android 按钮类,用于创建可点击的按钮
import android.widget.Button;
// 导入 Android 弹出菜单类,用于创建弹出式菜单
import android.widget.PopupMenu;
// 导入 Android 弹出菜单项点击监听器接口,用于处理弹出菜单项的点击事件
import android.widget.PopupMenu.OnMenuItemClickListener;
// 导入应用资源类,用于访问应用中的资源,如布局、字符串等
import net.micode.notes.R;
/**
* DropdownMenu
*/
public class DropdownMenu {
// 声明一个按钮对象,用于触发下拉菜单的显示
private Button mButton;
// 声明一个弹出菜单对象,用于显示下拉菜单的内容
private PopupMenu mPopupMenu;
// 声明一个菜单对象,用于管理弹出菜单中的菜单项
private Menu mMenu;
/**
*
*
* @param context
* @param button
* @param menuId ID
*/
public DropdownMenu(Context context, Button button, int menuId) {
// 将传入的按钮赋值给成员变量 mButton
mButton = button;
// 为按钮设置背景资源,使用下拉图标
mButton.setBackgroundResource(R.drawable.dropdown_icon);
// 创建一个弹出菜单对象,关联到传入的按钮上
mPopupMenu = new PopupMenu(context, mButton);
// 获取弹出菜单的菜单对象
mMenu = mPopupMenu.getMenu();
// 使用菜单布局资源 ID 来填充菜单内容
mPopupMenu.getMenuInflater().inflate(menuId, mMenu);
// 为按钮设置点击监听器
mButton.setOnClickListener(new OnClickListener() {
/**
*
*
* @param v
*/
public void onClick(View v) {
// 显示弹出菜单
mPopupMenu.show();
}
});
}
/**
*
*
* @param listener
*/
public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) {
// 检查弹出菜单对象是否不为空
if (mPopupMenu != null) {
// 为弹出菜单设置菜单项点击监听器
mPopupMenu.setOnMenuItemClickListener(listener);
}
}
/**
* ID
*
* @param id ID
* @return null
*/
public MenuItem findItem(int id) {
// 在菜单中查找指定 ID 的菜单项
return mMenu.findItem(id);
}
/**
*
*
* @param title
*/
public void setTitle(CharSequence title) {
// 设置按钮的文本内容为传入的标题
mButton.setText(title);
}
}

@ -0,0 +1,135 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
/**
* FoldersListAdapter CursorAdapter
* CursorAdapter Cursor AdapterView
*/
public class FoldersListAdapter extends CursorAdapter {
// 定义从数据库中查询所需的列,这里查询了笔记的 ID 和摘要
public static final String [] PROJECTION = {
NoteColumns.ID,
NoteColumns.SNIPPET
};
// 定义 PROJECTION 数组中 ID 列的索引
public static final int ID_COLUMN = 0;
// 定义 PROJECTION 数组中名称列的索引
public static final int NAME_COLUMN = 1;
/**
* FoldersListAdapter
* @param context
* @param c Cursor
*/
public FoldersListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}
/**
* Cursor
* Adapter
* @param context
* @param cursor Cursor
* @param parent
* @return
*/
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// 创建一个新的 FolderListItem 视图
return new FolderListItem(context);
}
/**
* Cursor
* Adapter
* @param view
* @param context
* @param cursor Cursor
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
// 检查视图是否为 FolderListItem 类型
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 的 bind 方法,将文件夹名称绑定到视图上
((FolderListItem) view).bind(folderName);
}
}
/**
*
* @param context
* @param position
* @return
*/
public String getFolderName(Context context, int position) {
// 获取指定位置的 Cursor 对象
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);
}
/**
* FolderListItem LinearLayout
* FoldersListAdapter
*/
private class FolderListItem extends LinearLayout {
// 用于显示文件夹名称的 TextView
private TextView mName;
/**
* FolderListItem
* @param context
*/
public FolderListItem(Context context) {
super(context);
// 加载布局文件 folder_list_item.xml 到当前视图
inflate(context, R.layout.folder_list_item, this);
// 查找布局文件中的 TextView 控件
mName = (TextView) findViewById(R.id.tv_folder_name);
}
/**
* TextView
* @param name
*/
public void bind(String name) {
// 设置 TextView 的文本为文件夹名称
mName.setText(name);
}
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,309 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.graphics.Rect;
import android.text.Layout;
import android.text.Selection;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.widget.EditText;
import net.micode.notes.R;
import java.util.HashMap;
import java.util.Map;
// 自定义的 EditText 类,继承自 EditText用于处理笔记编辑的特定逻辑
public class NoteEditText extends EditText {
// 日志标签,用于调试信息输出
private static final String TAG = "NoteEditText";
// 该 EditText 在集合中的索引
private int mIndex;
// 删除操作前的选择起始位置
private int mSelectionStartBeforeDelete;
// 定义支持的 URL 协议
private static final String SCHEME_TEL = "tel:" ;
private static final String SCHEME_HTTP = "http:" ;
private static final String SCHEME_EMAIL = "mailto:" ;
// 存储 URL 协议和对应的菜单资源 ID 的映射
private static final Map<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>();
static {
// 初始化映射,将不同协议与对应的菜单文本资源 ID 关联
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel);
sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web);
sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email);
}
/**
* NoteEditActivity EditText
*/
public interface OnTextViewChangeListener {
/**
* EditText
* @param index EditText
* @param text EditText
*/
void onEditTextDelete(int index, String text);
/**
* EditText EditText
* @param index EditText
* @param text
*/
void onEditTextEnter(int index, String text);
/**
*
* @param index EditText
* @param hasText EditText
*/
void onTextChange(int index, boolean hasText);
}
// 文本变化监听器
private OnTextViewChangeListener mOnTextViewChangeListener;
/**
* 使
* @param context
*/
public NoteEditText(Context context) {
super(context, null);
// 初始化索引为 0
mIndex = 0;
}
/**
* EditText
* @param index
*/
public void setIndex(int index) {
mIndex = index;
}
/**
*
* @param listener
*/
public void setOnTextViewChangeListener(OnTextViewChangeListener listener) {
mOnTextViewChangeListener = listener;
}
/**
* 使
* @param context
* @param attrs
*/
public NoteEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle);
}
/**
* 使
* @param context
* @param attrs
* @param defStyle
*/
public NoteEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
/**
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取触摸点的坐标
int x = (int) event.getX();
int y = (int) event.getY();
// 调整坐标,去除内边距并考虑滚动
x -= getTotalPaddingLeft();
y -= getTotalPaddingTop();
x += getScrollX();
y += getScrollY();
// 获取文本布局
Layout layout = getLayout();
// 根据垂直坐标获取行号
int line = layout.getLineForVertical(y);
// 根据行号和水平坐标获取字符偏移量
int off = layout.getOffsetForHorizontal(line, x);
// 设置文本选择位置
Selection.setSelection(getText(), off);
break;
}
return super.onTouchEvent(event);
}
/**
*
* @param keyCode
* @param event
* @return
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
// 如果设置了监听器,不处理回车键事件
if (mOnTextViewChangeListener != null) {
return false;
}
break;
case KeyEvent.KEYCODE_DEL:
// 记录删除操作前的选择起始位置
mSelectionStartBeforeDelete = getSelectionStart();
break;
default:
break;
}
return super.onKeyDown(keyCode, event);
}
/**
*
* @param keyCode
* @param event
* @return
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DEL:
// 如果设置了监听器
if (mOnTextViewChangeListener != null) {
// 当选择起始位置为 0 且索引不为 0 时,触发删除操作
if (0 == mSelectionStartBeforeDelete && mIndex != 0) {
mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString());
return true;
}
} else {
// 未设置监听器,输出日志
Log.d(TAG, "OnTextViewChangeListener was not seted");
}
break;
case KeyEvent.KEYCODE_ENTER:
// 如果设置了监听器
if (mOnTextViewChangeListener != null) {
// 获取选择起始位置
int selectionStart = getSelectionStart();
// 获取从选择起始位置到文本末尾的文本
String text = getText().subSequence(selectionStart, length()).toString();
// 设置文本为从开头到选择起始位置的内容
setText(getText().subSequence(0, selectionStart));
// 触发添加 EditText 操作
mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text);
} else {
// 未设置监听器,输出日志
Log.d(TAG, "OnTextViewChangeListener was not seted");
}
break;
default:
break;
}
return super.onKeyUp(keyCode, event);
}
/**
*
* @param focused
* @param direction
* @param previouslyFocusedRect
*/
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
// 如果设置了监听器
if (mOnTextViewChangeListener != null) {
// 失去焦点且文本为空时,触发文本变化事件
if (!focused && TextUtils.isEmpty(getText())) {
mOnTextViewChangeListener.onTextChange(mIndex, false);
} else {
// 其他情况,触发文本变化事件
mOnTextViewChangeListener.onTextChange(mIndex, true);
}
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
/**
*
* @param menu
*/
@Override
protected void onCreateContextMenu(ContextMenu menu) {
// 如果文本是 Spanned 类型
if (getText() instanceof Spanned) {
// 获取选择的起始和结束位置
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
// 计算选择范围的最小值和最大值
int min = Math.min(selStart, selEnd);
int max = Math.max(selStart, selEnd);
// 获取选择范围内的 URLSpan 数组
final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class);
// 如果只有一个 URLSpan
if (urls.length == 1) {
int defaultResId = 0;
// 遍历支持的协议
for(String schema: sSchemaActionResMap.keySet()) {
// 如果 URL 包含该协议
if(urls[0].getURL().indexOf(schema) >= 0) {
// 获取对应的菜单资源 ID
defaultResId = sSchemaActionResMap.get(schema);
break;
}
}
// 如果未找到匹配的协议,使用默认的菜单资源 ID
if (defaultResId == 0) {
defaultResId = R.string.note_link_other;
}
// 添加菜单项,并设置点击监听器
menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener(
new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
// 点击菜单项时,触发 URLSpan 的点击事件
urls[0].onClick(NoteEditText.this);
return true;
}
});
}
}
super.onCreateContextMenu(menu);
}
}

@ -0,0 +1,346 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 声明该类所在的包,属于笔记应用的用户界面相关包
package net.micode.notes.ui;
import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import net.micode.notes.data.Contact;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
/**
* NoteItemData
* ID
*
*/
public class NoteItemData {
// 定义从数据库查询笔记数据时需要的列名数组
static final String [] PROJECTION = new String [] {
NoteColumns.ID, // 笔记的唯一标识符
NoteColumns.ALERTED_DATE, // 笔记的提醒日期
NoteColumns.BG_COLOR_ID, // 笔记的背景颜色 ID
NoteColumns.CREATED_DATE, // 笔记的创建日期
NoteColumns.HAS_ATTACHMENT, // 笔记是否有附件
NoteColumns.MODIFIED_DATE, // 笔记的修改日期
NoteColumns.NOTES_COUNT, // 笔记数量
NoteColumns.PARENT_ID, // 笔记的父文件夹 ID
NoteColumns.SNIPPET, // 笔记的摘要
NoteColumns.TYPE, // 笔记的类型
NoteColumns.WIDGET_ID, // 笔记对应的小部件 ID
NoteColumns.WIDGET_TYPE, // 笔记对应的小部件类型
};
// 定义各列在 PROJECTION 数组中的索引位置,方便后续从 Cursor 中获取数据
private static final int ID_COLUMN = 0;
private static final int ALERTED_DATE_COLUMN = 1;
private static final int BG_COLOR_ID_COLUMN = 2;
private static final int CREATED_DATE_COLUMN = 3;
private static final int HAS_ATTACHMENT_COLUMN = 4;
private static final int MODIFIED_DATE_COLUMN = 5;
private static final int NOTES_COUNT_COLUMN = 6;
private static final int PARENT_ID_COLUMN = 7;
private static final int SNIPPET_COLUMN = 8;
private static final int TYPE_COLUMN = 9;
private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_TYPE_COLUMN = 11;
// 定义类的成员变量,用于存储从数据库中获取的笔记数据
private long mId; // 笔记的唯一标识符
private long mAlertDate; // 笔记的提醒日期
private int mBgColorId; // 笔记的背景颜色 ID
private long mCreatedDate; // 笔记的创建日期
private boolean mHasAttachment; // 笔记是否有附件
private long mModifiedDate; // 笔记的修改日期
private int mNotesCount; // 笔记数量
private long mParentId; // 笔记的父文件夹 ID
private String mSnippet; // 笔记的摘要
private int mType; // 笔记的类型
private int mWidgetId; // 笔记对应的小部件 ID
private int mWidgetType; // 笔记对应的小部件类型
private String mName; // 联系人姓名
private String mPhoneNumber; // 联系人电话号码
// 定义用于标记笔记在列表中位置的布尔变量
private boolean mIsLastItem; // 是否为列表中的最后一项
private boolean mIsFirstItem; // 是否为列表中的第一项
private boolean mIsOnlyOneItem; // 是否为列表中唯一的一项
private boolean mIsOneNoteFollowingFolder; // 是否为文件夹后的单条笔记
private boolean mIsMultiNotesFollowingFolder; // 是否为文件夹后的多条笔记
/**
* Cursor
* @param context ContentResolver
* @param cursor Cursor
*/
public NoteItemData(Context context, Cursor cursor) {
// 从 Cursor 中获取各列的数据并赋值给对应的成员变量
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false;
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
mParentId = cursor.getLong(PARENT_ID_COLUMN);
mSnippet = cursor.getString(SNIPPET_COLUMN);
// 去除摘要中的特定标签
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
NoteEditActivity.TAG_UNCHECKED, "");
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
mPhoneNumber = "";
// 如果笔记的父文件夹 ID 为通话记录文件夹的 ID
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
// 通过笔记 ID 获取通话号码
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
if (!TextUtils.isEmpty(mPhoneNumber)) {
// 根据电话号码获取联系人姓名
mName = Contact.getContact(context, mPhoneNumber);
if (mName == null) {
// 如果未找到联系人姓名,则使用电话号码作为姓名
mName = mPhoneNumber;
}
}
}
if (mName == null) {
mName = "";
}
// 检查笔记在列表中的位置信息
checkPostion(cursor);
}
/**
* Cursor
* @param cursor Cursor
*/
private void checkPostion(Cursor cursor) {
// 判断是否为列表中的最后一项
mIsLastItem = cursor.isLast() ? true : false;
// 判断是否为列表中的第一项
mIsFirstItem = cursor.isFirst() ? true : false;
// 判断是否为列表中唯一的一项
mIsOnlyOneItem = (cursor.getCount() == 1);
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
// 如果笔记类型为普通笔记且不是第一项
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
int position = cursor.getPosition();
if (cursor.moveToPrevious()) {
// 如果前一项是文件夹或系统类型
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {
if (cursor.getCount() > (position + 1)) {
// 如果后面还有其他笔记,则标记为文件夹后的多条笔记
mIsMultiNotesFollowingFolder = true;
} else {
// 否则标记为文件夹后的单条笔记
mIsOneNoteFollowingFolder = true;
}
}
// 将 Cursor 移动回原来的位置
if (!cursor.moveToNext()) {
throw new IllegalStateException("cursor move to previous but can't move back");
}
}
}
}
/**
*
* @return true false
*/
public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder;
}
/**
*
* @return true false
*/
public boolean isMultiFollowingFolder() {
return mIsMultiNotesFollowingFolder;
}
/**
*
* @return true false
*/
public boolean isLast() {
return mIsLastItem;
}
/**
*
* @return
*/
public String getCallName() {
return mName;
}
/**
*
* @return true false
*/
public boolean isFirst() {
return mIsFirstItem;
}
/**
*
* @return true false
*/
public boolean isSingle() {
return mIsOnlyOneItem;
}
/**
*
* @return ID
*/
public long getId() {
return mId;
}
/**
*
* @return
*/
public long getAlertDate() {
return mAlertDate;
}
/**
*
* @return
*/
public long getCreatedDate() {
return mCreatedDate;
}
/**
*
* @return true false
*/
public boolean hasAttachment() {
return mHasAttachment;
}
/**
*
* @return
*/
public long getModifiedDate() {
return mModifiedDate;
}
/**
* ID
* @return ID
*/
public int getBgColorId() {
return mBgColorId;
}
/**
* ID
* @return ID
*/
public long getParentId() {
return mParentId;
}
/**
*
* @return
*/
public int getNotesCount() {
return mNotesCount;
}
/**
* ID getParentId
* @return ID
*/
public long getFolderId () {
return mParentId;
}
/**
*
* @return
*/
public int getType() {
return mType;
}
/**
*
* @return
*/
public int getWidgetType() {
return mWidgetType;
}
/**
* ID
* @return ID
*/
public int getWidgetId() {
return mWidgetId;
}
/**
*
* @return
*/
public String getSnippet() {
return mSnippet;
}
/**
*
* @return true false
*/
public boolean hasAlert() {
return (mAlertDate > 0);
}
/**
*
* @return true false
*/
public boolean isCallRecord() {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
}
/**
* Cursor
* @param cursor Cursor
* @return
*/
public static int getNoteType(Cursor cursor) {
return cursor.getInt(TYPE_COLUMN);
}
}
Loading…
Cancel
Save