diff --git a/doc/1 b/doc/1
deleted file mode 100644
index e69de29..0000000
diff --git a/doc/ui设计类图.png b/doc/ui设计类图.png
new file mode 100644
index 0000000..05b5d84
Binary files /dev/null and b/doc/ui设计类图.png differ
diff --git a/doc/分析类图.png b/doc/分析类图.png
new file mode 100644
index 0000000..ad7a782
Binary files /dev/null and b/doc/分析类图.png differ
diff --git a/doc/小米便签维护-需求与设计方案_崔凌宵.docx b/doc/小米便签维护-需求与设计方案_崔凌宵.docx
index c45cdc5..6fe6c2d 100644
Binary files a/doc/小米便签维护-需求与设计方案_崔凌宵.docx and b/doc/小米便签维护-需求与设计方案_崔凌宵.docx differ
diff --git a/doc/展示ppt.pptx b/doc/展示ppt.pptx
new file mode 100644
index 0000000..5cdf80f
Binary files /dev/null and b/doc/展示ppt.pptx differ
diff --git a/doc/插入图片用例顺序图.png b/doc/插入图片用例顺序图.png
new file mode 100644
index 0000000..c779ec9
Binary files /dev/null and b/doc/插入图片用例顺序图.png differ
diff --git a/doc/插入声音用例顺序图.png b/doc/插入声音用例顺序图.png
new file mode 100644
index 0000000..f889458
Binary files /dev/null and b/doc/插入声音用例顺序图.png differ
diff --git a/doc/注释代码1089行与新功能代码364行.md b/doc/注释代码1089行与新功能代码364行.md
new file mode 100644
index 0000000..d9be11e
--- /dev/null
+++ b/doc/注释代码1089行与新功能代码364行.md
@@ -0,0 +1,2 @@
+注释代码 506+344+239 = 1089
+新功能代码 364
\ No newline at end of file
diff --git a/doc/类设计图.png b/doc/类设计图.png
new file mode 100644
index 0000000..fa8c284
Binary files /dev/null and b/doc/类设计图.png differ
diff --git a/doc/软件体系结构图.png b/doc/软件体系结构图.png
new file mode 100644
index 0000000..c740853
Binary files /dev/null and b/doc/软件体系结构图.png differ
diff --git a/src/Notes/res/layout/activity_main.xml b/src/Notes/res/layout/activity_main.xml
new file mode 100644
index 0000000..86a5d97
--- /dev/null
+++ b/src/Notes/res/layout/activity_main.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes/res/layout/note_edit.xml b/src/Notes/res/layout/note_edit.xml
index 10b2aa7..3e5ba0c 100644
--- a/src/Notes/res/layout/note_edit.xml
+++ b/src/Notes/res/layout/note_edit.xml
@@ -74,6 +74,13 @@
android:layout_height="7dip"
android:background="@drawable/bg_color_btn_mask" />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes/res/values-night/themes.xml b/src/Notes/res/values-night/themes.xml
new file mode 100644
index 0000000..ad0fd96
--- /dev/null
+++ b/src/Notes/res/values-night/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes/res/values/strings.xml b/src/Notes/res/values/strings.xml
index 55df868..1771bc6 100644
--- a/src/Notes/res/values/strings.xml
+++ b/src/Notes/res/values/strings.xml
@@ -39,6 +39,8 @@
/MIUI/notes/
notes_%s.txt
+ Insert image
+ Insert audio
(%d)
New Folder
Export text
diff --git a/src/Notes/res/values/styles.xml b/src/Notes/res/values/styles.xml
index d750e65..ad0d90d 100644
--- a/src/Notes/res/values/styles.xml
+++ b/src/Notes/res/values/styles.xml
@@ -64,6 +64,6 @@
\ No newline at end of file
diff --git a/src/Notes/res/values/themes.xml b/src/Notes/res/values/themes.xml
new file mode 100644
index 0000000..aa02b68
--- /dev/null
+++ b/src/Notes/res/values/themes.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes/src/net/micode/notes/ui/NoteEditActivity.java b/src/Notes/src/net/micode/notes/ui/NoteEditActivity.java
index 96a9ff8..20f2435 100644
--- a/src/Notes/src/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/Notes/src/net/micode/notes/ui/NoteEditActivity.java
@@ -16,25 +16,45 @@
package net.micode.notes.ui;
+import android.Manifest;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Paint;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Environment;
import android.preference.PreferenceManager;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.text.Editable;
+import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.DateUtils;
+import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan;
+import android.text.style.ClickableSpan;
+import android.text.style.ImageSpan;
+import android.text.style.URLSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -42,11 +62,14 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.view.WindowManager;
+import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -65,6 +88,8 @@ import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -74,6 +99,8 @@ import java.util.regex.Pattern;
public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener {
+ private static final int PHOTO_REQUEST = 1;
+
private class HeadViewHolder {
public TextView tvModified;
@@ -119,7 +146,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final String TAG = "NoteEditActivity";
+ private static final int REQUEST_IMAGE_SELECT = 1;
+ private static final int RECORD_REQUEST = 1987;
+ private Uri selectedAudioUri;
private HeadViewHolder mNoteHeaderHolder;
private View mHeadViewPanel;
@@ -140,12 +170,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
-
+ private static final int REQUEST_AUDIO_SELECT = 2;
public static final String TAG_CHECKED = String.valueOf('\u221A');
public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
private LinearLayout mEditTextList;
+ private LinearLayout audioContainer;
+
+ private MediaPlayer mediaPlayer;
+
private String mUserQuery;
private Pattern mPattern;
@@ -158,6 +192,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
return;
}
+
+ audioContainer = findViewById(R.id.audioContainer);
+
initResources();
}
@@ -293,8 +330,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* is not ready
*/
showAlertHeader();
+
+ convertToImage();
}
+
private void showAlertHeader() {
if (mWorkingNote.hasClockAlert()) {
long time = System.currentTimeMillis();
@@ -312,6 +352,97 @@ public class NoteEditActivity extends Activity implements OnClickListener,
};
}
+ private void convertToImage() {
+ NoteEditText noteEditText = findViewById(R.id.note_edit_view);
+ Editable editable = noteEditText.getEditableText();
+
+ String noteText = editable.toString();
+ int length = editable.length();
+
+ int cursorPositionBeforeInsert = noteEditText.getSelectionStart();
+ // 在光标位置插入换行符
+
+ noteEditText.setSelection(length);
+
+ boolean inserted = false;
+ for (int i = 0; i < length; i++) {
+ for (int j = i; j < length; j++) {
+ String img_fragment = noteText.substring(i, j + 1);
+ if (img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")) {
+ int limit = 7;
+ int len = img_fragment.length() - 15;
+ String path = img_fragment.substring(limit, limit + len);
+ Bitmap bitmap = BitmapFactory.decodeFile(path);
+ if (bitmap != null) {
+ int desiredHeight = 2000;
+ int originalWidth = bitmap.getWidth();
+ int originalHeight = bitmap.getHeight();
+ int desiredWidth = (originalWidth * desiredHeight) / originalHeight;
+
+ Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, desiredWidth, desiredHeight, false);
+
+ ImageSpan imageSpan = new ImageSpan(this, scaledBitmap);
+ String ss = "[local]" + path + "[/local]";
+ SpannableString spannableString = new SpannableString(ss);
+ spannableString.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER), 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 设置居中对齐
+ spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ // 添加ClickableSpan,使得点击图片末尾的光标可以和图片对齐
+ ClickableSpan clickableSpan = new ClickableSpan() {
+ @Override
+ public void onClick(View view) {
+ int selectionEnd = noteEditText.getSelectionEnd();
+ if (selectionEnd == cursorPositionBeforeInsert) {
+ noteEditText.setSelection(cursorPositionBeforeInsert + 1);
+ }
+ }
+ };
+ spannableString.setSpan(clickableSpan, ss.length(), ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ editable.replace(i, i + len + 15, spannableString);
+
+ inserted = true;
+ noteEditText.setSelection(cursorPositionBeforeInsert);
+
+ ClickableSpan[] spans = editable.getSpans(cursorPositionBeforeInsert, cursorPositionBeforeInsert, ClickableSpan.class);
+ if (spans != null && spans.length > 0) {
+ for (ClickableSpan span : spans) {
+ editable.removeSpan(span);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (inserted) {
+ editable.append("\n");
+ // 在插入图片后为NoteEditText设置触摸事件监听器
+ noteEditText.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ int action = event.getAction();
+ if (action == MotionEvent.ACTION_DOWN) {
+ int offset = noteEditText.getOffsetForPosition(event.getX(), event.getY());
+ ImageSpan[] imageSpans = editable.getSpans(0, editable.length(), ImageSpan.class);
+ for (ImageSpan span : imageSpans) {
+ int start = editable.getSpanStart(span);
+ int end = editable.getSpanEnd(span);
+ if (offset >= start && offset <= end) {
+ // 如果光标位于图片所在行,返回true,表示消费了该事件
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ });
+
+ }
+ }
+
+
+
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@@ -547,12 +678,257 @@ public class NoteEditActivity extends Activity implements OnClickListener,
case R.id.menu_delete_remind:
mWorkingNote.setAlertDate(0, false);
break;
+ case R.id.menu_insert_image:
+ Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT);
+ loadImage.addCategory(Intent.CATEGORY_OPENABLE);
+ loadImage.setType("image/*");
+ startActivityForResult(loadImage, PHOTO_REQUEST);
+ break;
+// Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+// startActivityForResult(intent, REQUEST_IMAGE_SELECT);
+ case R.id.menu_insert_audio:
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("audio/*");
+ startActivityForResult(intent, REQUEST_AUDIO_SELECT);
+// openAudioSelector();
+ break;
default:
break;
}
return true;
}
+
+// private void openImageSelector() {
+// Intent intent = new Intent(Intent.ACTION_PICK);
+// intent.setType("image/*");
+// startActivityForResult(intent, REQUEST_IMAGE_SELECT);
+// }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ super.onActivityResult(requestCode, resultCode, intent);
+ ContentResolver resolver = getContentResolver();
+ switch (requestCode) {
+ case PHOTO_REQUEST:
+ Uri originalUri = intent.getData(); //1.获得图片的真实路径
+ addImage(resolver,originalUri);
+ break;
+ case REQUEST_AUDIO_SELECT:
+ selectedAudioUri = intent.getData();
+ String fileName = getFileName(selectedAudioUri);
+ addAudioComponent(fileName, selectedAudioUri);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private String getFileName(Uri uri) {
+ String result = null;
+ if (uri.getScheme().equals("content")) {
+ try (Cursor cursor = getContentResolver().query(uri, null, null, null, null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+ }
+ }
+ }
+ if (result == null) {
+ result = uri.getPath();
+ int cut = result.lastIndexOf('/');
+ if (cut != -1) {
+ result = result.substring(cut + 1);
+ }
+ }
+ return result;
+ }
+
+
+ private void addImage(ContentResolver resolver,Uri originalUri) {
+ Bitmap bitmap = null;
+ try {
+ bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片
+ } catch (FileNotFoundException e) {
+ Log.d(TAG, "onActivityResult: get file_exception");
+ e.printStackTrace();
+ }
+
+ if (bitmap != null) {
+ //3.根据Bitmap对象创建ImageSpan对象
+ Log.d(TAG, "onActivityResult: bitmap is not null");
+ ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
+ String path = getPath(this, originalUri);
+ //4.使用[local][/local]将path括起来,用于之后方便识别图片路径在note中的位置
+ String img_fragment = "[local]" + path + "[/local]";
+ //创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
+ SpannableString spannableString = new SpannableString(img_fragment);
+ spannableString.setSpan(imageSpan, 0, img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ //5.将选择的图片追加到EditText中光标所在位置
+ NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view);
+ int index = e.getSelectionStart(); //获取光标所在位置
+ Log.d(TAG, "Index是: " + index);
+ Editable edit_text = e.getEditableText();
+ edit_text.insert(index, spannableString); //将图片插入到光标所在位置
+
+//
+// // 添加以下代码来在图片插入后自动换行
+// edit_text.insert(index + spannableString.length(), "\n");// 在图片后添加一个换行符
+//
+// // 更新光标
+// e.setSelection(index + spannableString.length() + 1); // 将光标移动到换行符后面
+
+ mWorkingNote.mContent = e.getText().toString();
+ mWorkingNote.mContent = mWorkingNote.mContent.replaceAll("(?m)^[ \t]*\r?\n", ""); // 删除空白行
+
+
+// //6.把改动提交到数据库中,两个数据库表都要改的
+// ContentResolver contentResolver = getContentResolver();
+// ContentValues contentValues = new ContentValues();
+// final long id = mWorkingNote.getNoteId();
+// contentValues.put("snippet",mWorkingNote.mContent);
+// contentResolver.update(Uri.parse("content://micode_notes/note"), contentValues,"_id=?",new String[]{""+id});
+// ContentValues contentValues1 = new ContentValues();
+// contentValues1.put("content",mWorkingNote.mContent);
+// contentResolver.update(Uri.parse("content://micode_notes/data"), contentValues1,"mime_type=? and note_id=?", new String[]{"vnd.android.cursor.item/text_note",""+id});
+ } else {
+ Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private void addAudioComponent(String fileName, final Uri uri) {
+ LinearLayout audioLayout = new LinearLayout(this);
+ audioLayout.setOrientation(LinearLayout.HORIZONTAL);
+ audioLayout.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ audioLayout.setPadding(0, 16, 0, 16);
+
+ TextView audioFileName = new TextView(this);
+ audioFileName.setText(fileName);
+ audioFileName.setLayoutParams(new LinearLayout.LayoutParams(
+ 0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
+
+ Button playAudioButton = new Button(this);
+ playAudioButton.setText("Play");
+ playAudioButton.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ playAudioButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ playAudio(uri);
+ }
+ });
+
+ audioLayout.addView(audioFileName);
+ audioLayout.addView(playAudioButton);
+ audioContainer.addView(audioLayout);
+ }
+
+ private void playAudio(Uri uri) {
+ if (mediaPlayer != null) {
+ mediaPlayer.release();
+ }
+ mediaPlayer = MediaPlayer.create(this, uri);
+ mediaPlayer.start();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mediaPlayer != null) {
+ mediaPlayer.release();
+ mediaPlayer = null;
+ }
+ }
+
+
+ public String getPath(final Context context, final Uri uri) {
+
+ final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+
+ // DocumentProvider
+ if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+ // ExternalStorageProvider
+ if (isExternalStorageDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ if ("primary".equalsIgnoreCase(type)) {
+ return Environment.getExternalStorageDirectory() + "/" + split[1];
+ }
+ }
+// // DownloadsProvider
+ else if (isDownloadsDocument(uri)) {
+ final String id = DocumentsContract.getDocumentId(uri);
+ final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+ return getDataColumn(context, contentUri, null, null);
+ }
+ // MediaProvider
+ else
+ if (isMediaDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ Uri contentUri = null;
+ if ("image".equals(type)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ }
+
+ final String selection = "_id=?";
+ final String[] selectionArgs = new String[]{split[1]};
+
+ return getDataColumn(context, contentUri, selection, selectionArgs);
+ }
+ }
+ // Media
+ else if ("content".equalsIgnoreCase(uri.getScheme())) {
+ return getDataColumn(context, uri, null, null);
+ }
+ // File
+ else if ("file".equalsIgnoreCase(uri.getScheme())) {
+ return uri.getPath();
+ }
+ return null;
+ }
+
+ //获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。
+ public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+
+ Cursor cursor = null;
+ final String column = "_data";
+ final String[] projection = {column};
+
+ try {
+ cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ final int column_index = cursor.getColumnIndexOrThrow(column);
+ return cursor.getString(column_index);
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ return null;
+ }
+ //是否为外部存储文件
+ public boolean isExternalStorageDocument(Uri uri) {
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
+ }
+
+ //是否为下载文件
+ public boolean isDownloadsDocument(Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
+ //是否为媒体文件
+ public boolean isMediaDocument(Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
+ }
+
+
+
private void setReminder() {
DateTimePickerDialog d = new DateTimePickerDialog(this, System.currentTimeMillis());
d.setOnDateTimeSetListener(new OnDateTimeSetListener() {
@@ -725,6 +1101,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return spannable;
}
+
private View getListItem(String item, int index) {
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
@@ -870,4 +1247,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show();
}
+
+
}