ui文件夹中所有代码已经修改完毕

src
zhangjinhan 8 months ago
parent a8775a1444
commit 2f7cda3615

@ -13,33 +13,40 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import java.util.Calendar; import java.util.Calendar;
import net.micode.notes.R; import net.micode.notes.R;
import net.micode.notes.ui.DateTimePicker; import net.micode.notes.ui.DateTimePicker;
import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener; import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.text.format.DateUtils; import android.text.format.DateUtils;
// 自定义的日期时间选择对话框继承自AlertDialog并实现了OnClickListener接口
public class DateTimePickerDialog extends AlertDialog implements OnClickListener { public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
// 存储当前选择的日期时间
private Calendar mDate = Calendar.getInstance(); private Calendar mDate = Calendar.getInstance();
// 是否使用24小时制
private boolean mIs24HourView; private boolean mIs24HourView;
// 回调接口,当日期时间设置完成后调用
private OnDateTimeSetListener mOnDateTimeSetListener; private OnDateTimeSetListener mOnDateTimeSetListener;
// 日期时间选择器控件
private DateTimePicker mDateTimePicker; private DateTimePicker mDateTimePicker;
// 定义日期时间设置完成后的回调接口
public interface OnDateTimeSetListener { public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date); void OnDateTimeSet(AlertDialog dialog, long date);
} }
// 构造函数,初始化对话框并设置初始日期时间
public DateTimePickerDialog(Context context, long date) { public DateTimePickerDialog(Context context, long date) {
super(context); super(context);
mDateTimePicker = new DateTimePicker(context); mDateTimePicker = new DateTimePicker(context);
@ -63,15 +70,18 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
set24HourView(DateFormat.is24HourFormat(this.getContext())); set24HourView(DateFormat.is24HourFormat(this.getContext()));
updateTitle(mDate.getTimeInMillis()); updateTitle(mDate.getTimeInMillis());
} }
// 设置是否使用24小时制显示时间
public void set24HourView(boolean is24HourView) { public void set24HourView(boolean is24HourView) {
mIs24HourView = is24HourView; mIs24HourView = is24HourView;
} }
// 设置日期时间选择完成后的回调监听器
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack; mOnDateTimeSetListener = callBack;
} }
// 更新对话框的标题以显示当前选择的日期时间
private void updateTitle(long date) { private void updateTitle(long date) {
int flag = int flag =
DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_YEAR |
@ -80,11 +90,12 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
} }
// 处理用户点击对话框按钮的事件,如果是确认按钮则调用回调监听器
public void onClick(DialogInterface arg0, int arg1) { public void onClick(DialogInterface arg0, int arg1) {
if (mOnDateTimeSetListener != null) { if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
} }
} }
} }

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.content.Context; import android.content.Context;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -24,14 +24,16 @@ import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.PopupMenu.OnMenuItemClickListener;
import net.micode.notes.R; import net.micode.notes.R;
// 下拉菜单类,用于在按钮点击时显示一个弹出菜单
public class DropdownMenu { public class DropdownMenu {
private Button mButton; private Button mButton; // 用于触发下拉菜单的按钮
private PopupMenu mPopupMenu; private PopupMenu mPopupMenu; // 弹出菜单对象
private Menu mMenu; private Menu mMenu; // 菜单对象
// 构造函数,初始化下拉菜单,设置按钮背景,并将菜单资源加载到弹出菜单中
public DropdownMenu(Context context, Button button, int menuId) { public DropdownMenu(Context context, Button button, int menuId) {
mButton = button; mButton = button;
mButton.setBackgroundResource(R.drawable.dropdown_icon); mButton.setBackgroundResource(R.drawable.dropdown_icon);
@ -44,18 +46,21 @@ public class DropdownMenu {
} }
}); });
} }
// 设置下拉菜单项点击监听器
public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) {
if (mPopupMenu != null) { if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener); mPopupMenu.setOnMenuItemClickListener(listener);
} }
} }
// 根据菜单项的ID查找菜单项
public MenuItem findItem(int id) { public MenuItem findItem(int id) {
return mMenu.findItem(id); return mMenu.findItem(id);
} }
// 设置按钮的标题
public void setTitle(CharSequence title) { public void setTitle(CharSequence title) {
mButton.setText(title); mButton.setText(title);
} }
} }

@ -28,26 +28,31 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
// 自定义的 CursorAdapter 用于显示文件夹列表
public class FoldersListAdapter extends CursorAdapter { public class FoldersListAdapter extends CursorAdapter {
// 定义查询文件夹时需要的列
public static final String [] PROJECTION = { public static final String [] PROJECTION = {
NoteColumns.ID, NoteColumns.ID,
NoteColumns.SNIPPET NoteColumns.SNIPPET
}; };
// 列索引常量
public static final int ID_COLUMN = 0; public static final int ID_COLUMN = 0;
public static final int NAME_COLUMN = 1; public static final int NAME_COLUMN = 1;
// 构造函数,初始化 FoldersListAdapter
public FoldersListAdapter(Context context, Cursor c) { public FoldersListAdapter(Context context, Cursor c) {
super(context, c); super(context, c);
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
// 创建一个新的视图项
@Override @Override
public View newView(Context context, Cursor cursor, ViewGroup parent) { public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new FolderListItem(context); return new FolderListItem(context);
} }
// 绑定数据到视图项
@Override @Override
public void bindView(View view, Context context, Cursor cursor) { public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof FolderListItem) { if (view instanceof FolderListItem) {
@ -57,24 +62,28 @@ public class FoldersListAdapter extends CursorAdapter {
} }
} }
// 根据位置获取文件夹名称
public String getFolderName(Context context, int position) { public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position); Cursor cursor = (Cursor) getItem(position);
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
} }
// 内部类,定义文件夹列表项的视图结构
private class FolderListItem extends LinearLayout { private class FolderListItem extends LinearLayout {
private TextView mName; private TextView mName;
// 构造函数,初始化 FolderListItem 视图
public FolderListItem(Context context) { public FolderListItem(Context context) {
super(context); super(context);
inflate(context, R.layout.folder_list_item, this); inflate(context, R.layout.folder_list_item, this);
mName = (TextView) findViewById(R.id.tv_folder_name); mName = (TextView) findViewById(R.id.tv_folder_name);
} }
// 绑定文件夹名称到视图
public void bind(String name) { public void bind(String name) {
mName.setText(name); mName.setText(name);
} }
} }
} }

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.app.Activity; import android.app.Activity;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -51,7 +51,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import net.micode.notes.R; import net.micode.notes.R;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote; import net.micode.notes.data.Notes.TextNote;
@ -64,26 +64,28 @@ import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener; import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x; import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x; import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
// 笔记编辑界面的Activity类
public class NoteEditActivity extends Activity implements OnClickListener, public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener { NoteSettingChangedListener, OnTextViewChangeListener {
// 用于存储笔记头部视图的ViewHolder类
private class HeadViewHolder { private class HeadViewHolder {
public TextView tvModified; public TextView tvModified;
public ImageView ivAlertIcon; public ImageView ivAlertIcon;
public TextView tvAlertDate; public TextView tvAlertDate;
public ImageView ibSetBgColor; public ImageView ibSetBgColor;
} }
// 背景色选择按钮和颜色ID的映射
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>(); private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static { static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW); sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@ -92,7 +94,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN); sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE); sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
} }
// 背景色选择后的显示标记和颜色ID的映射
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>(); private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
static { static {
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select); sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
@ -101,7 +104,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select); sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select); sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
} }
// 字体大小选择按钮和字体大小ID的映射
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>(); private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
static { static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE); sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
@ -109,7 +113,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM); sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM);
sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER); sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
} }
// 字体大小选择后的显示标记和字体大小ID的映射
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>(); private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<Integer, Integer>();
static { static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select); sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
@ -117,54 +122,52 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select); sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select); sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
} }
private static final String TAG = "NoteEditActivity"; private static final String TAG = "NoteEditActivity";
private HeadViewHolder mNoteHeaderHolder; private HeadViewHolder mNoteHeaderHolder;
private View mHeadViewPanel; private View mHeadViewPanel;
private View mNoteBgColorSelector; private View mNoteBgColorSelector;
private View mFontSizeSelector; private View mFontSizeSelector;
private EditText mNoteEditor; private EditText mNoteEditor;
private View mNoteEditorPanel; private View mNoteEditorPanel;
private WorkingNote mWorkingNote; private WorkingNote mWorkingNote;
private SharedPreferences mSharedPrefs; private SharedPreferences mSharedPrefs;
private int mFontSizeId; private int mFontSizeId;
private static final String PREFERENCE_FONT_SIZE = "pref_font_size"; private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
public static final String TAG_CHECKED = String.valueOf('\u221A'); public static final String TAG_CHECKED = String.valueOf('\u221A');
public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
private LinearLayout mEditTextList; private LinearLayout mEditTextList;
private String mUserQuery; private String mUserQuery;
private Pattern mPattern; private Pattern mPattern;
// 初始化Activity视图
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.setContentView(R.layout.note_edit); this.setContentView(R.layout.note_edit);
if (savedInstanceState == null && !initActivityState(getIntent())) { if (savedInstanceState == null && !initActivityState(getIntent())) {
finish(); finish();
return; return;
} }
initResources(); initResources();
} }
/** // 当Activity被系统杀死后恢复其状态
* Current activity may be killed when the memory is low. Once it is killed, for another time
* user load this activity, we should restore the former state
*/
@Override @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) { protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState);
@ -178,25 +181,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.d(TAG, "Restoring from killed activity"); Log.d(TAG, "Restoring from killed activity");
} }
} }
// 初始化Activity状态根据Intent决定加载笔记或创建新笔记
private boolean initActivityState(Intent intent) { private boolean initActivityState(Intent intent) {
/**
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
* then jump to the NotesListActivity
*/
mWorkingNote = null; mWorkingNote = null;
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) { if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0); long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
mUserQuery = ""; mUserQuery = "";
/**
* Starting from the searched result
*/
if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) { if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY)); noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY); mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
} }
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) { if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
Intent jump = new Intent(this, NotesListActivity.class); Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump); startActivity(jump);
@ -215,7 +212,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
} else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) { } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
// New note
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0); long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID, int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID); AppWidgetManager.INVALID_APPWIDGET_ID);
@ -223,8 +219,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Notes.TYPE_WIDGET_INVALIDE); Notes.TYPE_WIDGET_INVALIDE);
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
ResourceParser.getDefaultBgId(this)); ResourceParser.getDefaultBgId(this));
// Parse call-record note
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0); long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) { if (callDate != 0 && phoneNumber != null) {
@ -249,7 +244,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType, mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
bgResId); bgResId);
} }
getWindow().setSoftInputMode( getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
@ -261,13 +256,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mWorkingNote.setOnSettingStatusChangedListener(this); mWorkingNote.setOnSettingStatusChangedListener(this);
return true; return true;
} }
// Activity恢复时初始化笔记显示
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
initNoteScreen(); initNoteScreen();
} }
// 初始化笔记显示界面,包括背景颜色、字体大小、修改日期等
private void initNoteScreen() { private void initNoteScreen() {
mNoteEditor.setTextAppearance(this, TextAppearanceResources mNoteEditor.setTextAppearance(this, TextAppearanceResources
.getTexAppearanceResource(mFontSizeId)); .getTexAppearanceResource(mFontSizeId));
@ -282,19 +279,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this, mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR)); | DateUtils.FORMAT_SHOW_YEAR));
/**
* TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
* is not ready
*/
showAlertHeader(); showAlertHeader();
} }
// 显示或隐藏提醒头部信息
private void showAlertHeader() { private void showAlertHeader() {
if (mWorkingNote.hasClockAlert()) { if (mWorkingNote.hasClockAlert()) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
@ -311,28 +305,26 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE); mNoteHeaderHolder.ivAlertIcon.setVisibility(View.GONE);
}; };
} }
// 处理新的Intent可能需要重新加载笔记或创建新笔记
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
initActivityState(intent); initActivityState(intent);
} }
// 保存Activity状态在系统需要恢复Activity时使用
@Override @Override
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
/**
* For new note without note id, we should firstly save it to
* generate a id. If the editing note is not worth saving, there
* is no id which is equivalent to create new note
*/
if (!mWorkingNote.existInDatabase()) { if (!mWorkingNote.existInDatabase()) {
saveNote(); saveNote();
} }
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId()); outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState"); Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
} }
// 处理触摸事件,用于隐藏颜色和字体大小选择面板
@Override @Override
public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
@ -340,7 +332,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteBgColorSelector.setVisibility(View.GONE); mNoteBgColorSelector.setVisibility(View.GONE);
return true; return true;
} }
if (mFontSizeSelector.getVisibility() == View.VISIBLE if (mFontSizeSelector.getVisibility() == View.VISIBLE
&& !inRangeOfView(mFontSizeSelector, ev)) { && !inRangeOfView(mFontSizeSelector, ev)) {
mFontSizeSelector.setVisibility(View.GONE); mFontSizeSelector.setVisibility(View.GONE);
@ -348,7 +340,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return super.dispatchTouchEvent(ev); return super.dispatchTouchEvent(ev);
} }
// 判断触摸事件是否发生在指定视图内
private boolean inRangeOfView(View view, MotionEvent ev) { private boolean inRangeOfView(View view, MotionEvent ev) {
int []location = new int[2]; int []location = new int[2];
view.getLocationOnScreen(location); view.getLocationOnScreen(location);
@ -362,7 +355,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return true; return true;
} }
// 初始化视图资源
private void initResources() { private void initResources() {
mHeadViewPanel = findViewById(R.id.note_title); mHeadViewPanel = findViewById(R.id.note_title);
mNoteHeaderHolder = new HeadViewHolder(); mNoteHeaderHolder = new HeadViewHolder();
@ -378,7 +372,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
ImageView iv = (ImageView) findViewById(id); ImageView iv = (ImageView) findViewById(id);
iv.setOnClickListener(this); iv.setOnClickListener(this);
} }
mFontSizeSelector = findViewById(R.id.font_size_selector); mFontSizeSelector = findViewById(R.id.font_size_selector);
for (int id : sFontSizeBtnsMap.keySet()) { for (int id : sFontSizeBtnsMap.keySet()) {
View view = findViewById(id); View view = findViewById(id);
@ -386,17 +380,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}; };
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE); mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
* HACKME: Fix bug of store the resource id in shared preference.
* The id may larger than the length of resources, in this case,
* return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE}
*/
if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) { if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE; mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
} }
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list); mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
} }
// 暂停Activity时保存笔记并清理设置状态
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
@ -405,7 +395,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
clearSettingState(); clearSettingState();
} }
// 更新桌面小部件显示
private void updateWidget() { private void updateWidget() {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) { if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
@ -416,21 +407,22 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.e(TAG, "Unspported widget type"); Log.e(TAG, "Unspported widget type");
return; return;
} }
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
mWorkingNote.getWidgetId() mWorkingNote.getWidgetId()
}); });
sendBroadcast(intent); sendBroadcast(intent);
setResult(RESULT_OK, intent); setResult(RESULT_OK, intent);
} }
// 处理视图点击事件,包括颜色和字体大小选择
public void onClick(View v) { public void onClick(View v) {
int id = v.getId(); int id = v.getId();
if (id == R.id.btn_set_bg_color) { if (id == R.id.btn_set_bg_color) {
mNoteBgColorSelector.setVisibility(View.VISIBLE); mNoteBgColorSelector.setVisibility(View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
- View.VISIBLE); View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) { } else if (sBgSelectorBtnsMap.containsKey(id)) {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE); View.GONE);
@ -451,17 +443,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mFontSizeSelector.setVisibility(View.GONE); mFontSizeSelector.setVisibility(View.GONE);
} }
} }
// 处理返回键事件,如果设置面板可见则隐藏,否则保存笔记后返回
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if(clearSettingState()) { if(clearSettingState()) {
return; return;
} }
saveNote(); saveNote();
super.onBackPressed(); super.onBackPressed();
} }
// 清理设置面板状态
private boolean clearSettingState() { private boolean clearSettingState() {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) { if (mNoteBgColorSelector.getVisibility() == View.VISIBLE) {
mNoteBgColorSelector.setVisibility(View.GONE); mNoteBgColorSelector.setVisibility(View.GONE);
@ -472,14 +466,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return false; return false;
} }
// 处理笔记背景颜色变化事件
public void onBackgroundColorChanged() { public void onBackgroundColorChanged() {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.VISIBLE); View.VISIBLE);
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
} }
// 准备选项菜单,根据笔记状态动态更新菜单项
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
if (isFinishing()) { if (isFinishing()) {
@ -504,7 +500,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return true; return true;
} }
// 处理选项菜单项点击事件
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
@ -552,7 +549,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return true; return true;
} }
// 设置提醒时间
private void setReminder() { private void setReminder() {
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis()); DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
d.setOnDateTimeSetListener(new OnDateTimeSetListener() { d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
@ -562,30 +560,27 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}); });
d.show(); d.show();
} }
/** // 分享笔记内容到支持ACTION_SEND的其他应用
* Share note to apps that support {@link Intent#ACTION_SEND} action
* and {@text/plain} type
*/
private void sendTo(Context context, String info) { private void sendTo(Context context, String info) {
Intent intent = new Intent(Intent.ACTION_SEND); Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, info); intent.putExtra(Intent.EXTRA_TEXT, info);
intent.setType("text/plain"); intent.setType("text/plain");
context.startActivity(intent); context.startActivity(intent);
} }
// 创建新笔记,跳转到新笔记编辑界面
private void createNewNote() { private void createNewNote() {
// Firstly, save current editing notes
saveNote(); saveNote();
// For safety, start a new NoteEditActivity
finish(); finish();
Intent intent = new Intent(this, NoteEditActivity.class); Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT); intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId()); intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mWorkingNote.getFolderId());
startActivity(intent); startActivity(intent);
} }
// 删除当前笔记
private void deleteCurrentNote() { private void deleteCurrentNote() {
if (mWorkingNote.existInDatabase()) { if (mWorkingNote.existInDatabase()) {
HashSet<Long> ids = new HashSet<Long>(); HashSet<Long> ids = new HashSet<Long>();
@ -607,16 +602,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
mWorkingNote.markDeleted(true); mWorkingNote.markDeleted(true);
} }
// 判断是否处于同步模式
private boolean isSyncMode() { private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
} }
// 处理时钟提醒变化事件,设置或取消提醒
public void onClockAlertChanged(long date, boolean set) { public void onClockAlertChanged(long date, boolean set) {
/**
* User could set clock to an unsaved note, so before setting the
* alert clock, we should save the note first
*/
if (!mWorkingNote.existInDatabase()) { if (!mWorkingNote.existInDatabase()) {
saveNote(); saveNote();
} }
@ -632,31 +625,28 @@ public class NoteEditActivity extends Activity implements OnClickListener,
alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent); alarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
} }
} else { } else {
/**
* There is the condition that user has input nothing (the note is
* not worthy saving), we have no note id, remind the user that he
* should input something
*/
Log.e(TAG, "Clock alert setting error"); Log.e(TAG, "Clock alert setting error");
showToast(R.string.error_note_empty_for_clock); showToast(R.string.error_note_empty_for_clock);
} }
} }
// 处理小部件变化事件,更新小部件显示
public void onWidgetChanged() { public void onWidgetChanged() {
updateWidget(); updateWidget();
} }
// 处理EditText删除事件调整列表项索引
public void onEditTextDelete(int index, String text) { public void onEditTextDelete(int index, String text) {
int childCount = mEditTextList.getChildCount(); int childCount = mEditTextList.getChildCount();
if (childCount == 1) { if (childCount == 1) {
return; return;
} }
for (int i = index + 1; i < childCount; i++) { for (int i = index + 1; i < childCount; i++) {
((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text)) ((NoteEditText) mEditTextList.getChildAt(i).findViewById(R.id.et_edit_text))
.setIndex(i - 1); .setIndex(i - 1);
} }
mEditTextList.removeViewAt(index); mEditTextList.removeViewAt(index);
NoteEditText edit = null; NoteEditText edit = null;
if(index == 0) { if(index == 0) {
@ -671,15 +661,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
edit.requestFocus(); edit.requestFocus();
edit.setSelection(length); edit.setSelection(length);
} }
// 处理EditText输入事件添加新列表项
public void onEditTextEnter(int index, String text) { public void onEditTextEnter(int index, String text) {
/**
* Should not happen, check for debug
*/
if(index > mEditTextList.getChildCount()) { if(index > mEditTextList.getChildCount()) {
Log.e(TAG, "Index out of mEditTextList boundrary, should not happen"); Log.e(TAG, "Index out of mEditTextList boundrary, should not happen");
} }
View view = getListItem(text, index); View view = getListItem(text, index);
mEditTextList.addView(view, index); mEditTextList.addView(view, index);
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
@ -690,7 +678,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
.setIndex(i); .setIndex(i);
} }
} }
// 切换到列表模式,根据笔记内容生成列表项
private void switchToListMode(String text) { private void switchToListMode(String text) {
mEditTextList.removeAllViews(); mEditTextList.removeAllViews();
String[] items = text.split("\n"); String[] items = text.split("\n");
@ -703,11 +692,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
mEditTextList.addView(getListItem("", index)); mEditTextList.addView(getListItem("", index));
mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus(); mEditTextList.getChildAt(index).findViewById(R.id.et_edit_text).requestFocus();
mNoteEditor.setVisibility(View.GONE); mNoteEditor.setVisibility(View.GONE);
mEditTextList.setVisibility(View.VISIBLE); mEditTextList.setVisibility(View.VISIBLE);
} }
// 获取高亮查询结果,用于显示搜索关键词
private Spannable getHighlightQueryResult(String fullText, String userQuery) { private Spannable getHighlightQueryResult(String fullText, String userQuery) {
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText); SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
if (!TextUtils.isEmpty(userQuery)) { if (!TextUtils.isEmpty(userQuery)) {
@ -724,7 +714,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return spannable; return spannable;
} }
// 生成一个新的列表项视图
private View getListItem(String item, int index) { private View getListItem(String item, int index) {
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
@ -739,7 +730,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
} }
}); });
if (item.startsWith(TAG_CHECKED)) { if (item.startsWith(TAG_CHECKED)) {
cb.setChecked(true); cb.setChecked(true);
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
@ -749,13 +740,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
item = item.substring(TAG_UNCHECKED.length(), item.length()).trim(); item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
} }
edit.setOnTextViewChangeListener(this); edit.setOnTextViewChangeListener(this);
edit.setIndex(index); edit.setIndex(index);
edit.setText(getHighlightQueryResult(item, mUserQuery)); edit.setText(getHighlightQueryResult(item, mUserQuery));
return view; return view;
} }
// 处理EditText文本变化事件显示或隐藏复选框
public void onTextChange(int index, boolean hasText) { public void onTextChange(int index, boolean hasText) {
if (index >= mEditTextList.getChildCount()) { if (index >= mEditTextList.getChildCount()) {
Log.e(TAG, "Wrong index, should not happen"); Log.e(TAG, "Wrong index, should not happen");
@ -767,7 +759,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE); mEditTextList.getChildAt(index).findViewById(R.id.cb_edit_item).setVisibility(View.GONE);
} }
} }
// 处理笔记模式变化事件,从普通模式切换到列表模式或反之
public void onCheckListModeChanged(int oldMode, int newMode) { public void onCheckListModeChanged(int oldMode, int newMode) {
if (newMode == TextNote.MODE_CHECK_LIST) { if (newMode == TextNote.MODE_CHECK_LIST) {
switchToListMode(mNoteEditor.getText().toString()); switchToListMode(mNoteEditor.getText().toString());
@ -781,7 +774,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setVisibility(View.VISIBLE); mNoteEditor.setVisibility(View.VISIBLE);
} }
} }
// 获取正在编辑的文本内容,根据列表模式添加标签
private boolean getWorkingText() { private boolean getWorkingText() {
boolean hasChecked = false; boolean hasChecked = false;
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
@ -804,33 +798,23 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return hasChecked; return hasChecked;
} }
// 保存笔记内容到数据库
private boolean saveNote() { private boolean saveNote() {
getWorkingText(); getWorkingText();
boolean saved = mWorkingNote.saveNote(); boolean saved = mWorkingNote.saveNote();
if (saved) { if (saved) {
/**
* There are two modes from List view to edit view, open one note,
* create/edit a node. Opening node requires to the original
* position in the list when back from edit view, while creating a
* new node requires to the top of the list. This code
* {@link #RESULT_OK} is used to identify the create/edit state
*/
setResult(RESULT_OK); setResult(RESULT_OK);
} }
return saved; return saved;
} }
// 将笔记快捷方式添加到桌面
private void sendToDesktop() { private void sendToDesktop() {
/**
* Before send message to home, we should make sure that current
* editing note is exists in databases. So, for new note, firstly
* save it
*/
if (!mWorkingNote.existInDatabase()) { if (!mWorkingNote.existInDatabase()) {
saveNote(); saveNote();
} }
if (mWorkingNote.getNoteId() > 0) { if (mWorkingNote.getNoteId() > 0) {
Intent sender = new Intent(); Intent sender = new Intent();
Intent shortcutIntent = new Intent(this, NoteEditActivity.class); Intent shortcutIntent = new Intent(this, NoteEditActivity.class);
@ -846,28 +830,26 @@ public class NoteEditActivity extends Activity implements OnClickListener,
showToast(R.string.info_note_enter_desktop); showToast(R.string.info_note_enter_desktop);
sendBroadcast(sender); sendBroadcast(sender);
} else { } else {
/**
* There is the condition that user has input nothing (the note is
* not worthy saving), we have no note id, remind the user that he
* should input something
*/
Log.e(TAG, "Send to desktop error"); Log.e(TAG, "Send to desktop error");
showToast(R.string.error_note_empty_for_send_to_desktop); showToast(R.string.error_note_empty_for_send_to_desktop);
} }
} }
// 生成桌面快捷方式的标题,截取笔记内容的一部分作为标题
private String makeShortcutIconTitle(String content) { private String makeShortcutIconTitle(String content) {
content = content.replace(TAG_CHECKED, ""); content = content.replace(TAG_CHECKED, "");
content = content.replace(TAG_UNCHECKED, ""); content = content.replace(TAG_UNCHECKED, "");
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0, return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
SHORTCUT_ICON_TITLE_MAX_LEN) : content; SHORTCUT_ICON_TITLE_MAX_LEN) : content;
} }
// 显示短Toast消息
private void showToast(int resId) { private void showToast(int resId) {
showToast(resId, Toast.LENGTH_SHORT); showToast(resId, Toast.LENGTH_SHORT);
} }
// 显示指定持续时间的Toast消息
private void showToast(int resId, int duration) { private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show(); Toast.makeText(this, resId, duration).show();
} }
} }

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.text.Layout; import android.text.Layout;
@ -31,28 +31,29 @@ import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener; import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.widget.EditText; import android.widget.EditText;
import net.micode.notes.R; import net.micode.notes.R;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
// 自定义的EditText用于笔记应用中支持删除、添加文本事件监听
public class NoteEditText extends EditText { public class NoteEditText extends EditText {
private static final String TAG = "NoteEditText"; private static final String TAG = "NoteEditText";
private int mIndex; private int mIndex;
private int mSelectionStartBeforeDelete; private int mSelectionStartBeforeDelete;
private static final String SCHEME_TEL = "tel:" ; private static final String SCHEME_TEL = "tel:" ;
private static final String SCHEME_HTTP = "http:" ; private static final String SCHEME_HTTP = "http:" ;
private static final String SCHEME_EMAIL = "mailto:" ; private static final String SCHEME_EMAIL = "mailto:" ;
private static final Map<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>(); private static final Map<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>();
static { static {
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel); sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel);
sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web); sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web);
sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email); sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email);
} }
/** /**
* Call by the {@link NoteEditActivity} to delete or add edit text * Call by the {@link NoteEditActivity} to delete or add edit text
*/ */
@ -62,65 +63,69 @@ public class NoteEditText extends EditText {
* and the text is null * and the text is null
*/ */
void onEditTextDelete(int index, String text); void onEditTextDelete(int index, String text);
/** /**
* Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER} * Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER}
* happen * happen
*/ */
void onEditTextEnter(int index, String text); void onEditTextEnter(int index, String text);
/** /**
* Hide or show item option when text change * Hide or show item option when text change
*/ */
void onTextChange(int index, boolean hasText); void onTextChange(int index, boolean hasText);
} }
private OnTextViewChangeListener mOnTextViewChangeListener; private OnTextViewChangeListener mOnTextViewChangeListener;
public NoteEditText(Context context) { public NoteEditText(Context context) {
super(context, null); super(context, null);
mIndex = 0; mIndex = 0;
} }
// 设置当前文本框的索引
public void setIndex(int index) { public void setIndex(int index) {
mIndex = index; mIndex = index;
} }
// 设置文本变化监听器
public void setOnTextViewChangeListener(OnTextViewChangeListener listener) { public void setOnTextViewChangeListener(OnTextViewChangeListener listener) {
mOnTextViewChangeListener = listener; mOnTextViewChangeListener = listener;
} }
public NoteEditText(Context context, AttributeSet attrs) { public NoteEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle); super(context, attrs, android.R.attr.editTextStyle);
} }
public NoteEditText(Context context, AttributeSet attrs, int defStyle) { public NoteEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
// 处理触摸事件,更新光标位置
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
int x = (int) event.getX(); int x = (int) event.getX();
int y = (int) event.getY(); int y = (int) event.getY();
x -= getTotalPaddingLeft(); x -= getTotalPaddingLeft();
y -= getTotalPaddingTop(); y -= getTotalPaddingTop();
x += getScrollX(); x += getScrollX();
y += getScrollY(); y += getScrollY();
Layout layout = getLayout(); Layout layout = getLayout();
int line = layout.getLineForVertical(y); int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x); int off = layout.getOffsetForHorizontal(line, x);
Selection.setSelection(getText(), off); Selection.setSelection(getText(), off);
break; break;
} }
return super.onTouchEvent(event); return super.onTouchEvent(event);
} }
// 处理按键按下事件,记录删除操作前的光标位置
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) { switch (keyCode) {
@ -137,7 +142,8 @@ public class NoteEditText extends EditText {
} }
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }
// 处理按键弹起事件,根据按键类型执行相应操作
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
switch(keyCode) { switch(keyCode) {
@ -166,7 +172,8 @@ public class NoteEditText extends EditText {
} }
return super.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
} }
// 当EditText焦点发生变化时调用通知监听器文本是否有内容
@Override @Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (mOnTextViewChangeListener != null) { if (mOnTextViewChangeListener != null) {
@ -178,16 +185,17 @@ public class NoteEditText extends EditText {
} }
super.onFocusChanged(focused, direction, previouslyFocusedRect); super.onFocusChanged(focused, direction, previouslyFocusedRect);
} }
// 创建上下文菜单处理URL点击事件
@Override @Override
protected void onCreateContextMenu(ContextMenu menu) { protected void onCreateContextMenu(ContextMenu menu) {
if (getText() instanceof Spanned) { if (getText() instanceof Spanned) {
int selStart = getSelectionStart(); int selStart = getSelectionStart();
int selEnd = getSelectionEnd(); int selEnd = getSelectionEnd();
int min = Math.min(selStart, selEnd); int min = Math.min(selStart, selEnd);
int max = Math.max(selStart, selEnd); int max = Math.max(selStart, selEnd);
final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class);
if (urls.length == 1) { if (urls.length == 1) {
int defaultResId = 0; int defaultResId = 0;
@ -197,11 +205,11 @@ public class NoteEditText extends EditText {
break; break;
} }
} }
if (defaultResId == 0) { if (defaultResId == 0) {
defaultResId = R.string.note_link_other; defaultResId = R.string.note_link_other;
} }
menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener(
new OnMenuItemClickListener() { new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
@ -214,4 +222,4 @@ public class NoteEditText extends EditText {
} }
super.onCreateContextMenu(menu); super.onCreateContextMenu(menu);
} }
} }

@ -13,19 +13,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.text.TextUtils; import android.text.TextUtils;
import net.micode.notes.data.Contact; import net.micode.notes.data.Contact;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils; import net.micode.notes.tool.DataUtils;
// 该类用于从数据库游标中提取笔记项数据,并处理与笔记位置相关的逻辑
public class NoteItemData { public class NoteItemData {
static final String [] PROJECTION = new String [] { static final String [] PROJECTION = new String [] {
NoteColumns.ID, NoteColumns.ID,
@ -41,7 +41,8 @@ public class NoteItemData {
NoteColumns.WIDGET_ID, NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE, NoteColumns.WIDGET_TYPE,
}; };
// 定义了游标中各个列的索引位置
private static final int ID_COLUMN = 0; private static final int ID_COLUMN = 0;
private static final int ALERTED_DATE_COLUMN = 1; private static final int ALERTED_DATE_COLUMN = 1;
private static final int BG_COLOR_ID_COLUMN = 2; private static final int BG_COLOR_ID_COLUMN = 2;
@ -54,7 +55,8 @@ public class NoteItemData {
private static final int TYPE_COLUMN = 9; private static final int TYPE_COLUMN = 9;
private static final int WIDGET_ID_COLUMN = 10; private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_TYPE_COLUMN = 11; private static final int WIDGET_TYPE_COLUMN = 11;
// 笔记项的各种属性
private long mId; private long mId;
private long mAlertDate; private long mAlertDate;
private int mBgColorId; private int mBgColorId;
@ -69,13 +71,15 @@ public class NoteItemData {
private int mWidgetType; private int mWidgetType;
private String mName; private String mName;
private String mPhoneNumber; private String mPhoneNumber;
// 笔记项在列表中的位置信息
private boolean mIsLastItem; private boolean mIsLastItem;
private boolean mIsFirstItem; private boolean mIsFirstItem;
private boolean mIsOnlyOneItem; private boolean mIsOnlyOneItem;
private boolean mIsOneNoteFollowingFolder; private boolean mIsOneNoteFollowingFolder;
private boolean mIsMultiNotesFollowingFolder; private boolean mIsMultiNotesFollowingFolder;
// 构造函数,从游标中提取笔记项数据
public NoteItemData(Context context, Cursor cursor) { public NoteItemData(Context context, Cursor cursor) {
mId = cursor.getLong(ID_COLUMN); mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN); mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
@ -91,7 +95,7 @@ public class NoteItemData {
mType = cursor.getInt(TYPE_COLUMN); mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN); mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN); mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
mPhoneNumber = ""; mPhoneNumber = "";
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) { if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId); mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
@ -102,20 +106,21 @@ public class NoteItemData {
} }
} }
} }
if (mName == null) { if (mName == null) {
mName = ""; mName = "";
} }
checkPostion(cursor); checkPostion(cursor);
} }
// 检查笔记项在列表中的位置信息
private void checkPostion(Cursor cursor) { private void checkPostion(Cursor cursor) {
mIsLastItem = cursor.isLast() ? true : false; mIsLastItem = cursor.isLast() ? true : false;
mIsFirstItem = cursor.isFirst() ? true : false; mIsFirstItem = cursor.isFirst() ? true : false;
mIsOnlyOneItem = (cursor.getCount() == 1); mIsOnlyOneItem = (cursor.getCount() == 1);
mIsMultiNotesFollowingFolder = false; mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false; mIsOneNoteFollowingFolder = false;
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) { if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
int position = cursor.getPosition(); int position = cursor.getPosition();
if (cursor.moveToPrevious()) { if (cursor.moveToPrevious()) {
@ -133,92 +138,114 @@ public class NoteItemData {
} }
} }
} }
// 判断该笔记项是否是单个笔记跟在一个文件夹后
public boolean isOneFollowingFolder() { public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder; return mIsOneNoteFollowingFolder;
} }
// 判断该笔记项是否是多个笔记跟在一个文件夹后
public boolean isMultiFollowingFolder() { public boolean isMultiFollowingFolder() {
return mIsMultiNotesFollowingFolder; return mIsMultiNotesFollowingFolder;
} }
// 判断该笔记项是否是列表中的最后一个项
public boolean isLast() { public boolean isLast() {
return mIsLastItem; return mIsLastItem;
} }
// 获取与该笔记项关联的呼叫记录的联系人名称
public String getCallName() { public String getCallName() {
return mName; return mName;
} }
// 判断该笔记项是否是列表中的第一个项
public boolean isFirst() { public boolean isFirst() {
return mIsFirstItem; return mIsFirstItem;
} }
// 判断该笔记项是否是列表中唯一的项
public boolean isSingle() { public boolean isSingle() {
return mIsOnlyOneItem; return mIsOnlyOneItem;
} }
// 获取笔记项的ID
public long getId() { public long getId() {
return mId; return mId;
} }
// 获取笔记项的提醒日期
public long getAlertDate() { public long getAlertDate() {
return mAlertDate; return mAlertDate;
} }
// 获取笔记项的创建日期
public long getCreatedDate() { public long getCreatedDate() {
return mCreatedDate; return mCreatedDate;
} }
// 判断该笔记项是否有附件
public boolean hasAttachment() { public boolean hasAttachment() {
return mHasAttachment; return mHasAttachment;
} }
// 获取笔记项的修改日期
public long getModifiedDate() { public long getModifiedDate() {
return mModifiedDate; return mModifiedDate;
} }
// 获取笔记项的背景颜色ID
public int getBgColorId() { public int getBgColorId() {
return mBgColorId; return mBgColorId;
} }
// 获取笔记项的父ID
public long getParentId() { public long getParentId() {
return mParentId; return mParentId;
} }
// 获取笔记项包含的笔记数量
public int getNotesCount() { public int getNotesCount() {
return mNotesCount; return mNotesCount;
} }
// 获取笔记项所在的文件夹ID
public long getFolderId () { public long getFolderId () {
return mParentId; return mParentId;
} }
// 获取笔记项的类型
public int getType() { public int getType() {
return mType; return mType;
} }
// 获取笔记项的小部件类型
public int getWidgetType() { public int getWidgetType() {
return mWidgetType; return mWidgetType;
} }
// 获取笔记项的小部件ID
public int getWidgetId() { public int getWidgetId() {
return mWidgetId; return mWidgetId;
} }
// 获取笔记项的摘要
public String getSnippet() { public String getSnippet() {
return mSnippet; return mSnippet;
} }
// 判断该笔记项是否有提醒
public boolean hasAlert() { public boolean hasAlert() {
return (mAlertDate > 0); return (mAlertDate > 0);
} }
// 判断该笔记项是否是呼叫记录类型
public boolean isCallRecord() { public boolean isCallRecord() {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber)); return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
} }
// 静态方法,从游标中获取笔记项的类型
public static int getNoteType(Cursor cursor) { public static int getNoteType(Cursor cursor) {
return cursor.getInt(TYPE_COLUMN); return cursor.getInt(TYPE_COLUMN);
} }
} }

@ -126,12 +126,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private NoteItemData mFocusNoteDataItem; private NoteItemData mFocusNoteDataItem;
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?"; private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>"
+ Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR (" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ NoteColumns.NOTES_COUNT + ">0)"; + NoteColumns.NOTES_COUNT + ">0)";
private final static int REQUEST_CODE_OPEN_NODE = 102; private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103; private final static int REQUEST_CODE_NEW_NODE = 103;
@ -951,4 +951,4 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
} }
return false; return false;
} }
} }

@ -13,48 +13,52 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CursorAdapter; import android.widget.CursorAdapter;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
// 自定义的CursorAdapter用于显示笔记列表
public class NotesListAdapter extends CursorAdapter { public class NotesListAdapter extends CursorAdapter {
private static final String TAG = "NotesListAdapter"; private static final String TAG = "NotesListAdapter";
private Context mContext; private Context mContext;
private HashMap<Integer, Boolean> mSelectedIndex; private HashMap<Integer, Boolean> mSelectedIndex;
private int mNotesCount; private int mNotesCount;
private boolean mChoiceMode; private boolean mChoiceMode;
// 用于存储小部件属性的内部类
public static class AppWidgetAttribute { public static class AppWidgetAttribute {
public int widgetId; public int widgetId;
public int widgetType; public int widgetType;
}; };
// 构造函数,初始化上下文和选择索引
public NotesListAdapter(Context context) { public NotesListAdapter(Context context) {
super(context, null); super(context, null);
mSelectedIndex = new HashMap<Integer, Boolean>(); mSelectedIndex = new HashMap<Integer, Boolean>();
mContext = context; mContext = context;
mNotesCount = 0; mNotesCount = 0;
} }
// 创建新的视图项
@Override @Override
public View newView(Context context, Cursor cursor, ViewGroup parent) { public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new NotesListItem(context); return new NotesListItem(context);
} }
// 绑定数据到视图项
@Override @Override
public void bindView(View view, Context context, Cursor cursor) { public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof NotesListItem) { if (view instanceof NotesListItem) {
@ -63,21 +67,25 @@ public class NotesListAdapter extends CursorAdapter {
isSelectedItem(cursor.getPosition())); isSelectedItem(cursor.getPosition()));
} }
} }
// 设置指定位置的项是否被选中,并通知数据集发生变化
public void setCheckedItem(final int position, final boolean checked) { public void setCheckedItem(final int position, final boolean checked) {
mSelectedIndex.put(position, checked); mSelectedIndex.put(position, checked);
notifyDataSetChanged(); notifyDataSetChanged();
} }
// 检查当前是否处于多选模式
public boolean isInChoiceMode() { public boolean isInChoiceMode() {
return mChoiceMode; return mChoiceMode;
} }
// 设置多选模式,清空选择索引
public void setChoiceMode(boolean mode) { public void setChoiceMode(boolean mode) {
mSelectedIndex.clear(); mSelectedIndex.clear();
mChoiceMode = mode; mChoiceMode = mode;
} }
// 全选或全不选所有笔记
public void selectAll(boolean checked) { public void selectAll(boolean checked) {
Cursor cursor = getCursor(); Cursor cursor = getCursor();
for (int i = 0; i < getCount(); i++) { for (int i = 0; i < getCount(); i++) {
@ -88,7 +96,8 @@ public class NotesListAdapter extends CursorAdapter {
} }
} }
} }
// 获取所有选中的笔记ID集合
public HashSet<Long> getSelectedItemIds() { public HashSet<Long> getSelectedItemIds() {
HashSet<Long> itemSet = new HashSet<Long>(); HashSet<Long> itemSet = new HashSet<Long>();
for (Integer position : mSelectedIndex.keySet()) { for (Integer position : mSelectedIndex.keySet()) {
@ -101,10 +110,11 @@ public class NotesListAdapter extends CursorAdapter {
} }
} }
} }
return itemSet; return itemSet;
} }
// 获取所有选中的小部件属性集合
public HashSet<AppWidgetAttribute> getSelectedWidget() { public HashSet<AppWidgetAttribute> getSelectedWidget() {
HashSet<AppWidgetAttribute> itemSet = new HashSet<AppWidgetAttribute>(); HashSet<AppWidgetAttribute> itemSet = new HashSet<AppWidgetAttribute>();
for (Integer position : mSelectedIndex.keySet()) { for (Integer position : mSelectedIndex.keySet()) {
@ -127,7 +137,8 @@ public class NotesListAdapter extends CursorAdapter {
} }
return itemSet; return itemSet;
} }
// 获取选中的笔记数量
public int getSelectedCount() { public int getSelectedCount() {
Collection<Boolean> values = mSelectedIndex.values(); Collection<Boolean> values = mSelectedIndex.values();
if (null == values) { if (null == values) {
@ -142,31 +153,36 @@ public class NotesListAdapter extends CursorAdapter {
} }
return count; return count;
} }
// 检查是否所有笔记都被选中
public boolean isAllSelected() { public boolean isAllSelected() {
int checkedCount = getSelectedCount(); int checkedCount = getSelectedCount();
return (checkedCount != 0 && checkedCount == mNotesCount); return (checkedCount != 0 && checkedCount == mNotesCount);
} }
// 检查指定位置的项是否被选中
public boolean isSelectedItem(final int position) { public boolean isSelectedItem(final int position) {
if (null == mSelectedIndex.get(position)) { if (null == mSelectedIndex.get(position)) {
return false; return false;
} }
return mSelectedIndex.get(position); return mSelectedIndex.get(position);
} }
// 当数据内容发生变化时,更新笔记数量
@Override @Override
protected void onContentChanged() { protected void onContentChanged() {
super.onContentChanged(); super.onContentChanged();
calcNotesCount(); calcNotesCount();
} }
// 更改Cursor时更新笔记数量
@Override @Override
public void changeCursor(Cursor cursor) { public void changeCursor(Cursor cursor) {
super.changeCursor(cursor); super.changeCursor(cursor);
calcNotesCount(); calcNotesCount();
} }
// 计算笔记数量
private void calcNotesCount() { private void calcNotesCount() {
mNotesCount = 0; mNotesCount = 0;
for (int i = 0; i < getCount(); i++) { for (int i = 0; i < getCount(); i++) {
@ -181,4 +197,4 @@ public class NotesListAdapter extends CursorAdapter {
} }
} }
} }
} }

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.content.Context; import android.content.Context;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.view.View; import android.view.View;
@ -23,13 +23,13 @@ import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import net.micode.notes.R; import net.micode.notes.R;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.tool.DataUtils; import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser.NoteItemBgResources; import net.micode.notes.tool.ResourceParser.NoteItemBgResources;
// NotesListItem 类继承自 LinearLayout用于表示笔记列表中的一个项
public class NotesListItem extends LinearLayout { public class NotesListItem extends LinearLayout {
private ImageView mAlert; private ImageView mAlert;
private TextView mTitle; private TextView mTitle;
@ -37,7 +37,8 @@ public class NotesListItem extends LinearLayout {
private TextView mCallName; private TextView mCallName;
private NoteItemData mItemData; private NoteItemData mItemData;
private CheckBox mCheckBox; private CheckBox mCheckBox;
// 构造函数,初始化 NotesListItem 的视图组件
public NotesListItem(Context context) { public NotesListItem(Context context) {
super(context); super(context);
inflate(context, R.layout.note_item, this); inflate(context, R.layout.note_item, this);
@ -47,7 +48,8 @@ public class NotesListItem extends LinearLayout {
mCallName = (TextView) findViewById(R.id.tv_name); mCallName = (TextView) findViewById(R.id.tv_name);
mCheckBox = (CheckBox) findViewById(android.R.id.checkbox); mCheckBox = (CheckBox) findViewById(android.R.id.checkbox);
} }
// 绑定数据到 NotesListItem 的视图组件,并设置选择模式和选中状态
public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) {
if (choiceMode && data.getType() == Notes.TYPE_NOTE) { if (choiceMode && data.getType() == Notes.TYPE_NOTE) {
mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setVisibility(View.VISIBLE);
@ -55,7 +57,7 @@ public class NotesListItem extends LinearLayout {
} else { } else {
mCheckBox.setVisibility(View.GONE); mCheckBox.setVisibility(View.GONE);
} }
mItemData = data; mItemData = data;
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mCallName.setVisibility(View.GONE); mCallName.setVisibility(View.GONE);
@ -78,7 +80,7 @@ public class NotesListItem extends LinearLayout {
} else { } else {
mCallName.setVisibility(View.GONE); mCallName.setVisibility(View.GONE);
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
if (data.getType() == Notes.TYPE_FOLDER) { if (data.getType() == Notes.TYPE_FOLDER) {
mTitle.setText(data.getSnippet() mTitle.setText(data.getSnippet()
+ context.getString(R.string.format_folder_files_count, + context.getString(R.string.format_folder_files_count,
@ -95,10 +97,11 @@ public class NotesListItem extends LinearLayout {
} }
} }
mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate()));
setBackground(data); setBackground(data);
} }
// 根据数据设置 NotesListItem 的背景资源
private void setBackground(NoteItemData data) { private void setBackground(NoteItemData data) {
int id = data.getBgColorId(); int id = data.getBgColorId();
if (data.getType() == Notes.TYPE_NOTE) { if (data.getType() == Notes.TYPE_NOTE) {
@ -115,8 +118,9 @@ public class NotesListItem extends LinearLayout {
setBackgroundResource(NoteItemBgResources.getFolderBgRes()); setBackgroundResource(NoteItemBgResources.getFolderBgRes());
} }
} }
// 获取绑定到此 NotesListItem 的数据
public NoteItemData getItemData() { public NoteItemData getItemData() {
return mItemData; return mItemData;
} }
} }

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.micode.notes.ui; package net.micode.notes.ui;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.app.ActionBar; import android.app.ActionBar;
@ -41,59 +41,60 @@ import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import net.micode.notes.R; import net.micode.notes.R;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.remote.GTaskSyncService; import net.micode.notes.gtask.remote.GTaskSyncService;
// 设置界面活动类继承自PreferenceActivity
public class NotesPreferenceActivity extends PreferenceActivity { public class NotesPreferenceActivity extends PreferenceActivity {
public static final String PREFERENCE_NAME = "notes_preferences"; public static final String PREFERENCE_NAME = "notes_preferences";
public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name"; public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";
public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time"; public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";
public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear";
private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key"; private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";
private static final String AUTHORITIES_FILTER_KEY = "authorities"; private static final String AUTHORITIES_FILTER_KEY = "authorities";
private PreferenceCategory mAccountCategory; private PreferenceCategory mAccountCategory;
private GTaskReceiver mReceiver; private GTaskReceiver mReceiver;
private Account[] mOriAccounts; private Account[] mOriAccounts;
private boolean mHasAddedAccount; private boolean mHasAddedAccount;
// 创建活动时初始化界面
@Override @Override
protected void onCreate(Bundle icicle) { protected void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
/* using the app icon for navigation */ /* 使用应用图标进行导航 */
getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setDisplayHomeAsUpEnabled(true);
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY); mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);
mReceiver = new GTaskReceiver(); mReceiver = new GTaskReceiver();
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
registerReceiver(mReceiver, filter); registerReceiver(mReceiver, filter);
mOriAccounts = null; mOriAccounts = null;
View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null); View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);
getListView().addHeaderView(header, null, true); getListView().addHeaderView(header, null, true);
} }
// 恢复活动时刷新界面
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
// need to set sync account automatically if user has added a new // 如果用户添加了新账户,自动设置同步账户
// account
if (mHasAddedAccount) { if (mHasAddedAccount) {
Account[] accounts = getGoogleAccounts(); Account[] accounts = getGoogleAccounts();
if (mOriAccounts != null && accounts.length > mOriAccounts.length) { if (mOriAccounts != null && accounts.length > mOriAccounts.length) {
@ -112,10 +113,11 @@ public class NotesPreferenceActivity extends PreferenceActivity {
} }
} }
} }
refreshUI(); refreshUI();
} }
// 销毁活动时注销广播接收器
@Override @Override
protected void onDestroy() { protected void onDestroy() {
if (mReceiver != null) { if (mReceiver != null) {
@ -123,10 +125,11 @@ public class NotesPreferenceActivity extends PreferenceActivity {
} }
super.onDestroy(); super.onDestroy();
} }
// 加载账户偏好设置
private void loadAccountPreference() { private void loadAccountPreference() {
mAccountCategory.removeAll(); mAccountCategory.removeAll();
Preference accountPref = new Preference(this); Preference accountPref = new Preference(this);
final String defaultAccount = getSyncAccountName(this); final String defaultAccount = getSyncAccountName(this);
accountPref.setTitle(getString(R.string.preferences_account_title)); accountPref.setTitle(getString(R.string.preferences_account_title));
@ -135,11 +138,10 @@ public class NotesPreferenceActivity extends PreferenceActivity {
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
if (!GTaskSyncService.isSyncing()) { if (!GTaskSyncService.isSyncing()) {
if (TextUtils.isEmpty(defaultAccount)) { if (TextUtils.isEmpty(defaultAccount)) {
// the first time to set account // 第一次设置账户
showSelectAccountAlertDialog(); showSelectAccountAlertDialog();
} else { } else {
// if the account has already been set, we need to promp // 如果账户已经设置,提示用户切换账户的风险
// user about the risk
showChangeAccountConfirmAlertDialog(); showChangeAccountConfirmAlertDialog();
} }
} else { } else {
@ -150,15 +152,16 @@ public class NotesPreferenceActivity extends PreferenceActivity {
return true; return true;
} }
}); });
mAccountCategory.addPreference(accountPref); mAccountCategory.addPreference(accountPref);
} }
// 加载同步按钮
private void loadSyncButton() { private void loadSyncButton() {
Button syncButton = (Button) findViewById(R.id.preference_sync_button); Button syncButton = (Button) findViewById(R.id.preference_sync_button);
TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
// set button state // 设置按钮状态
if (GTaskSyncService.isSyncing()) { if (GTaskSyncService.isSyncing()) {
syncButton.setText(getString(R.string.preferences_button_sync_cancel)); syncButton.setText(getString(R.string.preferences_button_sync_cancel));
syncButton.setOnClickListener(new View.OnClickListener() { syncButton.setOnClickListener(new View.OnClickListener() {
@ -175,8 +178,8 @@ public class NotesPreferenceActivity extends PreferenceActivity {
}); });
} }
syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this))); syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));
// set last sync time // 设置上次同步时间
if (GTaskSyncService.isSyncing()) { if (GTaskSyncService.isSyncing()) {
lastSyncTimeView.setText(GTaskSyncService.getProgressString()); lastSyncTimeView.setText(GTaskSyncService.getProgressString());
lastSyncTimeView.setVisibility(View.VISIBLE); lastSyncTimeView.setVisibility(View.VISIBLE);
@ -192,30 +195,32 @@ public class NotesPreferenceActivity extends PreferenceActivity {
} }
} }
} }
// 刷新用户界面
private void refreshUI() { private void refreshUI() {
loadAccountPreference(); loadAccountPreference();
loadSyncButton(); loadSyncButton();
} }
// 显示选择账户的对话框
private void showSelectAccountAlertDialog() { private void showSelectAccountAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_select_account_title)); titleTextView.setText(getString(R.string.preferences_dialog_select_account_title));
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips)); subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));
dialogBuilder.setCustomTitle(titleView); dialogBuilder.setCustomTitle(titleView);
dialogBuilder.setPositiveButton(null, null); dialogBuilder.setPositiveButton(null, null);
Account[] accounts = getGoogleAccounts(); Account[] accounts = getGoogleAccounts();
String defAccount = getSyncAccountName(this); String defAccount = getSyncAccountName(this);
mOriAccounts = accounts; mOriAccounts = accounts;
mHasAddedAccount = false; mHasAddedAccount = false;
if (accounts.length > 0) { if (accounts.length > 0) {
CharSequence[] items = new CharSequence[accounts.length]; CharSequence[] items = new CharSequence[accounts.length];
final CharSequence[] itemMapping = items; final CharSequence[] itemMapping = items;
@ -236,10 +241,10 @@ public class NotesPreferenceActivity extends PreferenceActivity {
} }
}); });
} }
View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null); View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
dialogBuilder.setView(addAccountView); dialogBuilder.setView(addAccountView);
final AlertDialog dialog = dialogBuilder.show(); final AlertDialog dialog = dialogBuilder.show();
addAccountView.setOnClickListener(new View.OnClickListener() { addAccountView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
@ -253,10 +258,11 @@ public class NotesPreferenceActivity extends PreferenceActivity {
} }
}); });
} }
// 显示更改账户确认对话框
private void showChangeAccountConfirmAlertDialog() { private void showChangeAccountConfirmAlertDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
titleTextView.setText(getString(R.string.preferences_dialog_change_account_title, titleTextView.setText(getString(R.string.preferences_dialog_change_account_title,
@ -264,7 +270,7 @@ public class NotesPreferenceActivity extends PreferenceActivity {
TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg)); subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));
dialogBuilder.setCustomTitle(titleView); dialogBuilder.setCustomTitle(titleView);
CharSequence[] menuItemArray = new CharSequence[] { CharSequence[] menuItemArray = new CharSequence[] {
getString(R.string.preferences_menu_change_account), getString(R.string.preferences_menu_change_account),
getString(R.string.preferences_menu_remove_account), getString(R.string.preferences_menu_remove_account),
@ -282,12 +288,14 @@ public class NotesPreferenceActivity extends PreferenceActivity {
}); });
dialogBuilder.show(); dialogBuilder.show();
} }
// 获取Google账户列表
private Account[] getGoogleAccounts() { private Account[] getGoogleAccounts() {
AccountManager accountManager = AccountManager.get(this); AccountManager accountManager = AccountManager.get(this);
return accountManager.getAccountsByType("com.google"); return accountManager.getAccountsByType("com.google");
} }
// 设置同步账户
private void setSyncAccount(String account) { private void setSyncAccount(String account) {
if (!getSyncAccountName(this).equals(account)) { if (!getSyncAccountName(this).equals(account)) {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
@ -298,11 +306,11 @@ public class NotesPreferenceActivity extends PreferenceActivity {
editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
} }
editor.commit(); editor.commit();
// clean up last sync time // 清除上次同步时间
setLastSyncTime(this, 0); setLastSyncTime(this, 0);
// clean up local gtask related info // 清除本地Gtask相关信息
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
@ -311,13 +319,14 @@ public class NotesPreferenceActivity extends PreferenceActivity {
getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
} }
}).start(); }).start();
Toast.makeText(NotesPreferenceActivity.this, Toast.makeText(NotesPreferenceActivity.this,
getString(R.string.preferences_toast_success_set_accout, account), getString(R.string.preferences_toast_success_set_accout, account),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
} }
// 移除同步账户
private void removeSyncAccount() { private void removeSyncAccount() {
SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit(); SharedPreferences.Editor editor = settings.edit();
@ -328,8 +337,8 @@ public class NotesPreferenceActivity extends PreferenceActivity {
editor.remove(PREFERENCE_LAST_SYNC_TIME); editor.remove(PREFERENCE_LAST_SYNC_TIME);
} }
editor.commit(); editor.commit();
// clean up local gtask related info // 清除本地Gtask相关信息
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
@ -339,13 +348,15 @@ public class NotesPreferenceActivity extends PreferenceActivity {
} }
}).start(); }).start();
} }
// 获取同步账户名称
public static String getSyncAccountName(Context context) { public static String getSyncAccountName(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE); Context.MODE_PRIVATE);
return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
} }
// 设置上次同步时间
public static void setLastSyncTime(Context context, long time) { public static void setLastSyncTime(Context context, long time) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE); Context.MODE_PRIVATE);
@ -353,15 +364,17 @@ public class NotesPreferenceActivity extends PreferenceActivity {
editor.putLong(PREFERENCE_LAST_SYNC_TIME, time); editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
editor.commit(); editor.commit();
} }
// 获取上次同步时间
public static long getLastSyncTime(Context context) { public static long getLastSyncTime(Context context) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
Context.MODE_PRIVATE); Context.MODE_PRIVATE);
return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0); return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
} }
// 广播接收器,用于接收同步状态更新
private class GTaskReceiver extends BroadcastReceiver { private class GTaskReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
refreshUI(); refreshUI();
@ -370,10 +383,11 @@ public class NotesPreferenceActivity extends PreferenceActivity {
syncStatus.setText(intent syncStatus.setText(intent
.getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG)); .getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));
} }
} }
} }
// 选项菜单项点击事件处理
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case android.R.id.home: case android.R.id.home:
@ -385,4 +399,4 @@ public class NotesPreferenceActivity extends PreferenceActivity {
return false; return false;
} }
} }
} }
Loading…
Cancel
Save