From a8a737de09dca95170a9453e83e0c3fbdd685678 Mon Sep 17 00:00:00 2001 From: LiuRuiXuan <1912386608@qq.com> Date: Sat, 15 Apr 2023 23:13:08 +0800 Subject: [PATCH] =?UTF-8?q?210340062=E5=88=98=E7=91=9E=E8=BD=A9=E6=A0=87?= =?UTF-8?q?=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AlarmAlertActivity.java | 162 ++++++ .../AlarmInitReceiver.java | 70 +++ .../210340062_刘瑞轩/AlarmReceiver.java | 33 ++ .../210340062_刘瑞轩/DateTimePicker.java | 489 ++++++++++++++++++ .../DateTimePickerDialog.java | 90 ++++ .../210340062_刘瑞轩/DropdownMenu.java | 61 +++ .../FoldersListAdapter.java | 84 +++ 7 files changed, 989 insertions(+) create mode 100644 doc/标注/210340062_刘瑞轩/AlarmAlertActivity.java create mode 100644 doc/标注/210340062_刘瑞轩/AlarmInitReceiver.java create mode 100644 doc/标注/210340062_刘瑞轩/AlarmReceiver.java create mode 100644 doc/标注/210340062_刘瑞轩/DateTimePicker.java create mode 100644 doc/标注/210340062_刘瑞轩/DateTimePickerDialog.java create mode 100644 doc/标注/210340062_刘瑞轩/DropdownMenu.java create mode 100644 doc/标注/210340062_刘瑞轩/FoldersListAdapter.java diff --git a/doc/标注/210340062_刘瑞轩/AlarmAlertActivity.java b/doc/标注/210340062_刘瑞轩/AlarmAlertActivity.java new file mode 100644 index 0000000..8d98a55 --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/AlarmAlertActivity.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.DialogInterface.OnDismissListener; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.PowerManager; +import android.provider.Settings; +import android.view.Window; +import android.view.WindowManager; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.DataUtils; + +import java.io.IOException; +/* +author:刘瑞轩 +日期:2023-4-12 +*/ + +public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + private long mNoteId; + private String mSnippet; + private static final int SNIPPET_PREW_MAX_LEN = 60; + MediaPlayer mPlayer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState);//创建实例 + 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//在锁定状态下唤醒屏幕。如果该标志被设置,则当 Activity 启动时,系统将唤醒设备并点亮屏幕。 + | 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));//找到是否有对应的NoteId + mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, + SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) + : mSnippet; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + return; + } + + mPlayer = new MediaPlayer(); + if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {//如果存在对应的便签 + showActionDialog();//发出对话框 + playAlarmSound();//发出声音 + } else { + finish(); + } + } + + private boolean isScreenOn() { + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + return pm.isScreenOn(); + } + + private void playAlarmSound() { + //获取系统中当前默认的闹钟铃声所对应的 Uri,并将其赋值给 url 变量 + Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + //获取当前系统中哪些音频流会受到静音模式的影响 + int silentModeStreams = Settings.System.getInt(getContentResolver(), + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + //如果STREAM_ALARM受到影响,那么就将音频流形式设置为silentModeStreams + if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { + mPlayer.setAudioStreamType(silentModeStreams); + } else { + mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); + } + try { + mPlayer.setDataSource(this, url); + mPlayer.prepare();//于为音频播放做一些准备工作。具体来说,该方法会解析音频数据、分离音频轨道、获取音频格式信息等操作 + mPlayer.setLooping(true); + mPlayer.start(); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalStateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void showActionDialog() { + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setTitle(R.string.app_name);//设置对话框的标题 + dialog.setMessage(mSnippet);//设置对话框的信息 + dialog.setPositiveButton(R.string.notealert_ok, this);//设置确认按钮,在确认按钮按下后显示对话框 + if (isScreenOn()) { + dialog.setNegativeButton(R.string.notealert_enter, this);//关闭对话框 + } + dialog.show().setOnDismissListener(this);//执行相关的动作 + } + + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_NEGATIVE: + Intent intent = new Intent(this, NoteEditActivity.class);//新创建一个页面 + intent.setAction(Intent.ACTION_VIEW);//显示页面 + intent.putExtra(Intent.EXTRA_UID, mNoteId);//放入对应的数据库中 + startActivity(intent);//运行该页面 + break; + default: + break; + } + } + + public void onDismiss(DialogInterface dialog) { + stopAlarmSound();//关闭闹钟铃声 + finish();//该页面结束 + } + + private void stopAlarmSound() { + if (mPlayer != null) {//如果该播放器存在 + mPlayer.stop();//停下 + mPlayer.release();//释放资源 + mPlayer = null; + } + } +} diff --git a/doc/标注/210340062_刘瑞轩/AlarmInitReceiver.java b/doc/标注/210340062_刘瑞轩/AlarmInitReceiver.java new file mode 100644 index 0000000..1342567 --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/AlarmInitReceiver.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +/* +Author:刘瑞轩 +Data:2023-4-12 +*/ + +public class AlarmInitReceiver extends BroadcastReceiver { + + private static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.ALERTED_DATE + }; + + private static final int COLUMN_ID = 0; + private static final int COLUMN_ALERTED_DATE = 1; + + @Override + public void onReceive(Context context, Intent intent) { + long currentDate = System.currentTimeMillis();//找到目前的时间段 + Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + PROJECTION, + NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, + new String[] { String.valueOf(currentDate) }, + null);//筛选出来那些提醒时间大于当前时间并且类型是便签类型的 + + if (c != null) { + if (c.moveToFirst()) {//如果下一个数据存在的话 + do { + long alertDate = c.getLong(COLUMN_ALERTED_DATE);//获取当前数据的日期 + Intent sender = new Intent(context, AlarmReceiver.class);//获取一个新的页面 + sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + AlarmManager alermManager = (AlarmManager) context + .getSystemService(Context.ALARM_SERVICE); + alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent);//采用系统实时时钟(RTC)闹钟 + //当闹钟到达alertDate时唤醒设备,保证不会在睡眠模式错过闹钟,第二个参数是闹钟的触发时间,第三个就是指定谁到时候就会 + //被触发 + } while (c.moveToNext());//只要下一个数据存在的话 + } + c.close();//关闭流文件 + } + } +} diff --git a/doc/标注/210340062_刘瑞轩/AlarmReceiver.java b/doc/标注/210340062_刘瑞轩/AlarmReceiver.java new file mode 100644 index 0000000..186b4d5 --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/AlarmReceiver.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +/* +Author:刘瑞轩 +Data:2023/4/12 +*/ +public class AlarmReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + intent.setClass(context, AlarmAlertActivity.class);//由当前页面跳转到对应界面 + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//该标记表示在新任务栈中启动 Activity,当它不在前台的时候,保证其可以在后台显示 + context.startActivity(intent);//启动对应的活动 + } +} diff --git a/doc/标注/210340062_刘瑞轩/DateTimePicker.java b/doc/标注/210340062_刘瑞轩/DateTimePicker.java new file mode 100644 index 0000000..9c4aca9 --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/DateTimePicker.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import java.text.DateFormatSymbols; +import java.util.Calendar; + +import net.micode.notes.R; + + +import android.content.Context; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.NumberPicker; +/* +Author:刘瑞轩 +Data:2023/4/12 +*/ +public class DateTimePicker extends FrameLayout { + + private static final boolean DEFAULT_ENABLE_STATE = true; + + private static final int HOURS_IN_HALF_DAY = 12; + private static final int HOURS_IN_ALL_DAY = 24; + private static final int DAYS_IN_ALL_WEEK = 7; + private static final int DATE_SPINNER_MIN_VAL = 0; + private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; + private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; + private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; + private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; + private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12; + private static final int MINUT_SPINNER_MIN_VAL = 0; + 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; + private Calendar mDate; + + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + + private boolean mIsAm; + + private boolean mIs24HourView; + + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + + private boolean mInitialising; + + private OnDateTimeChangedListener mOnDateTimeChangedListener; + + private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) {//更改日期 + mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal); + updateDateControl(); + onDateTimeChanged(); + } + };//当用户更改值之后改变便签的修改日期 + + private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) {//各自的参数代表被改变值得NumberPicker对象,旧值,新值 + boolean isDateChanged = false;//用户是否改变值 + Calendar cal = Calendar.getInstance();//获取当前的时间 + if (!mIs24HourView) {//不是用的24小时制度 + if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) {//是下午旧值是11,新值是12,代表到了下一天 + cal.setTimeInMillis(mDate.getTimeInMillis());//将修改时间修改为当前的时间 + cal.add(Calendar.DAY_OF_YEAR, 1);//过了一天,将日期加1 + isDateChanged = true; + } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {//如果当前是上午,并且 + //旧值是12,新值是11,那么就代表回到了上一天 + cal.setTimeInMillis(mDate.getTimeInMillis());//获取当前的时间 + cal.add(Calendar.DAY_OF_YEAR, -1);//日期减一 + isDateChanged = true; + } + if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || + oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) {//只要之前是11,现在是12,或者是之前是12,现在是11,AM和PM都会发生改变,取反 + mIsAm = !mIsAm; + updateAmPmControl();//更新限制 + } + } else { + if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) {//如果当前时间比之前时间早,代表已经过了一天了 + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) {//如果当前时间比之前时间晚代表是同一天 + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + } + int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); + mDate.set(Calendar.HOUR_OF_DAY, newHour); + onDateTimeChanged(); + if (isDateChanged) { + setCurrentYear(cal.get(Calendar.YEAR)); + setCurrentMonth(cal.get(Calendar.MONTH)); + setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); + } + } + }; + + private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) {//通过调整分钟来调整时间 + int minValue = mMinuteSpinner.getMinValue();//获取最小值 + int maxValue = mMinuteSpinner.getMaxValue();//获取最大值 + int offset = 0;//判断是否跨越边界 + if (oldVal == maxValue && newVal == minValue) {//如果新的是最小的,旧的值是最大的那么小时加1 + offset += 1; + } else if (oldVal == minValue && newVal == maxValue) {//如果新的是最大的值,旧的是最小值,那么代表我们是往上调整的,那么小时减小 + offset -= 1; + } + if (offset != 0) {//如果跨越边界了 + mDate.add(Calendar.HOUR_OF_DAY, offset);//日期进行相应的改变 + mHourSpinner.setValue(getCurrentHour());//获取当前的时间 + updateDateControl();//更新限制 + int newHour = getCurrentHourOfDay();//更新小时 + if (newHour >= HOURS_IN_HALF_DAY) {//判断是上午还是下午 + mIsAm = false;//不是上午 + updateAmPmControl();//更新限制 + } else { + mIsAm = true;//是上午 + updateAmPmControl(); + } + } + mDate.set(Calendar.MINUTE, newVal);//设置成新的值 + onDateTimeChanged();//更改小时 + } + }; + + private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() {//更新上午还是下午 + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mIsAm = !mIsAm;//上午变成下午,下午变成上午 + if (mIsAm) { + mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY);//如果是下午变成上午,那么需要减去12小时 + } else { + mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY);//如果是上午变成下午,那么需要加上12小时 + } + updateAmPmControl(); + onDateTimeChanged(); + } + }; + + public interface OnDateTimeChangedListener { + void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute); + } + + public DateTimePicker(Context context) { + this(context, System.currentTimeMillis()); + } + + public DateTimePicker(Context context, long date) { + this(context, date, DateFormat.is24HourFormat(context)); + } + + 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);//将小时、分钟和日期、在上午还是下午填充到这个文件中 + + mDateSpinner = (NumberPicker) findViewById(R.id.date); + mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL);//选择当前月份的最小的那一天 + mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL);//选择当前月份最大的那一天 + mDateSpinner.setOnValueChangedListener(mOnDateChangedListener);//设置日期监听器 + + mHourSpinner = (NumberPicker) findViewById(R.id.hour);//找到小时 + mHourSpinner.setOnValueChangedListener(mOnHourChangedListener);//设置小时监听器 + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL);//设置分钟最小值 + mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL);//设置分钟最大值 + mMinuteSpinner.setOnLongPressUpdateInterval(100);//设置按下更新的间隔是100ms + mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener);//设置分钟监听器 + + String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings();//获取当前设备上的AM/PM字符串数组,第一个元素为AM,第二个元素为PM + mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); + mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); + mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); + mAmPmSpinner.setDisplayedValues(stringsForAmPm); + mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener);//设置上午下午监听器 + + // update controls to initial state + updateDateControl();//更新限制 + updateHourControl(); + updateAmPmControl(); + + set24HourView(is24HourView); + + // set to current time + setCurrentDate(date); + + setEnabled(isEnabled()); + + // set the content descriptions + mInitialising = false; + } + + @Override + public void setEnabled(boolean enabled) {//用来设置组件显示出来 + if (mIsEnabled == enabled) {//如果相同则不用修改 + return; + } + super.setEnabled(enabled);//设置可行 + mDateSpinner.setEnabled(enabled);//设置日期监听器可行 + mMinuteSpinner.setEnabled(enabled);//设置分钟监听器可行 + mHourSpinner.setEnabled(enabled);//设置小时监听器可行 + mAmPmSpinner.setEnabled(enabled);//设置上午下午监听器可行 + mIsEnabled = enabled;//设置为已经更新为可用 + } + + @Override + public boolean isEnabled() { + return mIsEnabled; + }//返回是否可用 + + /** + * Get the current date in millis + * + * @return the current date in millis + */ + public long getCurrentDateInTimeMillis() { + return mDate.getTimeInMillis(); + }//获取当前的日期 + + /** + * Set the current date + * + * @param date The current date in millis + */ + public void setCurrentDate(long date) { + Calendar cal = Calendar.getInstance(); + 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)); + } + + /** + * Set the current date + * + * @param year The current year + * @param month The current month + * @param dayOfMonth The current dayOfMonth + * @param hourOfDay The current hourOfDay + * @param minute The current minute + */ + public void setCurrentDate(int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + setCurrentYear(year); + setCurrentMonth(month); + setCurrentDay(dayOfMonth); + setCurrentHour(hourOfDay); + setCurrentMinute(minute); + }//设置时间 + + /** + * Get current year + * + * @return The current year + */ + public int getCurrentYear() { + return mDate.get(Calendar.YEAR); + }//返回当前年 + + /** + * Set current year + * + * @param year The current year + */ + public void setCurrentYear(int year) { + if (!mInitialising && year == getCurrentYear()) {//如果已经初始化并且年份和当前的相同 + return; + } + mDate.set(Calendar.YEAR, year);//更新 + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current month in the year + * + * @return The current month in the year + */ + public int getCurrentMonth() { + return mDate.get(Calendar.MONTH); + }//获得月份 + + /** + * Set current month in the year + * + * @param month The month in the year + */ + public void setCurrentMonth(int month) { + if (!mInitialising && month == getCurrentMonth()) { + return; + } + mDate.set(Calendar.MONTH, month);//更新月份 + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current day of the month + * + * @return The day of the month + */ + public int getCurrentDay() { + return mDate.get(Calendar.DAY_OF_MONTH); + }//获取月份 + + /** + * Set current day of the month + * + * @param dayOfMonth The day of the month + */ + public void setCurrentDay(int dayOfMonth) {//更新天 + if (!mInitialising && dayOfMonth == getCurrentDay()) { + return; + } + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current hour in 24 hour mode, in the range (0~23) + * @return The current hour in 24 hour mode + */ + public int getCurrentHourOfDay() { + return mDate.get(Calendar.HOUR_OF_DAY); + }//获取当前的小时 + + private int getCurrentHour() { + if (mIs24HourView){//如果是24小时 + return getCurrentHourOfDay(); + } else { + int hour = getCurrentHourOfDay();//获取小时 + if (hour > HOURS_IN_HALF_DAY) {//如果大于12应该减去12 + return hour - HOURS_IN_HALF_DAY; + } else { + return hour == 0 ? HOURS_IN_HALF_DAY : hour;//否则就和当前的相同 + } + } + } + + /** + * Set current hour in 24 hour mode, in the range (0~23) + * + * @param hourOfDay + */ + public void setCurrentHour(int hourOfDay) { + if (!mInitialising && hourOfDay == getCurrentHourOfDay()) {//如果已经初始化并且和现在的小时一样就不用管 + return; + } + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);//设置小时 + if (!mIs24HourView) {//如果不是24小时制度 + if (hourOfDay >= HOURS_IN_HALF_DAY) { + mIsAm = false;//代表是下午 + if (hourOfDay > HOURS_IN_HALF_DAY) {//如果大于12 + hourOfDay -= HOURS_IN_HALF_DAY; + } + } else { + mIsAm = true;//时上午 + if (hourOfDay == 0) { + hourOfDay = HOURS_IN_HALF_DAY;//代表到达了最后 + } + } + updateAmPmControl(); + } + mHourSpinner.setValue(hourOfDay);//更新时间 + onDateTimeChanged(); + } + + /** + * Get currentMinute + * + * @return The Current Minute + */ + public int getCurrentMinute() { + return mDate.get(Calendar.MINUTE); + } + + /** + * Set current minute + */ + public void setCurrentMinute(int minute) { + if (!mInitialising && minute == getCurrentMinute()) { + return; + } + mMinuteSpinner.setValue(minute);//设置时间 + mDate.set(Calendar.MINUTE, minute);//设置分钟 + onDateTimeChanged(); + } + + /** + * @return true if this is in 24 hour view else false. + */ + public boolean is24HourView () { + return mIs24HourView; + }//返回是否是24小时制 + + /** + * Set whether in 24 hour or AM/PM mode. + * + * @param is24HourView True for 24 hour mode. False for AM/PM mode. + */ + public void set24HourView(boolean is24HourView) { + if (mIs24HourView == is24HourView) {//如果是24小时制,就无需更改 + return; + } + mIs24HourView = is24HourView;//更改为24小时制度 + mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE);//讲对应的界面显示出来 + int hour = getCurrentHourOfDay();//获取当前的小时 + updateHourControl(); + setCurrentHour(hour);//更新时间 + updateAmPmControl(); + } + + private void updateDateControl() { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1);//按照一周来显示,以当前这一天为中心进行扩展 + mDateSpinner.setDisplayedValues(null);//清空mDateSpinner显示的数据 + for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) { + cal.add(Calendar.DAY_OF_YEAR, 1);//将当前的cal的最后一个数据加1 + mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal);//格式化日期 + } + mDateSpinner.setDisplayedValues(mDateDisplayValues);//把加入的数据显示出来 + mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2);//将选择器的初始位置设置为中心位置 + mDateSpinner.invalidate();//使选择器无效,从而更新显示值 + } + + private void updateAmPmControl() { + if (mIs24HourView) {//如果是24小时制 + mAmPmSpinner.setVisibility(View.GONE);//上午下午不显示 + } else { + int index = mIsAm ? Calendar.AM : Calendar.PM;//显示是上午还是下午 + mAmPmSpinner.setValue(index);//显示对应的内容 + mAmPmSpinner.setVisibility(View.VISIBLE);//可见 + } + } + + private void updateHourControl() { + if (mIs24HourView) {//如果是24小时制 + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW);//显示24小时最小值 + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW);//显示24小时最大值 + } else { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW);//显示12小时最小值 + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW);//显示12小时最大值 + } + } + + /** + * Set the callback that indicates the 'Set' button has been pressed. + * @param callback the callback, if null will do nothing + */ + public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { + mOnDateTimeChangedListener = callback; + } + + private void onDateTimeChanged() {//更改便签时间 + if (mOnDateTimeChangedListener != null) { + mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), + getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); + } + } +} diff --git a/doc/标注/210340062_刘瑞轩/DateTimePickerDialog.java b/doc/标注/210340062_刘瑞轩/DateTimePickerDialog.java new file mode 100644 index 0000000..46381ad --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/DateTimePickerDialog.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import java.util.Calendar; + +import net.micode.notes.R; +import net.micode.notes.ui.DateTimePicker; +import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.text.format.DateFormat; +import android.text.format.DateUtils; + +public class DateTimePickerDialog extends AlertDialog implements OnClickListener { + + private Calendar mDate = Calendar.getInstance(); + private boolean mIs24HourView; + private OnDateTimeSetListener mOnDateTimeSetListener; + private DateTimePicker mDateTimePicker; + + 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) { + mDate.set(Calendar.YEAR, year); + mDate.set(Calendar.MONTH, month); + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + mDate.set(Calendar.MINUTE, minute); + updateTitle(mDate.getTimeInMillis());//更新题目 + }//根据对话框参数定位到对应的日期 + }); + mDate.setTimeInMillis(date);//将其转化为时间戳 + mDate.set(Calendar.SECOND, 0);//设置s为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()));//根据24小时制或者是12小时进行设置 + updateTitle(mDate.getTimeInMillis());//更新题目 + } + + public void set24HourView(boolean is24HourView) { + mIs24HourView = is24HourView; + }//设置为24小时页面 + + public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { + mOnDateTimeSetListener = callBack; + } + + private void updateTitle(long date) { + int flag = + DateUtils.FORMAT_SHOW_YEAR |//显示年日时间 + DateUtils.FORMAT_SHOW_DATE | + DateUtils.FORMAT_SHOW_TIME; + flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;//是否按照24小时制显示 + setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));//设置对应的题目 + } + + public void onClick(DialogInterface arg0, int arg1) { + if (mOnDateTimeSetListener != null) { + mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); + } + } + +} \ No newline at end of file diff --git a/doc/标注/210340062_刘瑞轩/DropdownMenu.java b/doc/标注/210340062_刘瑞轩/DropdownMenu.java new file mode 100644 index 0000000..8e26ccc --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/DropdownMenu.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.content.Context; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.PopupMenu; +import android.widget.PopupMenu.OnMenuItemClickListener; + +import net.micode.notes.R; + +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);//设置背景资源,改变对应的背景图片 + mPopupMenu = new PopupMenu(context, mButton);//显示菜单 + mMenu = mPopupMenu.getMenu(); + mPopupMenu.getMenuInflater().inflate(menuId, mMenu);//填充菜单 + mButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPopupMenu.show(); + }//显示对应的菜单 + }); + } + + public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { + if (mPopupMenu != null) { + mPopupMenu.setOnMenuItemClickListener(listener); + } + } + + public MenuItem findItem(int id) { + return mMenu.findItem(id); + } + + public void setTitle(CharSequence title) { + mButton.setText(title); + } +} diff --git a/doc/标注/210340062_刘瑞轩/FoldersListAdapter.java b/doc/标注/210340062_刘瑞轩/FoldersListAdapter.java new file mode 100644 index 0000000..cb380cc --- /dev/null +++ b/doc/标注/210340062_刘瑞轩/FoldersListAdapter.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.content.Context; +import android.database.Cursor; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; + + +public class FoldersListAdapter extends CursorAdapter { + //CursorAdapter是Cursor和ListView的接口 + //FoldersListAdapter继承了CursorAdapter的类 + //主要作用是便签数据库和用户的交互 + //这里就是用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; + + public FoldersListAdapter(Context context, Cursor c) { + super(context, c); + // TODO Auto-generated constructor stub + }//数据库操作 + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return new FolderListItem(context); + }//创建一个文件夹,对于各文件夹中子标签的初始化 + + @Override + public void bindView(View view, Context context, Cursor cursor) { + if (view instanceof FolderListItem) {//FolderListItem是显示子图,如果view是该类的实例,那么就去cursor中获取文件夹的名称,并将其绑定到FolderListItem上 + String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context + .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + ((FolderListItem) view).bind(folderName); + } + }//将各个布局文件绑定起来 + + 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);//根据布局文件的名字等信息将其找出来 + } + + public void bind(String name) { + mName.setText(name); + } + } + +}