新功能代码与图 #15

Merged
mzvoe5kay merged 1 commits from develop into main 2 years ago

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@ -0,0 +1,2 @@
注释代码 506+344+239 = 1089
新功能代码 364

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -74,6 +74,13 @@
android:layout_height="7dip"
android:background="@drawable/bg_color_btn_mask" />
<LinearLayout
android:id="@+id/audioContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="16dp"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dip"
@ -123,6 +130,8 @@
android:background="@drawable/bg_color_btn_mask"
android:layout_gravity="top|right" />
<LinearLayout
android:id="@+id/note_bg_color_selector"
android:layout_width="wrap_content"

@ -49,4 +49,10 @@
<item
android:id="@+id/menu_delete_remind"
android:title="@string/menu_remove_remind" />
<item
android:id="@+id/menu_insert_image"
android:title="@string/menu_insert_image" />
<item
android:id="@+id/menu_insert_audio"
android:title="@string/menu_insert_audio" />
</menu>

@ -0,0 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.Notes" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>

@ -39,6 +39,8 @@
<string name="file_path">/MIUI/notes/</string>
<string name="file_name_txt_format">notes_%s.txt</string>
<!-- notes list string -->
<string name="menu_insert_image">Insert image</string>
<string name="menu_insert_audio">Insert audio</string>
<string name="format_folder_files_count">(%d)</string>
<string name="menu_create_folder">New Folder</string>
<string name="menu_export_text">Export text</string>

@ -64,6 +64,6 @@
<style name="NoteActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
<item name="android:displayOptions" />
<item name="android:visibility">gone</item>
<item name="android:visibility">visible</item>
</style>
</resources>

@ -0,0 +1,9 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.Notes" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.Notes" parent="Base.Theme.Notes" />
</resources>

@ -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();
}
}

Loading…
Cancel
Save