代码修改,上传xml文件,增加置顶功能 #8

Merged
psq5hzxpo merged 2 commits from luhaozhe_branch into master 1 month ago

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Notesmaster"
tools:targetApi="31">
<activity
android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustPan"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter >>
<intent-filter >
<action android:name="android.intent.action.INSERT_OR_EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<provider
android:name="net.micode.notes.data.NotesProvider"
android:authorities="micode_notes"
android:multiprocess="true" />
<receiver
android:name=".widget.NoteWidgetProvider_2x"
android:label="@string/app_widget2x2"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_2x_info" />
</receiver>
<receiver
android:name=".widget.NoteWidgetProvider_4x"
android:label="@string/app_widget4x4"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_4x_info" />
</receiver>
<receiver android:name=".ui.AlarmInitReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name="net.micode.notes.ui.AlarmReceiver"
android:process=":remote" >
</receiver>
<activity
android:name=".ui.AlarmAlertActivity"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar" >
</activity>
<activity
android:name="net.micode.notes.ui.NotesPreferenceActivity"
android:label="@string/preferences_title"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Holo.Light" >
</activity>
<service
android:name="net.micode.notes.gtask.remote.GTaskSyncService"
android:exported="false" >
</service>
<meta-data
android:name="android.app.default_searchable"
android:value=".ui.NoteEditActivity" />
<!-- <activity-->
<!-- android:name=".MainActivity"-->
<!-- android:exported="true">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
<!-- </activity>-->
</application>
</manifest>

@ -0,0 +1,24 @@
package net.micode.notes;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}

@ -28,12 +28,12 @@ public class Notes {
* ContentProvider便
*/
public static final String AUTHORITY = "micode_notes";
/**
*
*/
public static final String TAG = "Notes";
/**
* 便
* - TYPE_NOTE便
@ -211,6 +211,18 @@ public class Notes {
* <P> : INTEGER (long) </P>
*/
public static final String VERSION = "version";
/**
* 便
* <P> : INTEGER (0: , 1: ) </P>
*/
public static final String IS_PINNED = "is_pinned";
/**
* 便
* <P> : INTEGER (long) </P>
*/
public static final String PIN_PRIORITY = "pin_priority";
}
/**

@ -34,25 +34,25 @@ import net.micode.notes.data.Notes.NoteColumns;
public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 数据库名称
private static final String DB_NAME = "note.db";
// 数据库版本号
private static final int DB_VERSION = 4;
private static final int DB_VERSION = 5;
// 数据库表名定义
public interface TABLE {
// 笔记表:存储笔记和文件夹的基本信息
public static final String NOTE = "note";
// 数据表:存储笔记的详细内容,支持多种类型的笔记数据
public static final String DATA = "data";
}
// 日志标签
private static final String TAG = "NotesDatabaseHelper";
// 单例实例,确保整个应用只有一个数据库帮助类实例
private static NotesDatabaseHelper mInstance;
// 创建笔记表的SQL语句
// 笔记表存储笔记和文件夹的基本信息,包括:
// - ID唯一标识符
@ -73,25 +73,27 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
// - GTASK_IDGoogle任务ID
// - VERSION版本号
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.IS_PINNED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.PIN_PRIORITY + " INTEGER NOT NULL DEFAULT 0" +
")";
// 创建数据表的SQL语句
// 数据表存储笔记的详细内容,支持多种类型的笔记数据,包括:
@ -103,147 +105,147 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
// - CONTENT数据内容
// - DATA1, DATA2, DATA3, DATA4, DATA5扩展字段根据不同数据类型存储不同信息
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
/**
*
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
*
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
/**
*
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
*
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
/**
*
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
*
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
*
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
/**
*
*/
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
/**
*
*/
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
/**
*
*/
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
@ -412,6 +414,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
oldVersion++;
}
// 从v4升级到v5
if (oldVersion == 4) {
upgradeToV5(db);
oldVersion++;
}
// 如果需要,重新创建触发器
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
@ -469,4 +477,18 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
/**
* v4v5
* 便
* @param db SQLite
*/
private void upgradeToV5(SQLiteDatabase db) {
// 为笔记表添加置顶状态字段
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.IS_PINNED
+ " INTEGER NOT NULL DEFAULT 0");
// 为笔记表添加置顶优先级字段
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.PIN_PRIORITY
+ " INTEGER NOT NULL DEFAULT 0");
}
}

@ -29,53 +29,22 @@ import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
/**
* Google Task
* AsyncTask Google Task
*/
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
/**
* Google Task
*/
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
/**
*
*
*/
public interface OnCompleteListener {
/**
*
*/
void onComplete();
}
/**
*
*/
private Context mContext;
/**
*
*/
private NotificationManager mNotifiManager;
/**
* Google Task
*/
private GTaskManager mTaskManager;
/**
*
*/
private OnCompleteListener mOnCompleteListener;
/**
*
* @param context
* @param listener
*/
public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context;
mOnCompleteListener = listener;
@ -84,108 +53,84 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
mTaskManager = GTaskManager.getInstance();
}
/**
*
*/
public void cancelSync() {
mTaskManager.cancelSync();
}
/**
*
* @param message
*/
public void publishProgess(String message) {
publishProgress(new String[] {
message
});
}
/**
*
* @param tickerId ID
* @param content
*/
private void showNotification(int tickerId, String content) {
// 创建通知实例,设置图标、标题和时间
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
notification.defaults = Notification.DEFAULT_LIGHTS; // 使用默认灯光效果
notification.flags = Notification.FLAG_AUTO_CANCEL; // 点击后自动取消
// 根据通知类型设置不同的跳转意图
PendingIntent pendingIntent;
if (tickerId != R.string.ticker_success) {
// 同步失败时跳转到设置页面
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0);
} else {
// 同步成功时跳转到笔记列表页面
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
}
// 设置通知的详细信息并显示
notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
pendingIntent);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
}
/**
*
* @param unused
* @return
*/
// private void showNotification(int tickerId, String content) {
//Notification notification = new Notification(R.drawable.notification, mContext
// .getString(tickerId), System.currentTimeMillis());
//notification.defaults = Notification.DEFAULT_LIGHTS;
//notification.flags = Notification.FLAG_AUTO_CANCEL;
//PendingIntent pendingIntent;
//if (tickerId != R.string.ticker_success) {
// pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
// NotesPreferenceActivity.class), 0);
//notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
// pendingIntent);
// } else {
// pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
// NotesListActivity.class), 0);
// notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
// pendingIntent);
//}
//mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
// }
private void showNotification(int tickerId, String content) {
PendingIntent pendingIntent;
if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), PendingIntent.FLAG_IMMUTABLE);
} else {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), PendingIntent.FLAG_IMMUTABLE);
}
Notification.Builder builder = new Notification.Builder(mContext)
.setAutoCancel(true)
.setContentTitle(mContext.getString(R.string.app_name))
.setContentText(content)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setOngoing(true);
Notification notification=builder.getNotification();
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
}
@Override
protected Integer doInBackground(Void... unused) {
// 发布登录进度
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext)));
// 调用任务管理器执行同步
return mTaskManager.sync(mContext, this);
}
/**
*
* @param progress
*/
@Override
protected void onProgressUpdate(String... progress) {
// 显示同步中通知
showNotification(R.string.ticker_syncing, progress[0]);
// 如果上下文是同步服务,则发送广播通知进度
if (mContext instanceof GTaskSyncService) {
((GTaskSyncService) mContext).sendBroadcast(progress[0]);
}
}
/**
*
* @param result
*/
@Override
protected void onPostExecute(Integer result) {
// 根据同步结果显示不同的通知
if (result == GTaskManager.STATE_SUCCESS) {
// 同步成功
showNotification(R.string.ticker_success, mContext.getString(
R.string.success_sync_account, mTaskManager.getSyncAccount()));
// 更新最后同步时间
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis());
} else if (result == GTaskManager.STATE_NETWORK_ERROR) {
// 网络错误
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
} else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
// 内部错误
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal));
} else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
// 同步取消
showNotification(R.string.ticker_cancel, mContext
.getString(R.string.error_sync_cancelled));
}
// 如果设置了完成监听器,则在新线程中调用
if (mOnCompleteListener != null) {
new Thread(new Runnable() {

@ -702,55 +702,41 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
@Override
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 id = item.getItemId();
if (id == R.id.menu_new_note) {
createNewNote();
} else if (id == 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 (id == R.id.menu_font_size) {
mFontSizeSelector.setVisibility(View.VISIBLE);
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
} else if (id == R.id.menu_list_mode) {
mWorkingNote.setCheckListMode(mWorkingNote.getCheckListMode() == 0 ?
TextNote.MODE_CHECK_LIST : 0);
} else if (id == R.id.menu_share) {
getWorkingText();
sendTo(this, mWorkingNote.getContent());
} else if (id == R.id.menu_send_to_desktop) {
sendToDesktop();
} else if (id == R.id.menu_alert) {
setReminder();
} else if (id == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false);
} else {
// 默认情况,什么也不做
}
return true;
}

@ -34,18 +34,20 @@ public class NoteItemData {
*
*/
static final String [] PROJECTION = new String [] {
NoteColumns.ID,
NoteColumns.ALERTED_DATE,
NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE,
NoteColumns.HAS_ATTACHMENT,
NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT,
NoteColumns.PARENT_ID,
NoteColumns.SNIPPET,
NoteColumns.TYPE,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
NoteColumns.ID,
NoteColumns.ALERTED_DATE,
NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE,
NoteColumns.HAS_ATTACHMENT,
NoteColumns.IS_PINNED,
NoteColumns.MODIFIED_DATE,
NoteColumns.NOTES_COUNT,
NoteColumns.PARENT_ID,
NoteColumns.PIN_PRIORITY,
NoteColumns.SNIPPET,
NoteColumns.TYPE,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
};
/**
@ -68,34 +70,42 @@ public class NoteItemData {
*
*/
private static final int HAS_ATTACHMENT_COLUMN = 4;
/**
*
*/
private static final int IS_PINNED_COLUMN = 5;
/**
*
*/
private static final int MODIFIED_DATE_COLUMN = 5;
private static final int MODIFIED_DATE_COLUMN = 6;
/**
*
*/
private static final int NOTES_COUNT_COLUMN = 6;
private static final int NOTES_COUNT_COLUMN = 7;
/**
* ID
*/
private static final int PARENT_ID_COLUMN = 7;
private static final int PARENT_ID_COLUMN = 8;
/**
*
*/
private static final int PIN_PRIORITY_COLUMN = 9;
/**
*
*/
private static final int SNIPPET_COLUMN = 8;
private static final int SNIPPET_COLUMN = 10;
/**
*
*/
private static final int TYPE_COLUMN = 9;
private static final int TYPE_COLUMN = 11;
/**
* ID
*/
private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_ID_COLUMN = 12;
/**
*
*/
private static final int WIDGET_TYPE_COLUMN = 11;
private static final int WIDGET_TYPE_COLUMN = 13;
/**
* ID
@ -145,6 +155,14 @@ public class NoteItemData {
*
*/
private int mWidgetType;
/**
*
*/
private boolean mIsPinned;
/**
*
*/
private long mPinPriority;
/**
*
*/
@ -186,9 +204,11 @@ public class NoteItemData {
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false;
mIsPinned = (cursor.getInt(IS_PINNED_COLUMN) > 0) ? true : false;
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
mParentId = cursor.getLong(PARENT_ID_COLUMN);
mPinPriority = cursor.getLong(PIN_PRIORITY_COLUMN);
mSnippet = cursor.getString(SNIPPET_COLUMN);
// 移除勾选标记
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
@ -385,6 +405,22 @@ public class NoteItemData {
return mWidgetType;
}
/**
*
* @return
*/
public boolean isPinned() {
return mIsPinned;
}
/**
*
* @return
*/
public long getPinPriority() {
return mPinPriority;
}
/**
* ID
* @return ID

@ -78,186 +78,145 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
/**
* 便
* 便便
*
*/
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
/**
*
*/
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0; // 文件夹便签列表查询令牌
private static final int FOLDER_LIST_QUERY_TOKEN = 1; // 文件夹列表查询令牌
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
/**
*
*/
private static final int MENU_FOLDER_DELETE = 0; // 删除文件夹
private static final int MENU_FOLDER_VIEW = 1; // 查看文件夹
private static final int MENU_FOLDER_CHANGE_NAME = 2; // 修改文件夹名称
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
/**
* SharedPreferences
*/
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction"; // 是否添加过介绍便签
private static final int MENU_FOLDER_DELETE = 0;
private static final int MENU_FOLDER_VIEW = 1;
private static final int MENU_FOLDER_CHANGE_NAME = 2;
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction";
/**
*
* - NOTE_LIST便
* - SUB_FOLDER
* - CALL_RECORD_FOLDER
*/
private enum ListEditState {
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
};
/**
*
*/
private ListEditState mState;
/**
*
*/
private BackgroundQueryHandler mBackgroundQueryHandler;
/**
* 便便
*/
private NotesListAdapter mNotesListAdapter;
/**
* 便
*/
private ListView mNotesListView;
/**
* 便
*/
private Button mAddNewNote;
/**
*
*/
private boolean mDispatch;
/**
* Y
*/
private int mOriginY;
/**
* Y
*/
private int mDispatchY;
/**
*
*/
private TextView mTitleBar;
/**
* ID
*/
private long mCurrentFolderId;
/**
* ContentProvider
*/
private ContentResolver mContentResolver;
/**
*
*/
private ModeCallback mModeCallBack;
/**
*
*/
private static final String TAG = "NotesListActivity";
/**
* 便
*/
public static final int NOTES_LISTVIEW_SCROLL_RATE = 30;
/**
* 便
*/
private NoteItemData mFocusNoteDataItem;
/**
*
*/
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
/**
*
* 便
*/
private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>"
+ Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ NoteColumns.NOTES_COUNT + ">0)";
/**
*
*/
private final static int REQUEST_CODE_OPEN_NODE = 102; // 打开便签请求码
private final static int REQUEST_CODE_NEW_NODE = 103; // 新建便签请求码
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
/**
*
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_list); // 设置布局
initResources(); // 初始化资源
setContentView(R.layout.note_list);
initResources();
/**
* 使便
* Insert an introduction when user firstly use this application
*/
setAppInfoFromRawRes();
}
/**
*
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 如果是打开或新建便签的请求,并且返回成功,则刷新便签列表
if (resultCode == RESULT_OK
&& (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
mNotesListAdapter.changeCursor(null); // 清空适配器游标,触发重新查询
mNotesListAdapter.changeCursor(null);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
/**
* 便
* 便
*/
private void togglePinStatus() {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... unused) {
HashSet<Long> ids = mNotesListAdapter.getSelectedItemIds();
for (Long id : ids) {
// 查询当前便签的置顶状态
Cursor cursor = mContentResolver.query(Notes.CONTENT_NOTE_URI,
new String[] { NoteColumns.IS_PINNED },
NoteColumns.ID + "=?",
new String[] { String.valueOf(id) },
null);
if (cursor != null && cursor.moveToFirst()) {
boolean isPinned = cursor.getInt(0) > 0;
cursor.close();
// 更新置顶状态
ContentValues values = new ContentValues();
values.put(NoteColumns.IS_PINNED, isPinned ? 0 : 1);
values.put(NoteColumns.PIN_PRIORITY, isPinned ? 0 : System.currentTimeMillis());
values.put(NoteColumns.LOCAL_MODIFIED, 1);
values.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
mContentResolver.update(Notes.CONTENT_NOTE_URI, values,
NoteColumns.ID + "=?",
new String[] { String.valueOf(id) });
} else if (cursor != null) {
cursor.close();
}
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
startAsyncNotesListQuery();
mModeCallBack.finishActionMode();
}
}
}.execute();
}
private void setAppInfoFromRawRes() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
// 如果还没有添加过介绍便签,则创建
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
StringBuilder sb = new StringBuilder();
InputStream in = null;
try {
in = getResources().openRawResource(R.raw.introduction); // 打开介绍资源文件
in = getResources().openRawResource(R.raw.introduction);
if (in != null) {
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
char [] buf = new char[1024];
int len = 0;
while ((len = br.read(buf)) > 0) {
sb.append(buf, 0, len); // 读取文件内容
sb.append(buf, 0, len);
}
} else {
Log.e(TAG, "Read introduction file error");
@ -269,7 +228,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
} finally {
if(in != null) {
try {
in.close(); // 关闭输入流
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -277,13 +236,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
// 创建介绍便签
WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER,
AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE,
ResourceParser.RED);
note.setWorkingText(sb.toString()); // 设置便签内容
note.setWorkingText(sb.toString());
if (note.saveNote()) {
sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit(); // 标记已添加介绍便签
sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit();
} else {
Log.e(TAG, "Save introduction note error");
return;
@ -291,45 +249,34 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
*/
@Override
protected void onStart() {
super.onStart();
startAsyncNotesListQuery(); // 异步查询便签列表
startAsyncNotesListQuery();
}
/**
*
*/
private void initResources() {
mContentResolver = this.getContentResolver(); // 获取内容解析器
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver()); // 创建后台查询处理器
mCurrentFolderId = Notes.ID_ROOT_FOLDER; // 设置当前文件夹为根文件夹
mNotesListView = (ListView) findViewById(R.id.notes_list); // 获取便签列表视图
// 添加列表底部视图
mContentResolver = this.getContentResolver();
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
mNotesListView = (ListView) findViewById(R.id.notes_list);
mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null),
null, false);
mNotesListView.setOnItemClickListener(new OnListItemClickListener()); // 设置列表项点击监听器
mNotesListView.setOnItemLongClickListener(this); // 设置列表项长按监听器
mNotesListAdapter = new NotesListAdapter(this); // 创建便签列表适配器
mNotesListView.setAdapter(mNotesListAdapter); // 设置适配器
mAddNewNote = (Button) findViewById(R.id.btn_new_note); // 获取新建便签按钮
mAddNewNote.setOnClickListener(this); // 设置点击监听器
mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener()); // 设置触摸监听器
mDispatch = false; // 初始化触摸分发标志
mDispatchY = 0; // 初始化分发Y坐标
mOriginY = 0; // 初始化原始Y坐标
mTitleBar = (TextView) findViewById(R.id.tv_title_bar); // 获取标题栏
mState = ListEditState.NOTE_LIST; // 初始化状态为便签列表状态
mModeCallBack = new ModeCallback(); // 创建多选模式回调
mNotesListView.setOnItemClickListener(new OnListItemClickListener());
mNotesListView.setOnItemLongClickListener(this);
mNotesListAdapter = new NotesListAdapter(this);
mNotesListView.setAdapter(mNotesListAdapter);
mAddNewNote = (Button) findViewById(R.id.btn_new_note);
mAddNewNote.setOnClickListener(this);
mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
mDispatch = false;
mDispatchY = 0;
mOriginY = 0;
mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
mState = ListEditState.NOTE_LIST;
mModeCallBack = new ModeCallback();
}
/**
*
* 便
*/
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
@ -346,6 +293,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mMoveMenu.setVisible(true);
mMoveMenu.setOnMenuItemClickListener(this);
}
// 添加置顶/取消置顶菜单项
MenuItem pinMenu = menu.findItem(R.id.pin);
if (pinMenu != null) {
if (mFocusNoteDataItem.isPinned()) {
pinMenu.setTitle(R.string.menu_unpin);
} else {
pinMenu.setTitle(R.string.menu_pin);
}
pinMenu.setOnMenuItemClickListener(this);
}
mActionMode = mode;
mNotesListAdapter.setChoiceMode(true);
mNotesListView.setLongClickable(false);
@ -406,7 +363,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
boolean checked) {
mNotesListAdapter.setCheckedItem(position, checked);
updateMenu();
}
@ -418,37 +375,32 @@ 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;
if (item.getItemId() == 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 (item.getItemId() == R.id.move) {
startQueryDestinationFolders();
} else if (item.getItemId() == R.id.pin) {
togglePinStatus();
} else {
return false;
}
return true;
}
}
/**
* 便
* 便
*/
private class NewNoteOnTouchListener implements OnTouchListener {
public boolean onTouch(View v, MotionEvent event) {
@ -460,17 +412,20 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
int start = screenHeight - newNoteViewHeight;
int eventY = start + (int) event.getY();
/**
*
* Minus TitleBar's height
*/
if (mState == ListEditState.SUB_FOLDER) {
eventY -= mTitleBar.getHeight();
start -= mTitleBar.getHeight();
}
/**
* HACKME:"新建便签"
* "新建便签"y=-0.12x+94线
* "新建便签"94
* UI
* HACKME:When click the transparent part of "New Note" button, dispatch
* the event to the list view behind this button. The transparent part of
* "New Note" button could be expressed by formula y=-0.12x+94Unit:pixel
* and the line top of the button. The coordinate based on left of the "New
* Note" button. The 94 represents maximum height of the transparent part.
* Notice that, if the background of the button changes, the formula should
* also change. This is very bad, just for the UI designer's strong requirement.
*/
if (event.getY() < (event.getX() * (-0.12) + 94)) {
View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
@ -508,48 +463,30 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
/**
* 便
*/
private void startAsyncNotesListQuery() {
// 根据当前文件夹ID选择查询条件
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
// 开始异步查询
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
String.valueOf(mCurrentFolderId)
}, NoteColumns.IS_PINNED + " DESC," + NoteColumns.PIN_PRIORITY + " DESC,"
+ NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
/**
*
*
*/
private final class BackgroundQueryHandler extends AsyncQueryHandler {
/**
*
* @param contentResolver
*/
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
/**
*
* @param token
* @param cookie
* @param cursor
*/
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
case FOLDER_NOTE_LIST_QUERY_TOKEN: // 文件夹便签列表查询完成
mNotesListAdapter.changeCursor(cursor); // 更新适配器游标
case FOLDER_NOTE_LIST_QUERY_TOKEN:
mNotesListAdapter.changeCursor(cursor);
break;
case FOLDER_LIST_QUERY_TOKEN: // 文件夹列表查询完成
case FOLDER_LIST_QUERY_TOKEN:
if (cursor != null && cursor.getCount() > 0) {
showFolderListMenu(cursor); // 显示文件夹列表菜单
showFolderListMenu(cursor);
} else {
Log.e(TAG, "Query folder failed");
}
@ -560,64 +497,48 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
* @param cursor
*/
private void showFolderListMenu(Cursor cursor) {
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(R.string.menu_title_select_folder); // 设置对话框标题
final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor); // 创建文件夹列表适配器
builder.setTitle(R.string.menu_title_select_folder);
final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 批量移动选中的便签到目标文件夹
DataUtils.batchMoveToFolder(mContentResolver,
mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
// 显示移动成功提示
Toast.makeText(
NotesListActivity.this,
getString(R.string.format_move_notes_to_folder,
mNotesListAdapter.getSelectedCount(),
adapter.getFolderName(NotesListActivity.this, which)),
Toast.LENGTH_SHORT).show();
mModeCallBack.finishActionMode(); // 结束多选模式
mModeCallBack.finishActionMode();
}
});
builder.show(); // 显示对话框
builder.show();
}
/**
* 便
*/
private void createNewNote() {
Intent intent = new Intent(this, NoteEditActivity.class); // 创建跳转到编辑活动的意图
intent.setAction(Intent.ACTION_INSERT_OR_EDIT); // 设置动作
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId); // 设置文件夹ID
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE); // 启动活动
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
}
/**
* 便
*/
private void batchDelete() {
new AsyncTask<Void, Void, HashSet<AppWidgetAttribute>>() {
/**
*
* @param unused 使
* @return
*/
protected HashSet<AppWidgetAttribute> doInBackground(Void... unused) {
HashSet<AppWidgetAttribute> widgets = mNotesListAdapter.getSelectedWidget(); // 获取选中便签关联的小部件
HashSet<AppWidgetAttribute> widgets = mNotesListAdapter.getSelectedWidget();
if (!isSyncMode()) {
// 如果不是同步模式,直接删除便签
// if not synced, delete notes directly
if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
.getSelectedItemIds())) {
} else {
Log.e(TAG, "Delete notes error, should not happens");
}
} else {
// 如果是同步模式,将便签移到回收站
// in sync mode, we'll move the deleted note into the trash
// folder
if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
.getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
Log.e(TAG, "Move notes to trash folder error, should not happens");
@ -626,13 +547,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return widgets;
}
/**
*
* @param widgets
*/
@Override
protected void onPostExecute(HashSet<AppWidgetAttribute> widgets) {
// 更新关联的小部件
if (widgets != null) {
for (AppWidgetAttribute widget : widgets) {
if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
@ -641,17 +557,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
mModeCallBack.finishActionMode(); // 结束多选模式
mModeCallBack.finishActionMode();
}
}.execute();
}
/**
*
* @param folderId ID
*/
private void deleteFolder(long folderId) {
// 根文件夹不能删除
if (folderId == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Wrong folder id, should not happen " + folderId);
return;
@ -659,17 +570,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
HashSet<Long> ids = new HashSet<Long>();
ids.add(folderId);
// 获取文件夹中便签关联的小部件
HashSet<AppWidgetAttribute> widgets = DataUtils.getFolderNoteWidget(mContentResolver,
folderId);
if (!isSyncMode()) {
// 如果不是同步模式,直接删除文件夹
// if not synced, delete folder directly
DataUtils.batchDeleteNotes(mContentResolver, ids);
} else {
// 如果是同步模式,将文件夹移到回收站
// in sync mode, we'll move the deleted folder into the trash folder
DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER);
}
// 更新关联的小部件
if (widgets != null) {
for (AppWidgetAttribute widget : widgets) {
if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
@ -680,56 +589,36 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
* 便
* @param data 便
*/
private void openNode(NoteItemData data) {
Intent intent = new Intent(this, NoteEditActivity.class); // 创建跳转到编辑活动的意图
intent.setAction(Intent.ACTION_VIEW); // 设置动作为查看
intent.putExtra(Intent.EXTRA_UID, data.getId()); // 设置便签ID
this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); // 启动活动
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_UID, data.getId());
this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
}
/**
* 便
* @param data
*/
private void openFolder(NoteItemData data) {
mCurrentFolderId = data.getId(); // 设置当前文件夹ID
startAsyncNotesListQuery(); // 异步查询文件夹中的便签
mCurrentFolderId = data.getId();
startAsyncNotesListQuery();
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mState = ListEditState.CALL_RECORD_FOLDER; // 设置状态为通话记录文件夹
mAddNewNote.setVisibility(View.GONE); // 隐藏新建便签按钮
mState = ListEditState.CALL_RECORD_FOLDER;
mAddNewNote.setVisibility(View.GONE);
} else {
mState = ListEditState.SUB_FOLDER; // 设置状态为子文件夹
mState = ListEditState.SUB_FOLDER;
}
// 设置标题栏文本
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mTitleBar.setText(R.string.call_record_folder_name);
} else {
mTitleBar.setText(data.getSnippet());
}
mTitleBar.setVisibility(View.VISIBLE); // 显示标题栏
mTitleBar.setVisibility(View.VISIBLE);
}
/**
*
* @param v
*/
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();
}
}
/**
*
*/
private void showSoftInput() {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
@ -737,92 +626,74 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
* @param view
*/
private void hideSoftInput(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
/**
*
* @param create truefalse
*/
private void showCreateOrModifyFolderDialog(final boolean create) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null); // 加载对话框布局
final EditText etName = (EditText) view.findViewById(R.id.et_foler_name); // 获取文件夹名称输入框
showSoftInput(); // 显示输入法
// 设置对话框标题和输入框内容
View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
final EditText etName = (EditText) view.findViewById(R.id.et_foler_name);
showSoftInput();
if (!create) {
if (mFocusNoteDataItem != null) {
etName.setText(mFocusNoteDataItem.getSnippet()); // 设置现有文件夹名称
builder.setTitle(getString(R.string.menu_folder_change_name)); // 设置标题为修改文件夹名称
etName.setText(mFocusNoteDataItem.getSnippet());
builder.setTitle(getString(R.string.menu_folder_change_name));
} else {
Log.e(TAG, "The long click data item is null");
return;
}
} else {
etName.setText(""); // 清空输入框
builder.setTitle(this.getString(R.string.menu_create_folder)); // 设置标题为创建文件夹
etName.setText("");
builder.setTitle(this.getString(R.string.menu_create_folder));
}
builder.setPositiveButton(android.R.string.ok, null); // 设置确定按钮
builder.setPositiveButton(android.R.string.ok, null);
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
hideSoftInput(etName); // 隐藏输入法
hideSoftInput(etName);
}
}); // 设置取消按钮
});
final Dialog dialog = builder.setView(view).show(); // 显示对话框
final Button positive = (Button)dialog.findViewById(android.R.id.button1); // 获取确定按钮
final Dialog dialog = builder.setView(view).show();
final Button positive = (Button)dialog.findViewById(android.R.id.button1);
positive.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
hideSoftInput(etName); // 隐藏输入法
String name = etName.getText().toString(); // 获取输入的文件夹名称
// 检查文件夹名称是否已存在
hideSoftInput(etName);
String name = etName.getText().toString();
if (DataUtils.checkVisibleFolderName(mContentResolver, name)) {
Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name),
Toast.LENGTH_LONG).show();
etName.setSelection(0, etName.length()); // 选中输入框内容
etName.setSelection(0, etName.length());
return;
}
if (!create) {
// 修改现有文件夹
if (!TextUtils.isEmpty(name)) {
ContentValues values = new ContentValues();
values.put(NoteColumns.SNIPPET, name); // 设置新名称
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); // 设置类型为文件夹
values.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记为本地修改
// 更新数据库
values.put(NoteColumns.SNIPPET, name);
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
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)) {
// 创建新文件夹
ContentValues values = new ContentValues();
values.put(NoteColumns.SNIPPET, name); // 设置文件夹名称
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); // 设置类型为文件夹
// 插入数据库
values.put(NoteColumns.SNIPPET, name);
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
}
dialog.dismiss(); // 关闭对话框
dialog.dismiss();
}
});
// 如果输入框为空,禁用确定按钮
if (TextUtils.isEmpty(etName.getText())) {
positive.setEnabled(false);
}
/**
*
* When the name edit text is null, disable the positive button
*/
etName.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -832,9 +703,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (TextUtils.isEmpty(etName.getText())) {
positive.setEnabled(false); // 输入框为空,禁用确定按钮
positive.setEnabled(false);
} else {
positive.setEnabled(true); // 输入框不为空,启用确定按钮
positive.setEnabled(true);
}
}
@ -845,42 +716,32 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
});
}
/**
*
*/
@Override
public void onBackPressed() {
switch (mState) {
case SUB_FOLDER: // 子文件夹状态
mCurrentFolderId = Notes.ID_ROOT_FOLDER; // 返回根文件夹
mState = ListEditState.NOTE_LIST; // 设置状态为便签列表
startAsyncNotesListQuery(); // 异步查询便签列表
mTitleBar.setVisibility(View.GONE); // 隐藏标题栏
case SUB_FOLDER:
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
mState = ListEditState.NOTE_LIST;
startAsyncNotesListQuery();
mTitleBar.setVisibility(View.GONE);
break;
case CALL_RECORD_FOLDER: // 通话记录文件夹状态
mCurrentFolderId = Notes.ID_ROOT_FOLDER; // 返回根文件夹
mState = ListEditState.NOTE_LIST; // 设置状态为便签列表
mAddNewNote.setVisibility(View.VISIBLE); // 显示新建便签按钮
mTitleBar.setVisibility(View.GONE); // 隐藏标题栏
startAsyncNotesListQuery(); // 异步查询便签列表
case CALL_RECORD_FOLDER:
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
mState = ListEditState.NOTE_LIST;
mAddNewNote.setVisibility(View.VISIBLE);
mTitleBar.setVisibility(View.GONE);
startAsyncNotesListQuery();
break;
case NOTE_LIST: // 便签列表状态
super.onBackPressed(); // 执行默认返回操作
case NOTE_LIST:
super.onBackPressed();
break;
default:
break;
}
}
/**
*
* @param appWidgetId ID
* @param appWidgetType
*/
private void updateWidget(int appWidgetId, int appWidgetType) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); // 创建小部件更新意图
// 根据小部件类型设置相应的小部件提供者
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (appWidgetType == Notes.TYPE_WIDGET_2X) {
intent.setClass(this, NoteWidgetProvider_2x.class);
} else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
@ -891,11 +752,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
appWidgetId
}); // 设置小部件ID
appWidgetId
});
sendBroadcast(intent); // 发送广播更新小部件
setResult(RESULT_OK, intent); // 设置结果
sendBroadcast(intent);
setResult(RESULT_OK, intent);
}
private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
@ -971,40 +832,26 @@ 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);
}
if (item.getItemId() == R.id.menu_new_folder) {
showCreateOrModifyFolderDialog(true);
} else if (item.getItemId() == R.id.menu_export_text) {
exportNoteToText();
} else if (item.getItemId() == 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 (item.getItemId() == R.id.menu_setting) {
startPreferenceActivity();
} else if (item.getItemId() == R.id.menu_new_note) {
createNewNote();
} else if (item.getItemId() == R.id.menu_search) {
onSearchRequested();
}
return true;
}
@ -1111,7 +958,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private void startQueryDestinationFolders() {
String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
selection = (mState == ListEditState.NOTE_LIST) ? selection:
"(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")";
"(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")";
mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN,
null,

@ -33,11 +33,15 @@ import net.micode.notes.tool.ResourceParser.NoteItemBgResources;
/**
*
*/
public class NotesListItem extends LinearLayout {
public class NotesListItem extends LinearLayout {
/**
*
*/
private ImageView mAlert;
/**
*
*/
private ImageView mPinned;
/**
*
*/
@ -69,6 +73,7 @@ public class NotesListItem extends LinearLayout {
inflate(context, R.layout.note_item, this);
// 初始化控件
mAlert = (ImageView) findViewById(R.id.iv_alert_icon);
mPinned = (ImageView) findViewById(R.id.iv_pinned_icon);
mTitle = (TextView) findViewById(R.id.tv_title);
mTime = (TextView) findViewById(R.id.tv_time);
mCallName = (TextView) findViewById(R.id.tv_name);
@ -123,7 +128,7 @@ public class NotesListItem extends LinearLayout {
// 文件夹
mTitle.setText(data.getSnippet()
+ context.getString(R.string.format_folder_files_count,
data.getNotesCount()));
data.getNotesCount()));
mAlert.setVisibility(View.GONE);
} else {
// 普通笔记
@ -135,6 +140,12 @@ public class NotesListItem extends LinearLayout {
} else {
mAlert.setVisibility(View.GONE);
}
// 设置置顶图标
if (data.isPinned()) {
mPinned.setVisibility(View.VISIBLE);
} else {
mPinned.setVisibility(View.GONE);
}
}
}
// 设置修改时间

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#88555555" />
<item android:state_selected="true" android:color="#ff999999" />
<item android:color="#ff000000" />
</selector>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#50000000" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save