diff --git a/src/main/java/model/WorkingNote.java b/src/main/java/model/WorkingNote.java index 0886c78..f71a797 100644 --- a/src/main/java/model/WorkingNote.java +++ b/src/main/java/model/WorkingNote.java @@ -38,7 +38,7 @@ public class WorkingNote { // Note Id private long mNoteId; // Note content - private String mContent; + public String mContent; // Note mode private int mMode; @@ -203,7 +203,7 @@ public class WorkingNote { public synchronized boolean saveNote() { if (isWorthSaving()) { //是否值得保存 if (!existInDatabase()) { // 是否存在数据库中 - if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { + if ((mNoteId = net.micode.notes.model.Note.getNewNoteId(mContext, mFolderId)) == 0) { Log.e(TAG, "Create new note fail with id:" + mNoteId); return false; } diff --git a/src/main/java/ui/NoteEditActivity.java b/src/main/java/ui/NoteEditActivity.java index aa5db14..969f313 100644 --- a/src/main/java/ui/NoteEditActivity.java +++ b/src/main/java/ui/NoteEditActivity.java @@ -18,6 +18,17 @@ package net.micode.notes.ui; import android.Manifest; +import android.annotation.SuppressLint; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; import android.speech.tts.TextToSpeech.OnInitListener; import android.app.AlarmManager; import android.app.AlertDialog; @@ -42,6 +53,7 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.text.format.DateUtils; import android.text.style.BackgroundColorSpan; +import android.text.style.ImageSpan; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -74,6 +86,7 @@ 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.util.HashMap; import java.util.HashSet; import java.util.Locale; @@ -163,6 +176,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10; + private static final int PHOTO_REQUEST=1; + public static final String TAG_CHECKED = String.valueOf('\u221A'); public static final String TAG_UNCHECKED = String.valueOf('\u25A1'); @@ -187,6 +202,24 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen initResources(); count(); read(); + + //根据id获取添加图片按钮 + final ImageButton add_img_btn = (ImageButton) findViewById(R.id.add_img_btn); + //为点击图片按钮设置监听器 + add_img_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Log.d(TAG, "onClick: click add image button"); + //ACTION_GET_CONTENT: 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音) + Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT); + //Category属性用于指定当前动作(Action)被执行的环境. + //CATEGORY_OPENABLE; 用来指示一个ACTION_GET_CONTENT的intent + loadImage.addCategory(Intent.CATEGORY_OPENABLE); + loadImage.setType("image/*"); + startActivityForResult(loadImage, PHOTO_REQUEST); + + } + }); } /** @@ -311,6 +344,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen mNoteEditor.setTextAppearance(this, TextAppearanceResources .getTexAppearanceResource(mFontSizeId)); //设置外观 + if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { switchToListMode(mWorkingNote.getContent()); } else { @@ -332,6 +366,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen * TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker * is not ready */ + convertToImage(); showAlertHeader(); } //设置闹钟的显示 @@ -580,14 +615,6 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //根据菜单的id来编剧相关项目 - case R.id.action_insert_image: - //绑定按钮的点击响应,获取危险权限,这里的100是申请码,可以自己定义,整数即可 - ActivityCompat.requestPermissions(NoteEditActivity.this, mPermissionList, 100); -//用于获取焦点,否则插入图片时没有响应 - mNoteEditor.getFocusable(); - mNoteEditor.insertImage(realPathFromUri, realPathFromUri + "\" style=\"max-width:100%"); - break; - case R.id.menu_new_note: //创建一个新的便签 createNewNote(); @@ -1133,8 +1160,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen int flag1 = -1; int flag2 = -1; do{//不计入表示图片的字符 - flag1 = stringBuffer.indexOf(""); + flag1 = stringBuffer.indexOf("[local]"); + flag2 = stringBuffer.indexOf("[/local]")+7; if (flag1 != -1 && flag2 != -1){ stringBuffer = stringBuffer.replace(flag1,flag2+1,""); } @@ -1189,7 +1216,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen read.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mTTS.speak(mNoteEditor.getText().toString(),TextToSpeech.QUEUE_FLUSH,null); + mTTS.speak(TextChange(mNoteEditor.getText().toString()),TextToSpeech.QUEUE_FLUSH,null); } }); @@ -1207,4 +1234,187 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen // } // }); + + //路径字符串格式 转换为 图片image格式 + private void convertToImage() { + net.micode.notes.ui.NoteEditText noteEditText = (net.micode.notes.ui.NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit + Editable editable = noteEditText.getText();//1.获取text + String noteText = editable.toString(); //2.将note内容转换为字符串 + int length = editable.length(); //内容的长度 + //3.截取img片段 [local]+uri+[local],提取uri + for(int i = 0; i < length; i++) { + for(int j = i; j < length; j++) { + String img_fragment = noteText.substring(i, j+1); //img_fragment:关于图片路径的片段 + if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")){ + int limit = 7; //[local]为7个字符 + //[local][/local]共15个字符,剩下的为真正的path长度 + int len = img_fragment.length()-15; + //从[local]之后的len个字符就是path + String path = img_fragment.substring(limit,limit+len);//获取到了图片路径 + Bitmap bitmap = null; + Log.d(TAG, "图片的路径是:"+path); + try { + bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式 + } catch (Exception e) { + e.printStackTrace(); + } + if(bitmap!=null){ //若图片存在 + Log.d(TAG, "图片不为null"); + ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap); + //4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像 + String ss = "[local]" + path + "[/local]"; + SpannableString spannableString = new SpannableString(ss); + //5.将指定的标记对象附加到文本的开始...结束范围 + spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + Log.d(TAG, "Create spannable string success!"); + Editable edit_text = noteEditText.getEditableText(); + edit_text.delete(i,i+len+15); //6.删掉图片路径的文字 + edit_text.insert(i, spannableString); //7.在路径的起始位置插入图片 + } + } + } + } + } + + //重写onActivityResult()来处理返回的数据 + 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.获得图片的真实路径 + 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中光标所在位置 + net.micode.notes.ui.NoteEditText e = (net.micode.notes.ui.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); //将图片插入到光标所在位置 + + mWorkingNote.mContent = e.getText().toString(); + //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(); + } + + break; + default: + break; + } + } + + //获取文件的real path + + @SuppressLint("NewApi") + public static String getPath(final Context context, final Uri uri) { + if (uri == null) { + return null; + } + // 判斷是否為Android 4.4之後的版本 + final boolean after44 = Build.VERSION.SDK_INT >= 19; + if (after44 && DocumentsContract.isDocumentUri(context, uri)) { + // 如果是Android 4.4之後的版本,而且屬於文件URI + final String authority = uri.getAuthority(); + // 判斷Authority是否為本地端檔案所使用的 + if ("com.android.externalstorage.documents".equals(authority)) { + // 外部儲存空間 + final String docId = DocumentsContract.getDocumentId(uri); + final String[] divide = docId.split(":"); + final String type = divide[0]; + if ("primary".equals(type)) { + String path = Environment.getExternalStorageDirectory().getAbsolutePath().concat("/").concat(divide[1]); + return path; + } else { + String path = "/storage/".concat(type).concat("/").concat(divide[1]); + return path; + } + } else if ("com.android.providers.downloads.documents".equals(authority)) { + // 下載目錄 + final String docId = DocumentsContract.getDocumentId(uri); + if (docId.startsWith("raw:")) { + final String path = docId.replaceFirst("raw:", ""); + return path; + } + final Uri downloadUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.parseLong(docId)); + String path = queryAbsolutePath(context, downloadUri); + return path; + } else if ("com.android.providers.media.documents".equals(authority)) { + // 圖片、影音檔案 + final String docId = DocumentsContract.getDocumentId(uri); + final String[] divide = docId.split(":"); + final String type = divide[0]; + Uri mediaUri = null; + if ("image".equals(type)) { + mediaUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + mediaUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + mediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } else { + return null; + } + mediaUri = ContentUris.withAppendedId(mediaUri, Long.parseLong(divide[1])); + String path = queryAbsolutePath(context, mediaUri); + return path; + } + } else { + // 如果是一般的URI + final String scheme = uri.getScheme(); + String path = null; + if ("content".equals(scheme)) { + // 內容URI + path = queryAbsolutePath(context, uri); + } else if ("file".equals(scheme)) { + // 檔案URI + path = uri.getPath(); + } + return path; + } + return null; + } + + public static String queryAbsolutePath(final Context context, final Uri uri) { + final String[] projection = {MediaStore.MediaColumns.DATA}; + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(uri, projection, null, null, null); + if (cursor != null && cursor.moveToFirst()) { + final int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA); + return cursor.getString(index); + } + } catch (final Exception ex) { + ex.printStackTrace(); + if (cursor != null) { + cursor.close(); + } + } + return null; + } + } diff --git a/src/main/res/drawable-hdpi/laba1.png b/src/main/res/drawable-hdpi/laba1.png new file mode 100644 index 0000000..0a14a7d Binary files /dev/null and b/src/main/res/drawable-hdpi/laba1.png differ diff --git a/src/main/res/drawable-hdpi/photo.png b/src/main/res/drawable-hdpi/photo.png new file mode 100644 index 0000000..57d9d19 Binary files /dev/null and b/src/main/res/drawable-hdpi/photo.png differ diff --git a/src/main/res/drawable-hdpi/photo1.png b/src/main/res/drawable-hdpi/photo1.png new file mode 100644 index 0000000..8390f20 Binary files /dev/null and b/src/main/res/drawable-hdpi/photo1.png differ diff --git a/src/main/res/drawable-hdpi/voice.png b/src/main/res/drawable-hdpi/voice.png new file mode 100644 index 0000000..23de69b Binary files /dev/null and b/src/main/res/drawable-hdpi/voice.png differ diff --git a/src/main/res/layout/note_edit.xml b/src/main/res/layout/note_edit.xml index 9a562c4..9cbda0a 100644 --- a/src/main/res/layout/note_edit.xml +++ b/src/main/res/layout/note_edit.xml @@ -42,12 +42,19 @@ android:layout_marginRight="8dip" android:textAppearance="@style/TextAppearanceSecondaryItem" /> - + @@ -100,6 +107,7 @@ android:layout_height="7dip" android:background="@drawable/bg_color_btn_mask" /> +