Merge pull request 'ui包前七个类的标注' (#9) from xumingyang_branch into main

pull/17/head
ps249eph7 11 months ago
commit 08f777bb09

@ -39,36 +39,77 @@ import net.micode.notes.tool.DataUtils;
import java.io.IOException;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: AlarmAlertActivity
* @Description: AlarmAlertActivity
* 便AlarmAlertActivity
*
*
* @Author: xumingyang
* @CreateDate: 2023-12-24 10:33
* @UpdateUser:
* @UpdateDate: 2023-12-24 10:33
* @UpdateRemark:
* @Version: 1.0
*/
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
private long mNoteId;
private String mSnippet;
private long mNoteId; //文本在数据库存储中的ID号
private String mSnippet; //闹钟提示时出现的文本片段
private static final int SNIPPET_PREW_MAX_LEN = 60;
MediaPlayer mPlayer;
/**
* @method onCreate
* @description :
*
*
* Intent便ID
* 使便ID便
* MediaPlayer
* 便便
* 便
* 便
* @date: 2023-12-24 10:41
* @author: xumingyang
* @param
* @return
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Bundle类型的数据与Map类型的数据相似都是以key-value的形式存储数据的
//onsaveInstanceState方法是用来保存Activity的状态的
//能从onCreate的参数savedInsanceState中获得状态数
requestWindowFeature(Window.FEATURE_NO_TITLE);
//界面显示——无标题
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
if (!isScreenOn()) {
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
//保持窗体点亮
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
//将窗体点亮
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
//允许窗体点亮时锁屏
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
}
}//在手机锁屏后如果到了闹钟提示时间,点亮屏幕
Intent intent = getIntent();
try {
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
//根据ID从数据库中获取标签的内容
//getContentResolver是实现数据共享实例存储。
mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0,
SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info)
: mSnippet;
//判断标签片段是否达到符合长度
} catch (IllegalArgumentException e) {
e.printStackTrace();
return;
@ -77,20 +118,41 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
mPlayer = new MediaPlayer();
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
showActionDialog();
//弹出对话框
playAlarmSound();
//闹钟提示音激发
} else {
finish();
//完成闹钟动作
}
}
/**
* @method isScreenOn
* @description
* @date: 2023-12-24 10:45
* @author: xumingyang
* @param
* @return bool
*/
private boolean isScreenOn() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
return pm.isScreenOn();
}
/**
* @method playAlarmSound
* @description:
*
*
* @date: 2023-12-24 10:47
* @author: xumingyang
* @param
* @return
*/
private void playAlarmSound() {
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
//调用系统的铃声管理URI得到闹钟提示音
int silentModeStreams = Settings.System.getInt(getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
@ -101,12 +163,19 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
try {
mPlayer.setDataSource(this, url);
//方法setDataSource(Context context, Uri uri)
//解释:无返回值,设置多媒体数据来源【根据 Uri】
mPlayer.prepare();
//准备同步
mPlayer.setLooping(true);
//设置是否循环播放
mPlayer.start();
//开始播放
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//e.printStackTrace()函数功能是抛出异常, 还将显示出更深的调用信息
//System.out.println(e),这个方法打印出异常,并且输出在哪里出现的异常
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -119,39 +188,99 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
}
/**
* @method showActionDialog
* @description
* AlertDialog.BuilderR.string.app_name
* mSnippet
* Positive ButtonR.string.notealert_ok
* isScreenOn()Negative ButtonR.string.notealert_enter
* dialog.show().setOnDismissListener(this)
* @date: 2023-12-24 10:51
* @author: xumingyang
* @param
* @return
*/
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
/*
* AlertDialogProtected
* newAlertDialogAlertDialog
* AlertDialogAlertDialog.Buildercreate()
* dialogAlertDialog
*/
dialog.setTitle(R.string.app_name);
//为对话框设置标题
dialog.setMessage(mSnippet);
//为对话框设置内容
dialog.setPositiveButton(R.string.notealert_ok, this);
//给对话框添加"Yes"按钮
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
}
}//对话框添加"No"按钮
dialog.show().setOnDismissListener(this);
}
/**
* @method onClick
* @description :
*
* 便idActivity
* @date: 2023-12-24 10:55
* @author: xumingyang
* @param
* @return
*/
public void onClick(DialogInterface dialog, int which) {
switch (which) {
//用which来选择click后下一步的操作
case DialogInterface.BUTTON_NEGATIVE:
//这是取消操作
Intent intent = new Intent(this, NoteEditActivity.class);
//实现两个类间的数据传输
intent.setAction(Intent.ACTION_VIEW);
//设置动作属性
intent.putExtra(Intent.EXTRA_UID, mNoteId);
//实现key-value对
//EXTRA_UID为keymNoteId为键
startActivity(intent);
//开始动作
break;
default:
//这是确定操作'
break;
}
}
/**
* @method onDismiss
* @description Activity
* @date: 2023-12-24 10:57
* @author: xumingyang
* @param
* @return
*/
public void onDismiss(DialogInterface dialog) {
stopAlarmSound();
//停止闹钟声音
finish();
//完成该动作
}
/**
* @method stopAlarmSound
* @description
* @date: 2023-12-24 10:58
* @author: xumingyang
* @param
* @return
*/
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop();
//停止播放
mPlayer.release();
//释放MediaPlayer对象
mPlayer = null;
}
}

@ -27,6 +27,21 @@ import android.database.Cursor;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: AlarmInitReceiver
* @Description: AlarmInitReceiver便广BroadcastReceiver
* 广
* @Author: xumingyang
* @CreateDate: 2023-12-24 11:11
* @UpdateUser:
* @UpdateDate: 2023-12-24 11:11
* @UpdateRemark:
* @Version: 1.0
*/
public class AlarmInitReceiver extends BroadcastReceiver {
@ -34,19 +49,35 @@ public class AlarmInitReceiver extends BroadcastReceiver {
NoteColumns.ID,
NoteColumns.ALERTED_DATE
};
//对数据库的操作调用标签ID和闹钟时间
private static final int COLUMN_ID = 0;
private static final int COLUMN_ALERTED_DATE = 1;
/**
* @method onReceive
* @description
* 便
* @date: 2023-12-24 11:26
* @author: xumingyang
* @param *Cursor
* alertDate
* Intentsender广AlarmReceiver
* PendingIntent使getBroadcast()广PendingIntentpendingIntent
* @return Cursorc
*/
@Override
public void onReceive(Context context, Intent intent) {
long currentDate = System.currentTimeMillis();
//System.currentTimeMillis()产生一个当前的毫秒
//这个毫秒其实就是自1970年1月1日0时起的毫秒数
Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE,
new String[] { String.valueOf(currentDate) },
//将long变量currentDate转化为字符串
null);
//Cursor在这里的作用是通过查找数据库中的标签内容找到和当前系统时间相等的标签
if (c != null) {
if (c.moveToFirst()) {
do {
@ -62,4 +93,9 @@ public class AlarmInitReceiver extends BroadcastReceiver {
c.close();
}
}
/*
*
* IntentPendingIntentAlarmManager
*
*/
}

@ -20,11 +20,37 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: AlarmReceiver
* @Description: AlarmReceiver便
*
* @Author: xumingyang
* @CreateDate: 2023-12-24 12:46
* @UpdateUser:
* @UpdateDate: 2023-12-24 12:46
* @UpdateRemark:
* @Version: 1.0
*/
/**
* @method
* @description 广AlarmAlertActivity
* @param *Context contextIntent intentcontextintent广
* @return
*/
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//重写了onReceive()方法,该方法在接收到广播时会被调用
intent.setClass(context, AlarmAlertActivity.class);
////启动AlarmAlertActivity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
////activity要存在于activity的栈中而非activity的途径启动activity时必然不存在一个activity的栈
//所以要新起一个栈装入启动的activity
context.startActivity(intent);
}
}

@ -28,8 +28,23 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.NumberPicker;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: DateTimePicker
* @Description:
* 使NumberPicker便
* @Author: xumingyang
* @CreateDate: 2023-12-24 12:58
* @UpdateUser:
* @UpdateDate: 2023-12-24 12:58
* @UpdateRemark:
* @Version: 1.0
*/
public class DateTimePicker extends FrameLayout {
//FrameLayout是布局模板之一
//所有的子元素全部在屏幕的右上方
private static final boolean DEFAULT_ENABLE_STATE = true;
private static final int HOURS_IN_HALF_DAY = 12;
@ -45,13 +60,15 @@ public class DateTimePicker extends FrameLayout {
private static final int MINUT_SPINNER_MAX_VAL = 59;
private static final int AMPM_SPINNER_MIN_VAL = 0;
private static final int AMPM_SPINNER_MAX_VAL = 1;
//初始化控件
private final NumberPicker mDateSpinner;
private final NumberPicker mHourSpinner;
private final NumberPicker mMinuteSpinner;
private final NumberPicker mAmPmSpinner;
//NumberPicker是数字选择器
//这里定义的四个变量全部是在设置闹钟时需要选择的变量(如日期、时、分、上午或者下午)
private Calendar mDate;
//定义了Calendar类型的变量mDate用于操作时间
private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK];
private boolean mIsAm;
@ -72,8 +89,22 @@ public class DateTimePicker extends FrameLayout {
onDateTimeChanged();
}
};
//OnValueChangeListener这是时间改变监听器这里主要是对日期的监听
//将现在日期的值传递给mDateupdateDateControl是同步操作
private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() {
//这里是对 小时Hour 的监听
/**
* @method onValueChange
* @description NumberPicker
*
* 24
* @date: 2023-12-24 13:03
* @author: xumingyang
* @param *Calendarcal便
* @return isdateChanged bool
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
boolean isDateChanged = false;
@ -83,29 +114,33 @@ public class DateTimePicker extends FrameLayout {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, 1);
isDateChanged = true;
//这里是对于12小时制时晚上11点和12点交替时对日期的更改
} else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -1);
isDateChanged = true;
}
}//这里是对于12小时制时晚上11点和12点交替时对日期的更改
if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY ||
oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {
mIsAm = !mIsAm;
updateAmPmControl();
}
}//这里是对于12小时制时中午11点和12点交替时对AM和PM的更改
} else {
if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, 1);
isDateChanged = true;
//这里是对于24小时制时晚上11点和12点交替时对日期的更改
} else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) {
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -1);
isDateChanged = true;
}
}
}//这里是对于12小时制时凌晨11点和12点交替时对日期的更改
int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY);
//通过数字选择器对newHour的赋值
mDate.set(Calendar.HOUR_OF_DAY, newHour);
//通过set函数将新的Hour值传给mDate
onDateTimeChanged();
if (isDateChanged) {
setCurrentYear(cal.get(Calendar.YEAR));
@ -116,16 +151,25 @@ public class DateTimePicker extends FrameLayout {
};
private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() {
/**
* @method onValueChange
* @description NumberPicker
*
* @param *picker NumberPicker oldVal newVal
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
int minValue = mMinuteSpinner.getMinValue();
int maxValue = mMinuteSpinner.getMaxValue();
int offset = 0;
//设置offset作为小时改变的一个记录数据
if (oldVal == maxValue && newVal == minValue) {
offset += 1;
} else if (oldVal == minValue && newVal == maxValue) {
offset -= 1;
}
//如果原值为59新值为0则offset加1
//如果原值为0新值为59则offset减1
if (offset != 0) {
mDate.add(Calendar.HOUR_OF_DAY, offset);
mHourSpinner.setValue(getCurrentHour());
@ -145,9 +189,15 @@ public class DateTimePicker extends FrameLayout {
};
private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {
/**
* @method onValueChange
* @description NumberPicker
* /
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mIsAm = !mIsAm;
//对AM和PM的监听
if (mIsAm) {
mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);
} else {
@ -166,18 +216,25 @@ public class DateTimePicker extends FrameLayout {
public DateTimePicker(Context context) {
this(context, System.currentTimeMillis());
}
//通过对数据库的访问,获取当前的系统时间
public DateTimePicker(Context context, long date) {
this(context, date, DateFormat.is24HourFormat(context));
}
//上面函数的得到的是一个天文数字1970至今的秒数需要DateFormat将其变得有意义
public DateTimePicker(Context context, long date, boolean is24HourView) {
super(context);
//获取系统时间
mDate = Calendar.getInstance();
mInitialising = true;
mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY;
inflate(context, R.layout.datetime_picker, this);
/*
* Activitylayoutlayout
* layoutinflate()layout
* findViewById()
*/
mDateSpinner = (NumberPicker) findViewById(R.id.date);
mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL);
mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL);
@ -214,17 +271,28 @@ public class DateTimePicker extends FrameLayout {
mInitialising = false;
}
/**
* @method setEnabled
* @description
* @param * enabled
* @return mIsEnabled enabled
*/
@Override
public void setEnabled(boolean enabled) {
if (mIsEnabled == enabled) {
return;
}
/*
* enabled mIsEnabled
*
*/
super.setEnabled(enabled);
mDateSpinner.setEnabled(enabled);
mMinuteSpinner.setEnabled(enabled);
mHourSpinner.setEnabled(enabled);
mAmPmSpinner.setEnabled(enabled);
mIsEnabled = enabled;
//将 mIsEnabled 的值更新为传入的 enabled以保持状态同步
}
@Override
@ -239,7 +307,7 @@ public class DateTimePicker extends FrameLayout {
*/
public long getCurrentDateInTimeMillis() {
return mDate.getTimeInMillis();
}
}//实现函数——得到当前的秒数
/**
* Set the current date
@ -251,7 +319,7 @@ public class DateTimePicker extends FrameLayout {
cal.setTimeInMillis(date);
setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE));
}
}//实现函数功能——设置当前的时间参数是date
/**
* Set the current date
@ -269,13 +337,14 @@ public class DateTimePicker extends FrameLayout {
setCurrentDay(dayOfMonth);
setCurrentHour(hourOfDay);
setCurrentMinute(minute);
}
}//实现函数功能——设置当前的时间,参数是各详细的变量
/**
* Get current year
*
* @return The current year
*/
//下面是得到year、month、day等值
public int getCurrentYear() {
return mDate.get(Calendar.YEAR);
}
@ -446,7 +515,7 @@ public class DateTimePicker extends FrameLayout {
mDateSpinner.setDisplayedValues(mDateDisplayValues);
mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2);
mDateSpinner.invalidate();
}
}// 对于星期几的算法
private void updateAmPmControl() {
if (mIs24HourView) {
@ -456,7 +525,7 @@ public class DateTimePicker extends FrameLayout {
mAmPmSpinner.setValue(index);
mAmPmSpinner.setVisibility(View.VISIBLE);
}
}
}// 对于上下午操作的算法
private void updateHourControl() {
if (mIs24HourView) {
@ -466,7 +535,7 @@ public class DateTimePicker extends FrameLayout {
mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);
mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);
}
}
}// 对与小时的算法
/**
* Set the callback that indicates the 'Set' button has been pressed.

@ -29,21 +29,43 @@ import android.content.DialogInterface.OnClickListener;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
/**
*
* @ProjectName: DateTimePickerDialog
* @Package: net.micode.notes.ui
* @ClassName: DateTimePickerDialog
* @Description: DateTimePickerDialog
* 便
* DateTimePickerDialog 便使便
* @Author: xumingyang
* @CreateDate: 2023-12-24 13:52
* @UpdateUser:
* @UpdateDate: 2023-12-24 13:52
* @UpdateRemark:
* @Version: 1.0
*/
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
private Calendar mDate = Calendar.getInstance();
//创建一个Calendar类型的变量 mDate方便时间的操作
private boolean mIs24HourView;
private OnDateTimeSetListener mOnDateTimeSetListener;
//声明一个时间日期滚动选择控件 mOnDateTimeSetListener
private DateTimePicker mDateTimePicker;
//DateTimePicker控件控件一般用于让用户可以从日期列表中选择单个值。
//运行时,单击控件边上的下拉箭头,会显示为两个部分:一个下拉列表,一个用于选择日期的
public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date);
}
public DateTimePickerDialog(Context context, long date) {
//对该界面对话框的实例化
super(context);
//对数据库的操作
mDateTimePicker = new DateTimePicker(context);
setView(mDateTimePicker);
//添加一个子视图
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() {
public void onDateTimeChanged(DateTimePicker view, int year, int month,
int dayOfMonth, int hourOfDay, int minute) {
@ -52,15 +74,21 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
mDate.set(Calendar.MINUTE, minute);
//将视图中的各选项设置为系统当前时间
updateTitle(mDate.getTimeInMillis());
}
});
mDate.setTimeInMillis(date);
//得到系统时间
mDate.set(Calendar.SECOND, 0);
//将秒数设置为0 对日期时间进行标准化处理
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
//将日期时间选择器设置为当前设置的日期时间。
setButton(context.getString(R.string.datetime_dialog_ok), this);
setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null);
//设置按钮
set24HourView(DateFormat.is24HourFormat(this.getContext()));
//时间标准化打印
updateTitle(mDate.getTimeInMillis());
}
@ -70,7 +98,7 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
}
}//将时间日期滚动选择控件实例化
private void updateTitle(long date) {
int flag =
@ -79,12 +107,13 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
DateUtils.FORMAT_SHOW_TIME;
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
}
}//android开发中常见日期管理工具类API——DateUtils按照上下午显示时间
public void onClick(DialogInterface arg0, int arg1) {
if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}
}
}//第一个参数arg0是接收到点击事件的对话框
//第二个参数arg1是该对话框上的按钮
}

@ -27,17 +27,38 @@ import android.widget.PopupMenu.OnMenuItemClickListener;
import net.micode.notes.R;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: DropdownMenu
* @Description: DropdownMenu
* DropdownMenu
* 1.使DropdownMenu便
* 2.使DropdownMenu
* 3.使DropdownMenu
* @Author: xumingyang
* @CreateDate: 2023-12-24 13:57
* @UpdateUser:
* @UpdateDate: 2023-12-24 13:57
* @UpdateRemark:
* @Version: 1.0
*/
public class DropdownMenu {
private Button mButton;
private PopupMenu mPopupMenu;
//声明一个下拉菜单
private Menu mMenu;
public DropdownMenu(Context context, Button button, int menuId) {
mButton = button;
mButton.setBackgroundResource(R.drawable.dropdown_icon);
//设置这个view的背景
mPopupMenu = new PopupMenu(context, mButton);
mMenu = mPopupMenu.getMenu();
mPopupMenu.getMenuInflater().inflate(menuId, mMenu);
//MenuInflater是用来实例化Menu目录下的Menu布局文件
//根据ID来确认menu的内容选项
mButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mPopupMenu.show();
@ -49,13 +70,13 @@ public class DropdownMenu {
if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener);
}
}
}//设置菜单的监听
public MenuItem findItem(int id) {
return mMenu.findItem(id);
}
//对于菜单选项的初始化,根据索引搜索菜单需要的选项
public void setTitle(CharSequence title) {
mButton.setText(title);
}
}
}//布局文件,设置标题

@ -28,25 +28,54 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
/**
*
* @ProjectName:
* @Package: net.micode.notes.ui
* @ClassName: FoldersListAdapter
* @Description: FoldersListAdapter
* @Author: xumingyang
* @CreateDate: 2023-12-24 14:05
* @UpdateUser:
* @UpdateDate: 2023-12-24 14:05
* @UpdateRemark:
* @Version: 1.0
*/
public class FoldersListAdapter extends CursorAdapter {
/*
* CursorAdapterCursorListView
* FoldersListAdapterCursorAdapter
* 便
* folder
*/
public static final String [] PROJECTION = {
NoteColumns.ID,
NoteColumns.SNIPPET
};
};//调用数据库中便签的ID和片段
public static final int ID_COLUMN = 0;
public static final int NAME_COLUMN = 1;
/**
* @method FoldersListAdapter
* @description FoldersListAdapter
* @param context
* c Cursor
*/
public FoldersListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}
}//数据库操作
/**
* @method newView
* @description
* @return 使
*/
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new FolderListItem(context);
}
}//创建一个文件夹,对于各文件夹中子标签的初始化
@Override
public void bindView(View view, Context context, Cursor cursor) {
@ -55,20 +84,23 @@ public class FoldersListAdapter extends CursorAdapter {
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
((FolderListItem) view).bind(folderName);
}
}
}//将各个布局文件绑定起来
public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position);
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
}
}//根据数据库中标签的ID得到标签的各项内容
private class FolderListItem extends LinearLayout {
private TextView mName;
public FolderListItem(Context context) {
super(context);
//操作数据库
inflate(context, R.layout.folder_list_item, this);
//根据布局文件的名字等信息将其找出来
mName = (TextView) findViewById(R.id.tv_folder_name);
}

@ -429,8 +429,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
int id = v.getId();
if (id == R.id.btn_set_bg_color) {
mNoteBgColorSelector.setVisibility(View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
- View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
@ -506,53 +505,58 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
@Override
//这段代码是一个用于处理菜单项点击事件的方法onOptionsItemSelected(MenuItem item)当用户点击菜单项时会根据菜单项的ID执行相应的操作。以下是对代码的解释
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_new_note:
createNewNote();
break;
case R.id.menu_delete:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.alert_title_delete));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage(getString(R.string.alert_message_delete_note));
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
deleteCurrentNote();
finish();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
break;
case R.id.menu_font_size:
mFontSizeSelector.setVisibility(View.VISIBLE);
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
break;
case R.id.menu_list_mode:
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
TextNote.MODE_CHECK_LIST : 0);
break;
case R.id.menu_share:
getWorkingText();
sendTo(this, mWorkingNote.getContent());
break;
case R.id.menu_send_to_desktop:
sendToDesktop();
break;
case R.id.menu_alert:
setReminder();
break;
case R.id.menu_delete_remind:
mWorkingNote.setAlertDate(0, false);
break;
default:
break;
int itemId = item.getItemId();
if (itemId == R.id.menu_new_note) {
createNewNote();
} else if (itemId == R.id.menu_delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.alert_title_delete));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage(getString(R.string.alert_message_delete_note));
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
deleteCurrentNote();
finish();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
} else if (itemId == R.id.menu_font_size) {//修改字体的大小
mFontSizeSelector.setVisibility(View.VISIBLE);
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
} else if (itemId == R.id.menu_list_mode) {
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
TextNote.MODE_CHECK_LIST : 0);
} else if (itemId == R.id.menu_share) {
getWorkingText();
sendTo(this, mWorkingNote.getContent());
} else if (itemId == R.id.menu_send_to_desktop) {
sendToDesktop();
} else if (itemId == R.id.menu_alert) {
setReminder();
} else if (itemId == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false);
}
return true;
}
//onOptionsItemSelected方法是一个覆盖方法用于在用户选择某个选项菜单项时被调用。
//
//在这段代码中首先获取选项菜单项的ID即itemId = item.getItemId()。
//
//然后使用if-else语句对不同的菜单项进行处理。
//
//若itemId等于R.id.menu_new_note则调用createNewNote()方法。
//若itemId等于R.id.menu_delete则创建一个AlertDialog对话框设置标题、图标和消息并添加确定按钮和取消按钮的点击事件监听器点击确定按钮时调用deleteCurrentNote()方法并结束当前活动。
//若itemId等于R.id.menu_font_size则设置字体大小选择器显示并根据当前选中的字体大小ID找到对应的视图并设置其可见性为可见。
//若itemId等于R.id.menu_list_mode则切换工作笔记的清单模式若当前为0则切换为检查清单模式否则切换为普通文本模式
//若itemId等于R.id.menu_share则获取当前工作笔记的文本内容并将其发送到指定目标。
//若itemId等于R.id.menu_send_to_desktop则发送笔记到桌面。
//若itemId等于R.id.menu_alert则设置提醒事项。
//若itemId等于R.id.menu_delete_remind则将工作笔记的提醒日期设置为0表示删除提醒。
//最后返回值为true表示已经处理了选择的菜单项。
private void setReminder() {
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
@ -562,7 +566,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
});
d.show();
}
//这段代码定义了一个名为setReminder的私有方法用于设置笔记的提醒时间。
//
//在方法内部首先创建一个DateTimePickerDialog对象d并将当前时间作为默认时间传递给该对象。
//
//接着为d设置一个OnDateTimeSetListener监听器当用户设置时间时会调用该监听器的OnDateTimeSet方法。在该方法中调用正在编辑的笔记对象mWorkingNote的setAlertDate方法将用户设置的时间转换成毫秒值并将其设置为笔记的提醒时间。
//
//最后显示d对话框让用户选择提醒时间。
//
//因此,这段代码用于弹出一个日期时间选择对话框,让用户设置笔记的提醒时间,并将设置的时间保存到正在编辑的笔记对象中。
/**
* Share note to apps that support {@link Intent#ACTION_SEND} action
* and {@text/plain} type
@ -573,8 +585,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
intent.setType("text/plain");
context.startActivity(intent);
}
private void createNewNote() {
//这段代码是一个私有方法sendTo用于使用系统默认的分享功能将指定的文本信息发送给其他应用程序。
//
//在方法内部首先创建一个新的Intent对象并将其动作设置为Intent.ACTION_SEND表示发送内容。
//
//接着通过putExtra方法将要分享的文本信息info放入Intent中使用Intent.EXTRA_TEXT作为键。
//
//然后使用setType方法将要分享的内容的MIME类型设置为"text/plain",表示纯文本类型。
//
//最后通过context.startActivity(intent)启动该Intent将文本信息发送给其他应用程序进行处理。
//
//因此这段代码用于在给定的Context上下文环境中利用系统默认的分享功能将特定的文本信息发送给其他应用程序。
private void createNewNote() {//新建便签
// Firstly, save current editing notes
saveNote();
@ -586,7 +609,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
startActivity(intent);
}
private void deleteCurrentNote() {
private void deleteCurrentNote() {//删除便签
if (mWorkingNote.existInDatabase()) {
HashSet<Long> ids = new HashSet<Long>();
long id = mWorkingNote.getNoteId();
@ -804,7 +827,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return hasChecked;
}
//段代码是一个私有方法getWorkingText用于获取工作笔记的文本内容并根据是否为待办事项模式进行相应处理。同时该方法返回一个布尔值表示在待办事项模式下是否有选中的项目。
//
//在方法内部首先检查当前工作笔记mWorkingNote是否为待办事项模式。如果是就遍历所有子视图view其中包含每个待办事项的复选框和文本编辑框。对于每个非空的文本编辑框如果其相应的复选框被选中则将文本内容作为已选中的待办事项添加到字符串缓冲区sb中并将标记hasChecked设置为true否则将文本内容作为未选中的待办事项添加到字符串缓冲区sb中。
//
//最后将字符串缓冲区sb中的内容作为工作笔记的文本内容设置到mWorkingNote对象中。如果不是待办事项模式则将文本编辑器mNoteEditor中的文本内容设置为工作笔记的文本内容。
//
//最终该方法返回一个布尔值hasChecked表示在待办事项模式下是否有选中的项目。
//
//因此,这段代码用于获取工作笔记的文本内容,并根据是否为待办事项模式进行相应处理并返回结果。
private boolean saveNote() {
getWorkingText();
boolean saved = mWorkingNote.saveNote();
@ -820,7 +851,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return saved;
}
//这段代码是一个私有方法saveNote用于保存当前正在编辑的笔记。
//
//在方法内部首先调用getWorkingText方法获取当前正在编辑的笔记的文本内容并将其保存到mWorkingNote对象中。
//
//接着调用mWorkingNote.saveNote()方法将笔记保存到数据库中并将保存结果保存到saved变量中。
//
//如果保存成功则调用setResult(RESULT_OK)方法设置当前Activity的返回状态为RESULT_OK。这个状态用于标识从编辑状态返回到列表视图时是创建新笔记还是编辑已有笔记。
//
//最后,返回保存是否成功的布尔值。
//
//因此,这段代码用于将当前正在编辑的笔记保存到数据库中,并设置返回状态。
private void sendToDesktop() {
/**
* Before send message to home, we should make sure that current
@ -855,7 +896,33 @@ public class NoteEditActivity extends Activity implements OnClickListener,
showToast(R.string.error_note_empty_for_send_to_desktop);
}
}
//这段代码定义了一个名为sendToDesktop的私有方法用于将笔记发送到桌面。
//
//在方法内部首先检查当前正在编辑的笔记是否存在于数据库中。如果笔记不存在于数据库中则调用saveNote()方法保存笔记。
//
//接着如果当前正在编辑的笔记具有有效的笔记ID即大于0则执行以下操作
//
//创建一个Intent对象sender用于发送广播。
//
//创建一个Intent对象shortcutIntent指定其目标为NoteEditActivity类并设置动作为Intent.ACTION_VIEW。
//
//将正在编辑的笔记ID作为附加数据放入shortcutIntent中。
//
//将笔记内容生成适合作为快捷方式图标标题的字符串并放入sender中作为附加数据。
//
//将应用程序的图标资源作为快捷方式图标放入sender中。
//
//设置sender的动作为com.android.launcher.action.INSTALL_SHORTCUT表示要安装快捷方式。
//
//弹出一个简短的提示消息,提示用户笔记已经进入桌面。
//
//发送广播,安装快捷方式。
//
//如果当前正在编辑的笔记没有有效的笔记ID则执行以下操作
//
//输出一个错误日志,表示发送到桌面出错。
//
//弹出一个提示消息,提醒用户必须输入一些内容才能发送到桌面。
private String makeShortcutIconTitle(String content) {
content = content.replace(TAG_CHECKED, "");
content = content.replace(TAG_UNCHECKED, "");

@ -319,28 +319,26 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
switch (item.getItemId()) {
case R.id.delete:
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(getString(R.string.alert_title_delete));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage(getString(R.string.alert_message_delete_notes,
mNotesListAdapter.getSelectedCount()));
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
batchDelete();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
break;
case R.id.move:
startQueryDestinationFolders();
break;
default:
return false;
int itemId = item.getItemId();
if (itemId == R.id.delete) {
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(getString(R.string.alert_title_delete));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage(getString(R.string.alert_message_delete_notes,
mNotesListAdapter.getSelectedCount()));
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
batchDelete();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
} else if (itemId == R.id.move) {
startQueryDestinationFolders();
} else {
return false;
}
return true;
}
@ -511,7 +509,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
Log.e(TAG, "Wrong folder id, should not happen " + folderId);
return;
}
//该方法接收一个参数folderId表示要删除的文件夹的ID。
//
//在方法内部首先通过条件判断检查folderId是否等于Notes.ID_ROOT_FOLDER根文件夹的ID。如果是根文件夹的ID则记录错误日志并返回不执行删除操作。
//
//这段代码的作用是避免意外情况下删除根文件夹因为根文件夹通常是系统的关键文件夹不应该被删除。如果传入的folderId等于根文件夹的ID会输出错误日志并直接返回避免继续执行删除根文件夹的操作。
HashSet<Long> ids = new HashSet<Long>();
ids.add(folderId);
HashSet<AppWidgetAttribute> widgets = DataUtils.getFolderNoteWidget(mContentResolver,
@ -556,14 +558,25 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
mTitleBar.setVisibility(View.VISIBLE);
}
//该方法接收一个参数data表示要打开的文件夹。
//
//首先将当前文件夹的ID设置为参数data的ID并调用startAsyncNotesListQuery()方法开始异步查询当前文件夹下的笔记列表。
//
//接下来根据文件夹的ID判断当前状态
//
//如果文件夹的ID为Notes.ID_CALL_RECORD_FOLDER则将状态设置为ListEditState.CALL_RECORD_FOLDER并隐藏添加新笔记按钮
//否则将状态设置为ListEditState.SUB_FOLDER。
//然后根据文件夹的ID设置标题栏的文本
//
//如果文件夹的ID为Notes.ID_CALL_RECORD_FOLDER则设置标题栏的文本为字符串资源R.string.call_record_folder_name
//否则设置标题栏的文本为文件夹的名称通过调用data.getSnippet()方法获取)。
//最后,将标题栏设置为可见状态。
//
//总之这段代码实现了打开文件夹的功能根据文件夹的ID设置不同的状态和标题并更新UI显示。
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_new_note:
createNewNote();
break;
default:
break;
if (v.getId() == R.id.btn_new_note) {
createNewNote();
}
}
@ -624,7 +637,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.LOCAL_MODIFIED, 1);
mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
+ "=?", new String[] {
String.valueOf(mFocusNoteDataItem.getId())
String.valueOf(mFocusNoteDataItem.getId())//获取文件夹名称,并设置对话框的标题为对应的修改文件夹名称;
});
}
} else if (!TextUtils.isEmpty(name)) {
@ -663,7 +676,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
});
}
//该方法接收一个参数create用于指示是创建文件夹还是修改文件夹。
//
//在方法内部首先创建一个AlertDialog.Builder对象并通过LayoutInflater从XML布局文件中实例化一个视图。
// 获取EditText对象用于输入文件夹名称并调用showSoftInput()方法显示软键盘。
//
//根据create参数的值判断是创建文件夹还是修改文件夹。如果是修改文件夹
// 则从mFocusNoteDataItem中获取文件夹名称并设置对话框的标题为对应的修改文件夹名称
// 如果是创建文件夹则将EditText的文本设置为空并设置对话框的标题为创建文件夹。
@Override
public void onBackPressed() {
switch (mState) {
@ -780,50 +800,55 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_new_folder: {
showCreateOrModifyFolderDialog(true);
break;
}
case R.id.menu_export_text: {
exportNoteToText();
break;
}
case R.id.menu_sync: {
if (isSyncMode()) {
if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
GTaskSyncService.startSync(this);
} else {
GTaskSyncService.cancelSync(this);
}
int itemId = item.getItemId();
if (itemId == R.id.menu_new_folder) {
showCreateOrModifyFolderDialog(true);
} else if (itemId == R.id.menu_export_text) {
exportNoteToText();
} else if (itemId == R.id.menu_sync) {
if (isSyncMode()) {
if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
GTaskSyncService.startSync(this);
} else {
startPreferenceActivity();
GTaskSyncService.cancelSync(this);
}
break;
}
case R.id.menu_setting: {
} else {
startPreferenceActivity();
break;
}
case R.id.menu_new_note: {
createNewNote();
break;
}
case R.id.menu_search:
onSearchRequested();
break;
default:
break;
} else if (itemId == R.id.menu_setting) {
startPreferenceActivity();
} else if (itemId == R.id.menu_new_note) {
createNewNote();
} else if (itemId == R.id.menu_search) {
onSearchRequested();
}
return true;
}
//每当用户选择菜单项时Android 系统会调用该方法并传入被选中的菜单项MenuItem。该方法首先获取被选中菜单项的ID然后根据不同的ID执行相应的操作。
//
//具体来说:
//
//如果选中的菜单项是R.id.menu_new_folder则调用showCreateOrModifyFolderDialog(true)方法,显示创建或修改文件夹的对话框。
//如果选中的菜单项是R.id.menu_export_text则调用exportNoteToText()方法,将笔记导出为文本。
//如果选中的菜单项是R.id.menu_sync则根据当前是否处于同步模式isSyncMode()分别启动或取消同步服务GTaskSyncService或打开设置活动startPreferenceActivity
//如果选中的菜单项是R.id.menu_setting则打开设置活动startPreferenceActivity
//如果选中的菜单项是R.id.menu_new_note则创建新的笔记createNewNote
//如果选中的菜单项是R.id.menu_search则执行搜索请求onSearchRequested
//最后该方法返回true表示菜单项的选择事件已经得到处理。
//
//总之,该方法根据用户选择的菜单项执行不同的操作,包括创建新文件夹、导出笔记、同步服务控制、打开设置活动、创建新笔记和执行搜索请求等。
@Override
public boolean onSearchRequested() {
startSearch(null, false, null /* appData */, false);
return true;
}
//nSearchRequested方法是一个覆盖方法用于在用户点击搜索按钮或者执行搜索手势时被调用。
//
//在这段代码中首先调用了startSearch方法来启动搜索功能。startSearch方法接受四个参数搜索关键字null表示没有指定关键字是否全局搜索false表示只搜索当前应用程序应用程序数据null表示没有额外的应用程序数据以及是否由用户触发的搜索false表示不是由用户触发
//
//然后返回值为true表示该方法已经处理了搜索请求并不需要其他的默认处理。
//
//总之该代码片段实现了在搜索请求时调用startSearch方法并返回true表示已经处理了该搜索请求。
private void exportNoteToText() {
final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
new AsyncTask<Void, Void, Integer>() {
@ -865,7 +890,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}.execute();
}
//首先定义了一个名为exportNoteToText的私有方法没有任何参数。
//
//在该方法中首先通过BackupUtils.getInstance(NotesListActivity.this)获取一个备份工具类的实例。然后创建一个异步任务AsyncTask来执行导出操作。
//
//在异步任务的doInBackground方法中调用backup.exportToText()方法来执行导出操作,并返回一个结果值。
//
//在异步任务的onPostExecute方法中根据导出的结果值进行不同的处理
//
//如果结果值等于BackupUtils.STATE_SD_CARD_UNMOUONTED表示SD卡未挂载弹出一个对话框提示导出失败和SD卡未挂载的错误信息。
//如果结果值等于BackupUtils.STATE_SUCCESS表示导出成功弹出一个对话框提示导出成功和导出文件的位置信息。
//如果结果值等于BackupUtils.STATE_SYSTEM_ERROR表示导出失败弹出一个对话框提示导出失败的错误信息。
//在最后通过调用execute方法来执行异步任务。
private boolean isSyncMode() {
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}

Loading…
Cancel
Save