Merge pull request 'UI修改' (#15) from wangjiaqi_branch into master

pull/19/head
p82feo7wg 2 months ago
commit 257910f8e6

Binary file not shown.

@ -0,0 +1,160 @@
<?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:windowSoftInputMode="adjustPan"
android:exported="true">
<!-- 这段本来在theme和windowSoftInputMode之间android:uiOptions="splitActionBarWhenNarrow" -->
<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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 1.5 MiB

@ -1,170 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

@ -15,18 +15,17 @@
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dip"
android:gravity="center_vertical"
android:minHeight="50dip"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/preferences_add_account" />
android:text="@string/preferences_add_account"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>

@ -77,11 +77,11 @@
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_gravity="left|top"
android:layout_weight="1"
android:scrollbars="none"
android:fadingEdgeLength="0dip"
android:overScrollMode="never"
android:layout_gravity="left|top"
android:fadingEdgeLength="0dip">
android:scrollbars="none">
<LinearLayout
android:layout_width="fill_parent"
@ -91,20 +91,20 @@
android:id="@+id/note_edit_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left|top"
android:background="@null"
android:autoLink="all"
android:background="@null"
android:gravity="left|top"
android:lineSpacingMultiplier="1.2"
android:linksClickable="false"
android:minLines="12"
android:textAppearance="@style/TextAppearancePrimaryItem"
android:lineSpacingMultiplier="1.2" />
android:textAppearance="@style/TextAppearancePrimaryItem" />
<LinearLayout
android:id="@+id/note_edit_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="-10dip"
android:orientation="vertical"
android:visibility="gone" />
</LinearLayout>
</ScrollView>

@ -27,6 +27,15 @@
android:layout_gravity="center_vertical"
android:gravity="center_vertical">
<!-- 清单复选框,仅在清单模式下显示 -->
<CheckBox
android:id="@android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="true"
android:visibility="gone" />
<LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
@ -46,12 +55,29 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/tv_title"
<!-- 使用FrameLayout来让标题可以相互替代 -->
<FrameLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true" />
android:layout_weight="1">
<!-- 笔记标题 TextView -->
<TextView
android:id="@+id/tv_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
<!-- 清单标题 EditText仅在清单模式下显示 -->
<EditText
android:id="@+id/et_checklist_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:visibility="gone"
android:background="@null"
android:textAppearance="@style/TextAppearancePrimaryItem" />
</FrameLayout>
<TextView
android:id="@+id/tv_time"
@ -61,12 +87,12 @@
</LinearLayout>
</LinearLayout>
<CheckBox
android:id="@android:id/checkbox"
<!-- 清单项完成状态指示器,仅在清单模式下显示 -->
<ImageView
android:id="@+id/iv_checklist_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false"
android:src="@drawable/selected"
android:visibility="gone" />
</LinearLayout>

@ -36,6 +36,40 @@
android:singleLine="true"
android:textColor="#FFEAD1AE"
android:textSize="@dimen/text_font_size_medium" />
<!-- 顶部工具栏 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dip"
android:gravity="center_vertical|end">
<!-- 菜单按钮 -->
<ImageButton
android:id="@+id/btn_menu"
android:layout_width="50dip"
android:layout_height="50dip"
android:src="@android:drawable/ic_menu_more"
android:background="@null"
android:onClick="showCustomMenu" />
<!-- 搜索图标按钮 -->
<ImageButton
android:id="@+id/btn_search"
android:layout_width="50dp"
android:layout_height="50dip"
android:layout_marginRight="10dip"
android:src="@android:drawable/ic_menu_search"
android:background="@null"
android:onClick="handleSearchClick" />
<!-- 正方形添加按钮 -->
<Button
android:id="@+id/btn_new_note"
android:background="@drawable/new_note"
android:layout_width="50dip"
android:layout_height="50dip"
android:focusable="false" />
</LinearLayout>
<ListView
android:id="@+id/notes_list"
@ -46,13 +80,50 @@
android:listSelector="@android:color/transparent"
android:divider="@null"
android:fadingEdge="@null" />
<!-- 底部模式切换栏 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="60dip"
android:orientation="horizontal"
android:weightSum="2"
android:background="#FF007AFF">
<!-- 笔记模式按钮 -->
<Button
android:id="@+id/btn_note_mode"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="笔记"
android:textColor="#FFFFFFFF"
android:background="#FF007AFF"
android:onClick="switchToNoteMode"
android:textSize="@dimen/text_font_size_medium"
android:gravity="center"
android:padding="0dip"
android:layout_margin="0dip"
android:minHeight="0dip"
android:minWidth="0dip" />
<!-- 清单模式按钮 -->
<Button
android:id="@+id/btn_checklist_mode"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="清单"
android:textColor="#FF000000"
android:background="#FFFFFFFF"
android:onClick="switchToChecklistMode"
android:textSize="@dimen/text_font_size_medium"
android:gravity="center"
android:padding="0dip"
android:layout_margin="0dip"
android:minHeight="0dip"
android:minWidth="0dip" />
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/btn_new_note"
android:background="@drawable/new_note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:layout_gravity="bottom" />
</FrameLayout>

@ -32,11 +32,6 @@
<item
android:id="@+id/menu_setting"
android:title="@string/menu_setting" />
<item
android:id="@+id/menu_search"
android:title="@string/menu_search"/>
<item
android:id="@+id/menu_trash"
android:title="@string/menu_trash"/>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/new_note_pressed_background"/>
<foreground android:drawable="@mipmap/new_note_pressed_foreground"/>
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/new_note_pressed_background"/>
<foreground android:drawable="@mipmap/new_note_pressed_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">便签</string>
<string name="app_name">小米便签</string>
<string name="app_widget2x2">便签2x2</string>
<string name="app_widget4x4">便签4x4</string>
<string name="widget_havenot_content">没有关联内容,点击新建便签。</string>

@ -17,18 +17,47 @@
package net.micode.notes.data;
import android.net.Uri;
/**
*
*
*
*/
public class Notes {
// ContentProvider的授权标识
public static final String AUTHORITY = "micode_notes";
// 日志标签
public static final String TAG = "Notes";
// 0类型普通笔记
public static final int TYPE_NOTE = 0;
// 1类型文件夹
public static final int TYPE_FOLDER = 1;
// 2类型系统文件夹
public static final int TYPE_SYSTEM = 2;
// 系统文件夹的 ID 定义。
// #ID_ROOT_FOLDER 默认根文件夹
// #ID_TEMPARAY_FOLDER 临时文件夹,移动笔记时的中转
// #ID_CALL_RECORD_FOLDER 通话记录专用文件夹
// #ID_TRASH_FOLER 回收站
public static final int ID_ROOT_FOLDER = 0; // 默认根文件夹
public static final int ID_TEMPARAY_FOLDER = -1; // 临时文件夹(用于无归属的笔记)
public static final int ID_CALL_RECORD_FOLDER = -2; // 通话记录文件夹
public static final int ID_TRASH_FOLER = -3; // 回收站文件夹
/**
* Intent Extra Android Intent
* 1.
* 2. ID
* 3. ID
* 4.
* 5. ID
* 6.
* Following IDs are system folders' identifiers
* {@link Notes#ID_ROOT_FOLDER } is default folder
* {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder
* {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records
* 7.
*/
public static final int ID_ROOT_FOLDER = 0;
public static final int ID_TEMPARAY_FOLDER = -1;
@ -41,6 +70,7 @@ public class Notes {
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type";
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date";
public static final String INTENT_EXTRA_NOTE_TYPE = "net.micode.notes.note_type";
public static final int TYPE_WIDGET_INVALIDE = -1;
public static final int TYPE_WIDGET_2X = 0;
@ -186,6 +216,11 @@ public class Notes {
public static final String DELETED_DATE = "deleted_date";
}
/**
* DataColumns - 便(data)
* 便
* 使MIME_TYPE便便
*/
public interface DataColumns {
/**
* The unique ID for a row

@ -0,0 +1,152 @@
/*
* 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.model;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
/**
*
*
*/
public class ChecklistManager {
private static final String TAG = "ChecklistManager";
private ContentResolver mContentResolver;
/**
*
* @param contentResolver
*/
public ChecklistManager(ContentResolver contentResolver) {
mContentResolver = contentResolver;
}
/**
*
* @param noteId ID
* @return
*/
public boolean isChecklistNote(long noteId) {
// 使用ContentResolver查询笔记是否为清单
String selection = DataColumns.NOTE_ID + "=? AND " + DataColumns.MIME_TYPE + "=? AND " + DataColumns.DATA1 + "=? AND " + DataColumns.DATA2 + "=?";
String[] selectionArgs = {String.valueOf(noteId), DataConstants.NOTE, TextNote.MODE, String.valueOf(TextNote.MODE_CHECK_LIST)};
Cursor cursor = mContentResolver.query(Notes.CONTENT_DATA_URI, null, selection, selectionArgs, null);
boolean isChecklist = false;
if (cursor != null) {
isChecklist = cursor.moveToFirst();
cursor.close();
}
return isChecklist;
}
/**
*
* @param folderId ID
* @param widgetId ID
* @param widgetType
* @param bgResId ID
* @param context
* @return
*/
public WorkingNote createChecklistNote(long folderId, int widgetId, int widgetType, int bgResId, android.content.Context context) {
WorkingNote note = WorkingNote.createEmptyNote(context, folderId, widgetId, widgetType, bgResId);
note.setCheckListMode(TextNote.MODE_CHECK_LIST);
return note;
}
/**
*
* @param workingNote
*/
public void setChecklistType(WorkingNote workingNote) {
// 这里可以根据需要设置笔记类型
// workingNote.setNoteType(Notes.TYPE_CHECKLIST);
}
/**
*
* @param noteId ID
* @param context
* @return
*/
public boolean convertToChecklist(long noteId, android.content.Context context) {
WorkingNote note = WorkingNote.load(context, noteId);
if (note != null) {
note.setCheckListMode(TextNote.MODE_CHECK_LIST);
return note.saveNote();
}
return false;
}
/**
*
* @param noteId ID
* @param context
* @return
*/
public boolean convertToNormal(long noteId, android.content.Context context) {
WorkingNote note = WorkingNote.load(context, noteId);
if (note != null) {
note.setCheckListMode(TextNote.MODE_NORMAL);
return note.saveNote();
}
return false;
}
/**
*
* @return SQL
*/
public String getChecklistSelection() {
// 使用子查询来检查笔记是否为清单模式
return "EXISTS (SELECT 1 FROM note_data WHERE note_id = " + NoteColumns.ID +
" AND data1 = '" + TextNote.MODE + "' AND data2 = '" + String.valueOf(TextNote.MODE_CHECK_LIST) + "')";
}
/**
* Intent
* @param intent Intent
* @param forceChecklist
*/
public void addChecklistModeToIntent(Intent intent, boolean forceChecklist) {
if (forceChecklist) {
intent.putExtra("FORCE_CHECKLIST_MODE", true);
}
}
/**
* Intent
* @param intent Intent
* @param workingNote
*/
public void handleChecklistModeFromIntent(Intent intent, WorkingNote workingNote) {
boolean forceChecklistMode = intent.getBooleanExtra("FORCE_CHECKLIST_MODE", false);
if (forceChecklistMode) {
workingNote.setCheckListMode(TextNote.MODE_CHECK_LIST);
}
}
}

@ -50,15 +50,16 @@ public class Note {
*
* @param context
* @param folderId ID
* @param type TYPE_NOTE
* @return ID>00
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
public static synchronized long getNewNoteId(Context context, long folderId, int type) {
// 在数据库中创建新笔记:设置创建/修改时间、类型、父文件夹等初始值
ContentValues values = new ContentValues();
long createdTime = System.currentTimeMillis();
values.put(NoteColumns.CREATED_DATE, createdTime);
values.put(NoteColumns.MODIFIED_DATE, createdTime);
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
values.put(NoteColumns.TYPE, type);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
values.put(NoteColumns.PARENT_ID, folderId);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
@ -76,6 +77,18 @@ public class Note {
return noteId;
}
/**
* ID
* TYPE_NOTE
*
* @param context
* @param folderId ID
* @return ID>00
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
return getNewNoteId(context, folderId, Notes.TYPE_NOTE);
}
/**
* -
*/

@ -57,6 +57,7 @@ public class WorkingNote {
private boolean mIsDeleted; // 是否已删除
private NoteSettingChangedListener mNoteSettingStatusListener; // 笔记设置变化监听器
private String mPassword; // 密码(仅在创建时使用)
private int mNoteType; // 笔记类型(普通笔记/清单)
@ -115,6 +116,7 @@ public class WorkingNote {
mIsDeleted = false;
mMode = 0;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
mNoteType = Notes.TYPE_NOTE; // 默认创建普通笔记
}
/**
@ -165,7 +167,7 @@ public class WorkingNote {
private void loadNoteData() {
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] {
String.valueOf(mNoteId)
String.valueOf(mNoteId)
}, null);
if (cursor != null) {
@ -201,7 +203,7 @@ public class WorkingNote {
* @return
*/
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) {
int widgetType, int defaultBgColorId) {
WorkingNote note = new WorkingNote(context, folderId);
note.setBgColorId(defaultBgColorId);
note.setWidgetId(widgetId);
@ -227,7 +229,14 @@ public class WorkingNote {
public synchronized boolean saveNote() {
if (isWorthSaving()) {
if (!existInDatabase()) {
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
// 根据当前模式设置笔记类型
int noteType = Notes.TYPE_NOTE;
if (mMode == TextNote.MODE_CHECK_LIST) {
noteType = Notes.TYPE_CHECKLIST;
}
// 使用指定的笔记类型创建新笔记
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId, noteType)) == 0) {
Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false;
}
@ -317,7 +326,7 @@ public class WorkingNote {
mIsDeleted = mark;
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onWidgetChanged();
mNoteSettingStatusListener.onWidgetChanged();
}
}

@ -55,6 +55,7 @@ import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.ChecklistManager;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
@ -161,6 +162,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private LinearLayout mEditTextList; // 编辑文本列表(用于清单模式)
private String mUserQuery; // 用户查询字符串
private Pattern mPattern; // 正则表达式模式(用于高亮查询结果)
private ChecklistManager mChecklistManager; // 清单管理器OMO
/**
*
@ -171,12 +173,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
super.onCreate(savedInstanceState);
this.setContentView(R.layout.note_edit); // 设置布局
initResources(); // 先初始化资源再初始化活动状态OMO
// 初始化清单管理器
mChecklistManager = new ChecklistManager(getContentResolver());
// 如果没有保存的状态且无法初始化活动状态,则结束活动
if (savedInstanceState == null && !initActivityState(getIntent())) {
finish();
return;
}
initResources(); // 初始化资源
}
/**
@ -220,7 +226,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE) && !DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_CHECKLIST)) {
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
showToast(R.string.error_note_not_exist);
@ -269,8 +275,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mWorkingNote.convertToCallNote(phoneNumber, callDate);
}
} else {
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType,
bgResId);
mWorkingNote = WorkingNote.createEmptyNote(this, folderId, widgetId, widgetType, bgResId);
// 设置笔记类型
int noteType = intent.getIntExtra(Notes.INTENT_EXTRA_NOTE_TYPE, Notes.TYPE_NOTE);
// 使用ChecklistManager处理清单模式标记OMO
if (mChecklistManager != null) {
mChecklistManager.handleChecklistModeFromIntent(intent, mWorkingNote);
}
}
// 处理加密便签
@ -313,7 +326,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 设置笔记编辑器的文本外观
mNoteEditor.setTextAppearance(this, TextAppearanceResources
.getTexAppearanceResource(mFontSizeId));
// 根据笔记模式设置显示方式
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent()); // 切换到清单模式
@ -323,12 +336,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 将光标定位到文本末尾
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
// 隐藏所有背景选择的选中状态
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
// 设置头部视图和编辑器面板的背景
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
@ -429,8 +442,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|| ev.getX() > (x + view.getWidth())
|| ev.getY() < y
|| ev.getY() > (y + view.getHeight())) {
return false;
}
return false;
}
return true;
}
@ -449,7 +462,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
// 为所有背景选择按钮设置点击监听器
for (int id : sBgSelectorBtnsMap.keySet()) {
ImageView iv = (ImageView) findViewById(id);
@ -457,17 +470,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
mFontSizeSelector = findViewById(R.id.font_size_selector);
// 为所有字体大小选择按钮设置点击监听器
for (int id : sFontSizeBtnsMap.keySet()) {
View view = findViewById(id);
view.setOnClickListener(this);
};
// 初始化共享偏好设置和字体大小
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mFontSizeId = mSharedPrefs.getInt(PREFERENCE_FONT_SIZE, ResourceParser.BG_DEFAULT_FONT_SIZE);
/**
* HACKME: Fix bug of store the resource id in shared preference.
* The id may larger than the length of resources, in this case,
@ -476,7 +489,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if(mFontSizeId >= TextAppearanceResources.getResourcesSize()) {
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
}
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
}
@ -499,7 +512,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
private void updateWidget() {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
// 根据小部件类型设置对应的小部件提供器
if (mWorkingNote.getWidgetType() == Notes.TYPE_WIDGET_2X) {
intent.setClass(this, NoteWidgetProvider_2x.class);
@ -511,7 +524,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
mWorkingNote.getWidgetId()
mWorkingNote.getWidgetId()
});
sendBroadcast(intent); // 发送广播更新小部件
@ -542,7 +555,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mFontSizeId = sFontSizeBtnsMap.get(id);
mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit();
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.VISIBLE);
// 根据当前模式更新字体大小
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
getWorkingText();
@ -868,6 +881,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @param text
*/
private void switchToListMode(String text) {
// 处理null文本避免空指针异常OMO
if (text == null) {
text = "";
}
mEditTextList.removeAllViews(); // 清空编辑文本列表
String[] items = text.split("\n"); // 按行分割文本
int index = 0;
@ -920,7 +938,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
// 设置复选框的选中状态变化监听器
CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@ -975,14 +993,31 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @param newMode
*/
public void onCheckListModeChanged(int oldMode, int newMode) {
// 添加null检查避免在mNoteEditor初始化前调用导致闪退
if (mNoteEditor == null || mEditTextList == null) {
return;
}
String text = "";
if (newMode == TextNote.MODE_CHECK_LIST) {
switchToListMode(mNoteEditor.getText().toString());
// 安全获取文本避免空指针异常OMO
if (mNoteEditor.getText() != null) {
text = mNoteEditor.getText().toString();
}
switchToListMode(text);
} else {
if (!getWorkingText()) {
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
""));
String content = mWorkingNote.getContent();
if (content != null) {
mWorkingNote.setWorkingText(content.replace(TAG_UNCHECKED + " ", ""));
}
}
String content = mWorkingNote.getContent();
if (content != null) {
mNoteEditor.setText(getHighlightQueryResult(content, mUserQuery));
} else {
mNoteEditor.setText("");
}
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE);
}

@ -36,18 +36,6 @@ import net.micode.notes.tool.DataUtils;
public class NoteItemData {
/** 数据库查询投影数组 */
static final String [] PROJECTION = new String [] {
NoteColumns.ID, // 笔记ID
NoteColumns.ALERTED_DATE, // 提醒日期
NoteColumns.BG_COLOR_ID, // 背景颜色ID
NoteColumns.CREATED_DATE, // 创建日期
NoteColumns.HAS_ATTACHMENT, // 是否有附件
NoteColumns.MODIFIED_DATE, // 修改日期
NoteColumns.NOTES_COUNT, // 笔记数量
NoteColumns.PARENT_ID, // 父文件夹ID
NoteColumns.SNIPPET, // 笔记摘要
NoteColumns.TYPE, // 笔记类型
NoteColumns.WIDGET_ID, // 小部件ID
NoteColumns.WIDGET_TYPE, // 小部件类型
NoteColumns.IS_ENCRYPTED, // 是否加密
};
@ -108,6 +96,10 @@ public class NoteItemData {
private String mName;
/** 电话号码(用于通话记录) */
private String mPhoneNumber;
/** 清单项目完成状态 */
private boolean mIsChecked;
/** 原始带标记的摘要 */
private String mOriginalSnippet;
/** 是否为最后一项 */
private boolean mIsLastItem;
@ -134,10 +126,19 @@ public class NoteItemData {
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
mParentId = cursor.getLong(PARENT_ID_COLUMN);
mSnippet = cursor.getString(SNIPPET_COLUMN);
// 移除复选框标签
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
NoteEditActivity.TAG_UNCHECKED, "");
mOriginalSnippet = cursor.getString(SNIPPET_COLUMN);
mSnippet = mOriginalSnippet;
// 解析完成状态
mIsChecked = false;
if (mSnippet.startsWith(NoteEditActivity.TAG_CHECKED)) {
mIsChecked = true;
mSnippet = mSnippet.substring(NoteEditActivity.TAG_CHECKED.length()).trim();
} else if (mSnippet.startsWith(NoteEditActivity.TAG_UNCHECKED)) {
mIsChecked = false;
mSnippet = mSnippet.substring(NoteEditActivity.TAG_UNCHECKED.length()).trim();
}
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
@ -173,8 +174,8 @@ public class NoteItemData {
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
// 如果是笔记类型且不是第一项,检查前一项是否为文件夹
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
// 如果是笔记或清单类型且不是第一项,检查前一项是否为文件夹
if ((mType == Notes.TYPE_NOTE || mType == Notes.TYPE_CHECKLIST) && !mIsFirstItem) {
int position = cursor.getPosition();
if (cursor.moveToPrevious()) {
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
@ -362,6 +363,30 @@ public class NoteItemData {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
}
/**
*
* @return truefalse
*/
public boolean isChecked() {
return mIsChecked;
}
/**
*
* @param checked
*/
public void setChecked(boolean checked) {
mIsChecked = checked;
}
/**
*
* @return
*/
public String getOriginalSnippet() {
return mOriginalSnippet;
}
/**
* Cursor
* @param cursor Cursor

@ -63,7 +63,9 @@ import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.gtask.remote.GTaskSyncService;
import net.micode.notes.model.ChecklistManager;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.tool.BackupUtils;
import net.micode.notes.tool.DataUtils;
@ -78,6 +80,15 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
import android.os.Build;
import android.view.ViewConfiguration;
import java.lang.reflect.Field;
/**
* -
*
*
*/
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
@ -96,6 +107,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
private ListEditState mState;
private boolean mIsChecklistMode; // 是否为清单模式OMO
private Button mNoteModeButton; // 笔记模式按钮OMO
private Button mChecklistModeButton; // 清单模式按钮OMO
private ChecklistManager mChecklistManager; // 清单管理器OMO
private BackgroundQueryHandler mBackgroundQueryHandler;
@ -138,13 +153,32 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_list);
initResources();
// 隐藏标题栏OMO
if (getActionBar() != null) {
getActionBar().hide();
}
/**
* Insert an introduction when user firstly use this application
*/
setAppInfoFromRawRes();
setContentView(R.layout.note_list); // 设置布局
initResources(); // 初始化资源
// 隐藏底部虚拟菜单按钮OMO
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = null;
try {
menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 首次进入时插入“介绍”笔记
setAppInfoFromRawRes(); // 设置应用信息(首次使用时添加介绍笔记)
}
@Override
@ -163,7 +197,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
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);
@ -203,19 +237,25 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
*
*/
@Override
protected void onStart() {
super.onStart();
startAsyncNotesListQuery();
}
/**
*
*
*/
private void initResources() {
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);
@ -229,13 +269,28 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
mState = ListEditState.NOTE_LIST;
mModeCallBack = new ModeCallback();
// 初始化模式切换按钮和清单管理器OMO
mNoteModeButton = (Button) findViewById(R.id.btn_note_mode);
mChecklistModeButton = (Button) findViewById(R.id.btn_checklist_mode);
mIsChecklistMode = false;
updateModeButtons();
mChecklistManager = new ChecklistManager(mContentResolver);
}
/**
* -
*
*/
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
private MenuItem mMoveMenu;
/**
*
*
*/
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
getMenuInflater().inflate(R.menu.note_list_options, menu);
menu.findItem(R.id.delete).setOnMenuItemClickListener(this);
@ -269,6 +324,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
/**
*
*
*/
private void updateMenu() {
int selectedCount = mNotesListAdapter.getSelectedCount();
// Update dropdown menu
@ -296,22 +355,37 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return false;
}
/**
*
*
*/
public void onDestroyActionMode(ActionMode mode) {
mNotesListAdapter.setChoiceMode(false);
mNotesListView.setLongClickable(true);
mAddNewNote.setVisibility(View.VISIBLE);
}
/**
*
*/
public void finishActionMode() {
mActionMode.finish();
}
/**
*
*
*/
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
boolean checked) {
mNotesListAdapter.setCheckedItem(position, checked);
updateMenu();
}
/**
*
*
*/
public boolean onMenuItemClick(MenuItem item) {
if (mNotesListAdapter.getSelectedCount() == 0) {
Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
@ -321,22 +395,24 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
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()));
mNotesListAdapter.getSelectedCount()));
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
batchDelete();
}
});
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:
@ -346,6 +422,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
*
*/
private class NewNoteOnTouchListener implements OnTouchListener {
public boolean onTouch(View v, MotionEvent event) {
@ -356,6 +436,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
int newNoteViewHeight = mAddNewNote.getHeight();
int start = screenHeight - newNoteViewHeight;
int eventY = start + (int) event.getY();
// 子文件夹状态需减去标题栏高度
/**
* Minus TitleBar's height
*/
@ -363,6 +444,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
eventY -= mTitleBar.getHeight();
start -= mTitleBar.getHeight();
}
// HACKME: 点击“新建”按钮透明区时,将事件派发给下方列表。
// 透明区近似线性公式 y = -0.12x + 94px背景改动需同步更新该公式。
/**
* HACKME:When click the transparent part of "New Note" button, dispatch
* the event to the list view behind this button. The transparent part of
@ -408,27 +491,61 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
/**
*
* ID
*/
private void startAsyncNotesListQuery() {
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
String selection;
String[] selectionArgs;
if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
if (mIsChecklistMode) {
// 根文件夹下的清单模式:只显示清单类型的笔记
selection = "(" + NoteColumns.TYPE + "=" + Notes.TYPE_CHECKLIST + " AND " + NoteColumns.PARENT_ID + "=?)" +
" OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0)";
} else {
// 根文件夹下的笔记模式:显示文件夹、普通笔记和非空通话记录文件夹
selection = "(" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" +
" OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0)";
}
} else {
if (mIsChecklistMode) {
// 普通文件夹下的清单模式:只显示清单类型的笔记
selection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_CHECKLIST;
} else {
// 普通文件夹下的笔记模式:只显示普通笔记
selection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
}
}
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {
String.valueOf(mCurrentFolderId)
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
/**
* -
*/
private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
/**
*
*
*/
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
case FOLDER_NOTE_LIST_QUERY_TOKEN:
// 查询笔记列表完成,更新适配器
mNotesListAdapter.changeCursor(cursor);
break;
case FOLDER_LIST_QUERY_TOKEN:
// 查询文件夹列表完成,显示文件夹菜单
if (cursor != null && cursor.getCount() > 0) {
showFolderListMenu(cursor);
} else {
@ -441,6 +558,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
*
*/
private void showFolderListMenu(Cursor cursor) {
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(R.string.menu_title_select_folder);
@ -462,6 +583,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder.show();
}
/**
*
*
*/
private void createNewNote() {
// 弹出对话框询问是否加密
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@ -526,9 +651,28 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
// 设置笔记类型
if (mIsChecklistMode) {
// 清单模式:创建清单类型的笔记
intent.putExtra(Notes.INTENT_EXTRA_NOTE_TYPE, Notes.TYPE_CHECKLIST);
} else {
// 笔记模式:创建普通笔记类型
intent.putExtra(Notes.INTENT_EXTRA_NOTE_TYPE, Notes.TYPE_NOTE);
}
// 如果是清单模式使用ChecklistManager添加清单模式标记
if (mIsChecklistMode && mChecklistManager != null) {
mChecklistManager.addChecklistModeToIntent(intent, true);
}
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
}
/**
*
*
*/
private void createNoteWithEncryption(String password) {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
@ -575,6 +719,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}.execute();
}
/**
*
*
*/
private void deleteFolder(long folderId) {
if (folderId == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Wrong folder id, should not happen " + folderId);
@ -602,6 +750,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
* /
*/
private void openNode(NoteItemData data) {
// 检查是否为加密便签
// 使用PasswordUtils检查因为数据库中的值可能更准确
@ -620,6 +772,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
* ID
*/
private void openFolder(NoteItemData data) {
mCurrentFolderId = data.getId();
startAsyncNotesListQuery();
@ -637,16 +793,101 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mTitleBar.setVisibility(View.VISIBLE);
}
/**
*
*
*/
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_new_note:
createNewNote();
break;
default:
break;
}
}
/**
*
* OMO
*/
public void showCustomMenu(View view) {
PopupMenu popupMenu = new PopupMenu(this, view);
popupMenu.inflate(R.menu.note_list); // 加载原有菜单资源
// 设置菜单点击事件
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// 调用原有的菜单处理逻辑
return onOptionsItemSelected(item);
}
});
popupMenu.show();
}
/**
*
*
* OMO
*/
private void updateModeButtons() {
if (mIsChecklistMode) {
// 清单模式下,清单按钮高亮
mChecklistModeButton.setBackgroundColor(0xFF007AFF);
mChecklistModeButton.setTextColor(0xFFFFFFFF);
mNoteModeButton.setBackgroundColor(0xFFFFFFFF);
mNoteModeButton.setTextColor(0xFF000000);
} else {
// 笔记模式下,笔记按钮高亮
mNoteModeButton.setBackgroundColor(0xFF007AFF);
mNoteModeButton.setTextColor(0xFFFFFFFF);
mChecklistModeButton.setBackgroundColor(0xFFFFFFFF);
mChecklistModeButton.setTextColor(0xFF000000);
}
}
/**
*
* @param view
* OMO
*/
public void switchToNoteMode(View view) {
mIsChecklistMode = false;
updateModeButtons();
// 更新适配器模式
if (mNotesListAdapter != null) {
mNotesListAdapter.setChecklistMode(false);
}
// 查询笔记列表
startAsyncNotesListQuery();
}
/**
*
*
* @param view
* OMO
*/
public void switchToChecklistMode(View view) {
mIsChecklistMode = true;
updateModeButtons();
// 更新适配器模式
if (mNotesListAdapter != null) {
mNotesListAdapter.setChecklistMode(true);
}
// 查询清单列表
startAsyncNotesListQuery();
}
/**
*
*/
private void showSoftInput() {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
@ -654,11 +895,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
*/
private void hideSoftInput(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
/**
*
* @param create
*/
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);
@ -704,7 +952,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.LOCAL_MODIFIED, 1);
mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
+ "=?", new String[] {
String.valueOf(mFocusNoteDataItem.getId())
String.valueOf(mFocusNoteDataItem.getId())
});
}
} else if (!TextUtils.isEmpty(name)) {
@ -744,6 +992,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
});
}
/**
*
* 退
*/
@Override
public void onBackPressed() {
switch (mState) {
@ -768,6 +1020,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
*
* 广
*/
private void updateWidget(int appWidgetId, int appWidgetType) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (appWidgetType == Notes.TYPE_WIDGET_2X) {
@ -780,13 +1036,17 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
appWidgetId
appWidgetId
});
sendBroadcast(intent);
setResult(RESULT_OK, intent);
}
/**
*
*
*/
private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
if (mFocusNoteDataItem != null) {
@ -798,6 +1058,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
};
/**
*
*
*/
@Override
public void onContextMenuClosed(Menu menu) {
if (mNotesListView != null) {
@ -806,6 +1070,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
super.onContextMenuClosed(menu);
}
/**
*
*
*/
@Override
public boolean onContextItemSelected(MenuItem item) {
if (mFocusNoteDataItem == null) {
@ -840,6 +1108,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
/**
*
*
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
@ -858,6 +1130,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
/**
*
*
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@ -908,7 +1184,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
startSearch(null, false, null /* appData */, false);
return true;
}
/**
*
* @param view
* OMO
*/
public void handleSearchClick(View view) {
// 调用系统搜索方法
onSearchRequested();
}
private void exportNoteToText() {
final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
new AsyncTask<Void, Void, Integer>() {
@ -967,7 +1251,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (view instanceof NotesListItem) {
NoteItemData item = ((NotesListItem) view).getItemData();
if (mNotesListAdapter.isInChoiceMode()) {
if (item.getType() == Notes.TYPE_NOTE) {
if (item.getType() == Notes.TYPE_NOTE || item.getType() == Notes.TYPE_CHECKLIST) {
position = position - mNotesListView.getHeaderViewsCount();
mModeCallBack.onItemCheckedStateChanged(null, position, id,
!mNotesListAdapter.isSelectedItem(position));
@ -980,18 +1264,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (item.getType() == Notes.TYPE_FOLDER
|| item.getType() == Notes.TYPE_SYSTEM) {
openFolder(item);
} else if (item.getType() == Notes.TYPE_NOTE) {
} else if (item.getType() == Notes.TYPE_NOTE || item.getType() == Notes.TYPE_CHECKLIST) {
openNode(item);
} else {
Log.e(TAG, "Wrong note type in NOTE_LIST");
Log.e(TAG, "Wrong note type in NOTE_LIST: " + item.getType());
}
break;
case SUB_FOLDER:
case CALL_RECORD_FOLDER:
if (item.getType() == Notes.TYPE_NOTE) {
if (item.getType() == Notes.TYPE_NOTE || item.getType() == Notes.TYPE_CHECKLIST) {
openNode(item);
} else {
Log.e(TAG, "Wrong note type in SUB_FOLDER");
Log.e(TAG, "Wrong note type in SUB_FOLDER: " + item.getType());
}
break;
default:
@ -1005,7 +1289,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,
@ -1023,7 +1307,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
mFocusNoteDataItem = ((NotesListItem) view).getItemData();
if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
if ((mFocusNoteDataItem.getType() == Notes.TYPE_NOTE || mFocusNoteDataItem.getType() == Notes.TYPE_CHECKLIST) && !mNotesListAdapter.isInChoiceMode()) {
if (mNotesListView.startActionMode(mModeCallBack) != null) {
mModeCallBack.onItemCheckedStateChanged(null, position, id, true);
mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);

@ -16,6 +16,8 @@
package net.micode.notes.ui;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
@ -24,6 +26,7 @@ import android.view.ViewGroup;
import android.widget.CursorAdapter;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import java.util.Collection;
import java.util.HashMap;
@ -49,6 +52,8 @@ public class NotesListAdapter extends CursorAdapter {
private int mNotesCount;
/** 是否处于选择模式 */
private boolean mChoiceMode;
/** 是否处于清单模式 */
private boolean mIsChecklistMode;
/**
*
@ -70,6 +75,16 @@ public class NotesListAdapter extends CursorAdapter {
mSelectedIndex = new HashMap<Integer, Boolean>();
mContext = context;
mNotesCount = 0;
mIsChecklistMode = false;
}
/**
*
* @param isChecklistMode
*/
public void setChecklistMode(boolean isChecklistMode) {
mIsChecklistMode = isChecklistMode;
notifyDataSetChanged();
}
/**
@ -95,8 +110,90 @@ public class NotesListAdapter extends CursorAdapter {
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof NotesListItem) {
NoteItemData itemData = new NoteItemData(context, cursor);
((NotesListItem) view).bind(context, itemData, mChoiceMode,
isSelectedItem(cursor.getPosition()));
NotesListItem notesListItem = (NotesListItem) view;
// 绑定数据,传递当前模式
notesListItem.bind(context, itemData, mChoiceMode,
isSelectedItem(cursor.getPosition()), mIsChecklistMode);
// 设置标题变更监听器
notesListItem.setOnTitleChangedListener(new NotesListItem.OnTitleChangedListener() {
@Override
public void onTitleChanged(long noteId, String newTitle) {
updateNoteTitle(noteId, newTitle);
}
});
// 设置完成状态变更监听器
notesListItem.setOnCheckStatusChangedListener(new NotesListItem.OnCheckStatusChangedListener() {
@Override
public void onCheckStatusChanged(long noteId, boolean isChecked) {
updateNoteCheckStatus(noteId, isChecked);
}
});
}
}
/**
*
* @param noteId ID
* @param newTitle
*/
private void updateNoteTitle(long noteId, String newTitle) {
// 使用ContentResolver更新笔记标题
ContentValues values = new ContentValues();
values.put(NoteColumns.SNIPPET, newTitle);
mContext.getContentResolver().update(
Notes.CONTENT_NOTE_URI,
values,
NoteColumns.ID + "=?",
new String[]{String.valueOf(noteId)});
}
/**
*
* @param noteId ID
* @param isChecked
*/
private void updateNoteCheckStatus(long noteId, boolean isChecked) {
// 查询当前笔记的内容
Cursor cursor = mContext.getContentResolver().query(
Notes.CONTENT_NOTE_URI,
new String[]{NoteColumns.SNIPPET},
NoteColumns.ID + "=?",
new String[]{String.valueOf(noteId)},
null);
if (cursor != null && cursor.moveToFirst()) {
String currentSnippet = cursor.getString(0);
cursor.close();
// 移除旧的标记
String contentWithoutMark = currentSnippet;
if (contentWithoutMark.startsWith(NoteEditActivity.TAG_CHECKED)) {
contentWithoutMark = contentWithoutMark.substring(NoteEditActivity.TAG_CHECKED.length()).trim();
} else if (contentWithoutMark.startsWith(NoteEditActivity.TAG_UNCHECKED)) {
contentWithoutMark = contentWithoutMark.substring(NoteEditActivity.TAG_UNCHECKED.length()).trim();
}
// 添加新的标记
String newSnippet;
if (isChecked) {
newSnippet = NoteEditActivity.TAG_CHECKED + " " + contentWithoutMark;
} else {
newSnippet = NoteEditActivity.TAG_UNCHECKED + " " + contentWithoutMark;
}
// 更新数据库
ContentValues values = new ContentValues();
values.put(NoteColumns.SNIPPET, newSnippet);
mContext.getContentResolver().update(
Notes.CONTENT_NOTE_URI,
values,
NoteColumns.ID + "=?",
new String[]{String.valueOf(noteId)});
}
}
@ -135,8 +232,9 @@ public class NotesListAdapter extends CursorAdapter {
Cursor cursor = getCursor();
for (int i = 0; i < getCount(); i++) {
if (cursor.moveToPosition(i)) {
// 只处理类型为笔记的项
if (NoteItemData.getNoteType(cursor) == Notes.TYPE_NOTE) {
// 处理类型为笔记或清单的项
int type = NoteItemData.getNoteType(cursor);
if (type == Notes.TYPE_NOTE || type == Notes.TYPE_CHECKLIST) {
setCheckedItem(i, checked);
}
}
@ -244,15 +342,16 @@ public class NotesListAdapter extends CursorAdapter {
/**
*
*
*
*/
private void calcNotesCount() {
mNotesCount = 0;
for (int i = 0; i < getCount(); i++) {
Cursor c = (Cursor) getItem(i);
if (c != null) {
// 只统计类型为笔记的项
if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) {
// 统计类型为笔记或清单的项
int type = NoteItemData.getNoteType(c);
if (type == Notes.TYPE_NOTE || type == Notes.TYPE_CHECKLIST) {
mNotesCount++;
}
} else {

@ -17,15 +17,24 @@
package net.micode.notes.ui;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
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.TextNote;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser.NoteItemBgResources;
@ -52,6 +61,48 @@ public class NotesListItem extends LinearLayout {
private NoteItemData mItemData;
/** 复选框(用于选择模式) */
private CheckBox mCheckBox;
/** 清单标题编辑框 */
private EditText mChecklistTitle;
/** 清单状态图标 */
private ImageView mChecklistStatus;
/** 上下文 */
private Context mContext;
/** 当前是否为清单模式 */
private boolean mIsChecklistMode;
/** 标题监听器,用于保存清单标题变更 */
private OnTitleChangedListener mOnTitleChangedListener;
/** 完成状态监听器,用于保存清单项目完成状态变更 */
private OnCheckStatusChangedListener mOnCheckStatusChangedListener;
/**
*
*/
public interface OnTitleChangedListener {
void onTitleChanged(long noteId, String newTitle);
}
/**
*
*/
public interface OnCheckStatusChangedListener {
void onCheckStatusChanged(long noteId, boolean isChecked);
}
/**
*
* @param listener
*/
public void setOnTitleChangedListener(OnTitleChangedListener listener) {
mOnTitleChangedListener = listener;
}
/**
*
* @param listener
*/
public void setOnCheckStatusChangedListener(OnCheckStatusChangedListener listener) {
mOnCheckStatusChangedListener = listener;
}
/**
*
@ -59,6 +110,7 @@ public class NotesListItem extends LinearLayout {
*/
public NotesListItem(Context context) {
super(context);
mContext = context;
// 填充布局
inflate(context, R.layout.note_item, this);
// 获取视图组件
@ -68,6 +120,30 @@ public class NotesListItem extends LinearLayout {
mTime = (TextView) findViewById(R.id.tv_time);
mCallName = (TextView) findViewById(R.id.tv_name);
mCheckBox = (CheckBox) findViewById(android.R.id.checkbox);
// 初始化清单相关组件
mChecklistTitle = (EditText) findViewById(R.id.et_checklist_title);
mChecklistStatus = (ImageView) findViewById(R.id.iv_checklist_status);
// 设置清单标题编辑框的文本变更监听器
mChecklistTitle.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// 文本变更前的处理
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// 文本变更时的处理
}
@Override
public void afterTextChanged(Editable s) {
// 文本变更后的处理,保存新标题
if (mItemData != null && mOnTitleChangedListener != null) {
mOnTitleChangedListener.onTitleChanged(mItemData.getId(), s.toString());
}
}
});
}
/**
@ -78,16 +154,31 @@ public class NotesListItem extends LinearLayout {
* @param checked
*/
public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) {
// 处理选择模式下的复选框显示
if (choiceMode && data.getType() == Notes.TYPE_NOTE) {
mCheckBox.setVisibility(View.VISIBLE);
mCheckBox.setChecked(checked);
} else {
mCheckBox.setVisibility(View.GONE);
}
bind(context, data, choiceMode, checked, false);
}
/**
*
* @param context
* @param data
* @param choiceMode
* @param checked
* @param isChecklistMode
*/
public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked, boolean isChecklistMode) {
mContext = context;
mIsChecklistMode = isChecklistMode;
// 先默认隐藏复选框
mCheckBox.setVisibility(View.GONE);
mItemData = data;
// 重置视图状态
mTitle.setVisibility(View.VISIBLE);
mChecklistTitle.setVisibility(View.GONE);
mChecklistStatus.setVisibility(View.GONE);
// 处理通话记录文件夹
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
mCallName.setVisibility(View.GONE);
@ -96,7 +187,7 @@ public class NotesListItem extends LinearLayout {
mTitle.setText(context.getString(R.string.call_record_folder_name)
+ context.getString(R.string.format_folder_files_count, data.getNotesCount()));
mAlert.setImageResource(R.drawable.call_record);
}
}
// 处理通话记录笔记
else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) {
mCallName.setVisibility(View.VISIBLE);
@ -109,30 +200,114 @@ public class NotesListItem extends LinearLayout {
} else {
mAlert.setVisibility(View.GONE);
}
}
}
// 处理普通文件夹或笔记
else {
mCallName.setVisibility(View.GONE);
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
if (data.getType() == Notes.TYPE_FOLDER) {
// 文件夹显示格式:名称 + 数量
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
mTitle.setText(data.getSnippet()
+ context.getString(R.string.format_folder_files_count,
data.getNotesCount()));
data.getNotesCount()));
mAlert.setVisibility(View.GONE);
} else {
// 笔记显示格式:摘要
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
if (data.hasAlert()) {
mAlert.setImageResource(R.drawable.clock);
mAlert.setVisibility(View.VISIBLE);
// 处理清单模式
if (isChecklistMode) {
// 清单模式显示编辑框和复选框隐藏TextView和状态指示器
mTitle.setVisibility(View.GONE);
mChecklistTitle.setVisibility(View.VISIBLE);
mCheckBox.setVisibility(View.VISIBLE);
mChecklistStatus.setVisibility(View.GONE);
// 设置清单标题
String title = data.getSnippet();
mChecklistTitle.setText(title);
mChecklistTitle.setSelection(title.length());
// 初始状态下EditText不可编辑只能长按后编辑
mChecklistTitle.setFocusable(false);
mChecklistTitle.setFocusableInTouchMode(false);
mChecklistTitle.setClickable(false);
mChecklistTitle.setCursorVisible(false);
// 根据完成状态设置复选框和样式
boolean isChecked = data.isChecked();
mCheckBox.setChecked(isChecked);
updateChecklistStyle(isChecked);
// 添加复选框点击事件,切换完成状态
mCheckBox.setClickable(true);
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// 切换完成状态
data.setChecked(isChecked);
// 更新UI
updateChecklistStyle(isChecked);
// 通知监听器,保存完成状态到数据库
if (mOnCheckStatusChangedListener != null) {
mOnCheckStatusChangedListener.onCheckStatusChanged(data.getId(), isChecked);
}
}
});
// 添加长按事件,长按后可编辑
mChecklistTitle.setLongClickable(true);
mChecklistTitle.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// 设置为可编辑状态
mChecklistTitle.setFocusable(true);
mChecklistTitle.setFocusableInTouchMode(true);
mChecklistTitle.setClickable(true);
mChecklistTitle.setCursorVisible(true);
// 获得焦点并弹出键盘
mChecklistTitle.requestFocus();
mChecklistTitle.setSelection(mChecklistTitle.getText().length());
// 强制弹出键盘
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(mChecklistTitle, InputMethodManager.SHOW_FORCED);
}
return true; // 消耗长按事件,避免触发其他长按事件
}
});
// 添加焦点变化监听器,失去焦点时保存修改并恢复为不可编辑状态
mChecklistTitle.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// 失去焦点时,保存修改并恢复为不可编辑状态
mChecklistTitle.setFocusable(false);
mChecklistTitle.setFocusableInTouchMode(false);
mChecklistTitle.setClickable(false);
mChecklistTitle.setCursorVisible(false);
}
}
});
} else {
mAlert.setVisibility(View.GONE);
// 普通模式显示TextView隐藏编辑框
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
if (data.hasAlert()) {
mAlert.setImageResource(R.drawable.clock);
mAlert.setVisibility(View.VISIBLE);
} else {
mAlert.setVisibility(View.GONE);
}
}
}
}
// 设置修改时间
mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate()));
@ -148,15 +323,44 @@ public class NotesListItem extends LinearLayout {
setBackground(data);
}
/**
*
*/
private void updateChecklistStatus() {
if (mChecklistStatus == null || mItemData == null) {
return;
}
// TODO: 根据清单完成情况更新状态图标
// 这里可以实现逻辑,检查清单中已完成项的比例,显示不同的状态图标
mChecklistStatus.setImageResource(R.drawable.clock);
}
/**
*
* @param isChecked
*/
private void updateChecklistStyle(boolean isChecked) {
if (isChecked) {
// 已完成:显示删除线,文字变暗
mChecklistTitle.setPaintFlags(mChecklistTitle.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
mChecklistTitle.setTextColor(Color.GRAY);
} else {
// 未完成:正常显示
mChecklistTitle.setPaintFlags(mChecklistTitle.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
mChecklistTitle.setTextColor(Color.BLACK);
}
}
/**
*
* @param data
*/
private void setBackground(NoteItemData data) {
int id = data.getBgColorId();
if (data.getType() == Notes.TYPE_NOTE) {
// 根据笔记在列表中的位置选择不同的背景
if (data.getType() == Notes.TYPE_NOTE || data.getType() == Notes.TYPE_CHECKLIST) {
// 根据笔记或清单在列表中的位置选择不同的背景
if (data.isSingle() || data.isOneFollowingFolder()) {
setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id));
} else if (data.isLast()) {

@ -0,0 +1,32 @@
#!/bin/bash
echo "Checking Android project structure..."
# Check if this is an Android project
if [ -f "AndroidManifest.xml" ]; then
echo "Found AndroidManifest.xml"
else
echo "Error: No AndroidManifest.xml found"
exit 1
fi
# Check if src directory exists
if [ -d "src" ]; then
echo "Found src directory"
else
echo "Error: No src directory found"
exit 1
fi
# Check if res directory exists
if [ -d "res" ]; then
echo "Found res directory"
else
echo "Error: No res directory found"
exit 1
fi
echo "Project structure is valid!"
echo "The project should be ready to build with Android SDK tools."
echo "You can use the following command to build the project:"
echo "android update project -p . && ant debug"
Loading…
Cancel
Save