修改图片不能正常插入的bug,兼容了富文本 #23

Merged
p82feo7wg merged 1 commits from wangjiaqi_branch into master 2 months ago

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M2,20h20v4H2V20zM5.49,17h2.42l1.27,-3.58h5.65L16.09,17h2.42L13.25,3h-2.5L5.49,17zM9.91,11.39l2.03,-5.79h0.12l2.03,5.79H9.91z"/>
</vector>

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M15.6,10.79c0.97,-0.67 1.65,-1.77 1.65,-2.79 0,-2.26 -1.75,-4 -4,-4L7,4v14h7.04c2.09,0 3.71,-1.7 3.71,-3.79 0,-1.52 -0.86,-2.82 -2.15,-3.42zM10,6.5h3c0.83,0 1.5,0.67 1.5,1.5s-0.67,1.5 -1.5,1.5h-3v-3zM13.5,15.5L10,15.5v-3h3.5c0.83,0 1.5,0.67 1.5,1.5s-0.67,1.5 -1.5,1.5z"/>
</vector>

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M10,4v3h2.21l-3.42,8H6v3h8v-3h-2.21l3.42,-8H18V4z"/>
</vector>

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z"/>
</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>

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/new_note_pressed" />
<item
android:drawable="@drawable/new_note_normal" />
</selector>

@ -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>

@ -191,55 +191,7 @@
</LinearLayout>
<!-- 富文本工具栏 - 放置在页面底部 -->
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#F5F5F5"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="4dp">
<ImageButton
android:id="@+id/btn_bold"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_edit"
android:contentDescription="@string/formatting_bold" />
<ImageButton
android:id="@+id/btn_italic"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_edit"
android:contentDescription="@string/formatting_italic" />
<ImageButton
android:id="@+id/btn_underline"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/ic_menu_edit"
android:contentDescription="@string/formatting_underline" />
<!-- 插入图片按钮 -->
<ImageButton
android:id="@+id/btn_insert_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@android:drawable/ic_menu_gallery"
android:background="@drawable/bg_btn_set_color"
android:layout_marginRight="8dip" />
<ImageButton
android:id="@+id/btn_set_bg_color_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_btn_set_color" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
<ImageView

@ -35,7 +35,11 @@
<string name="note_link_email">发送邮件</string>
<string name="note_link_web">浏览网页</string>
<string name="note_link_other">打开地图</string>
<!-- Text export file information -->
<string name="file_path">/MIUI/notes/</string>
<string name="file_name_txt_format">notes_%s.txt</string>
<!-- note list string -->
<string name="format_folder_files_count">(%d)</string>
<string name="menu_create_folder">新建文件夹</string>
<string name="menu_export_text">导出文本</string>
<string name="menu_sync">同步</string>
@ -84,6 +88,8 @@
<string name="error_note_not_exist">要查看的便签不存在</string>
<string name="error_note_empty_for_clock">不能为空便签设置闹钟提醒</string>
<string name="error_note_empty_for_send_to_desktop">不能将空便签发送到桌面</string>
<string name="error_permission_denied">权限被拒绝,无法访问图片</string>
<string name="error_image_insert_failed">插入图片失败,请重试</string>
<string name="success_sdcard_export">导出成功</string>
<string name="failed_sdcard_export">导出失败</string>
<string name="format_exported_file_location">已将文本文件(%1$s)输出至SD卡(%2$s)目录</string>
@ -117,7 +123,11 @@
<string name="preferences_toast_cannot_change_account">正在同步中,不能修改同步帐号</string>
<string name="preferences_toast_success_set_accout">同步帐号已设置为%1$s</string>
<string name="preferences_bg_random_appear_title">新建便签背景颜色随机</string>
<string name="preferences_last_sync_time_format">yyyy-MM-dd hh:mm:ss</string>
<string name="button_delete">删除</string>
<string name="formatting_bold">粗体</string>
<string name="formatting_italic">斜体</string>
<string name="formatting_underline">下划线</string>
<string name="call_record_folder_name">通话便签</string>
<string name="hint_foler_name">请输入名称</string>
<string name="search_label">正在搜索便签</string>

@ -146,8 +146,11 @@
<string name="password_set_dialog_message">Enter password please</string>
<string name="password_error">Error, try again</string>
<string name="password_empty">The password can not be empty</string>
<string name="formatting_bold">Bold</string>
<string name="formatting_italic">Italic</string>
<string name="formatting_underline">Underline</string>
<plurals name="search_results_title">
<item quantity="one"><xliff:g id="number" example="1">%1$s</xliff:g> result for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
<item quantity="one"><xliff:g id="number" example="1">%1$s</xliff:g> result for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
<!-- Case of 0 or 2 or more results. -->
<item quantity="other"><xliff:g id="number" example="15">%1$s</xliff:g> results for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
</plurals>

@ -40,6 +40,7 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
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;
@ -48,6 +49,11 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import android.util.Base64;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@ -357,7 +363,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.e(TAG, "Some views are not initialized! Check initResources method.");
return;
}
// 设置富文本编辑器字体大小
setRichEditorFontSize(mFontSizeId);
@ -370,46 +376,111 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 切换到富文本模式
mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE);
// 获取笔记原始内容(为空则赋空字符串,避免空指针)
String content = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
// 检查内容是否已经是HTML格式如果是则直接加载
// 无论内容是否为HTML格式都检查并处理[IMAGE]标记
String finalHtml = content;
// 如果内容不是HTML格式比如旧笔记则处理图片标记
if (!TextUtils.isEmpty(content) && (!content.startsWith("<") || !content.contains("</"))) {
// 处理 [IMAGE] 标签,转换为 HTML img 标签
Pattern imgPattern = Pattern.compile("\\[IMAGE\\]([^\\[]+)\\[/IMAGE\\]");
Matcher imgMatcher = imgPattern.matcher(content);
// 处理 [IMAGE] 标签,转换为 HTML img 标签
Pattern imgPattern = Pattern.compile("\\[IMAGE\\]([^\\[]+)\\[/IMAGE\\]");
Matcher imgMatcher = imgPattern.matcher(content);
// 检查是否包含[IMAGE]标记
if (imgMatcher.find()) {
// 重新创建匹配器因为第一次find会移动指针
imgMatcher = imgPattern.matcher(content);
StringBuffer htmlContent = new StringBuffer();
// 遍历替换所有[IMAGE]标记为<img>标签
while (imgMatcher.find()) {
String imgUri = imgMatcher.group(1); // 提取图片URI
// 检查是否为本地文件路径
if (imgUri.startsWith("file://") || imgUri.startsWith("/")) {
String imgPath = imgUri.startsWith("file://") ? imgUri.substring(7) : imgUri;
File imgFile = new File(imgPath);
String imgUri = imgMatcher.group(1); // 提取图片路径
Log.d(TAG, "Processing image URI: " + imgUri);
String imgHtmlUrl = "";
boolean isValidImage = false;
// 检查图片路径类型并生成有效的HTML图片URL
if (imgUri.startsWith("file://")) {
// 处理file://前缀的路径
String filePath = imgUri.substring(7);
File imgFile = new File(filePath);
if (imgFile.exists() && imgFile.isFile()) {
String imgHtmlUrl = "file://" + imgPath;
String imgHtmlTag = "<img src=\"" + imgHtmlUrl + "\" width=\"200\" height=\"200\"/><br/>";
imgMatcher.appendReplacement(htmlContent, imgHtmlTag);
// 对于本地文件转换为Base64编码以确保在WebView中显示
try {
InputStream is = new FileInputStream(imgFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
String base64Data = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
imgHtmlUrl = "data:image/jpeg;base64," + base64Data;
isValidImage = true;
is.close();
baos.close();
} catch (IOException e) {
Log.e(TAG, "Error converting file to Base64: " + e.getMessage());
}
} else {
// 如果文件不存在,保留原标记
imgMatcher.appendReplacement(htmlContent, imgMatcher.group(0));
Log.e(TAG, "Image file not found: " + filePath);
}
} else if (imgUri.startsWith("/")) {
// 处理直接的绝对路径
File imgFile = new File(imgUri);
if (imgFile.exists() && imgFile.isFile()) {
// 对于本地文件转换为Base64编码以确保在WebView中显示
try {
InputStream is = new FileInputStream(imgFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
String base64Data = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
imgHtmlUrl = "data:image/jpeg;base64," + base64Data;
isValidImage = true;
is.close();
baos.close();
} catch (IOException e) {
Log.e(TAG, "Error converting file to Base64: " + e.getMessage());
}
} else {
Log.e(TAG, "Image file not found: " + imgUri);
}
} else {
// URI格式直接使用
String imgHtmlTag = "<img src=\"" + imgUri + "\" width=\"200\" height=\"200\"/><br/>";
// 其他URI格式直接使用包括Base64图片
imgHtmlUrl = imgUri;
isValidImage = true;
}
if (isValidImage) {
// 生成HTML img标签
String imgHtmlTag = "<img src=\"" + imgHtmlUrl + "\" width=\"200\" height=\"200\"/><br/>";
imgMatcher.appendReplacement(htmlContent, imgHtmlTag);
Log.d(TAG, "Successfully replaced [IMAGE] tag with HTML img tag: " + imgHtmlTag);
} else {
// 如果图片无效,保留原标记,但添加错误提示
Log.w(TAG, "Invalid image, keeping original tag: " + imgMatcher.group(0));
imgMatcher.appendReplacement(htmlContent, imgMatcher.group(0));
}
}
imgMatcher.appendTail(htmlContent); // 拼接剩余文本
finalHtml = htmlContent.toString();
Log.d(TAG, "Final HTML content after processing [IMAGE] tags: " + finalHtml);
} else {
// 没有[IMAGE]标签直接使用内容作为HTML包括Base64图片
Log.d(TAG, "No [IMAGE] tags found, using content as HTML: " + content);
finalHtml = content;
}
// 用RichEditor加载HTML内容
mNoteEditor.setHtml(finalHtml);
// 更新我们自己维护的HTML内容
mCurrentHtmlContent = finalHtml;
}
// 隐藏所有背景选择的选中状态
@ -478,43 +549,38 @@ public class NoteEditActivity extends Activity implements OnClickListener,
int tagStart = builder.length();
builder.append(fullImageTag);
// 尝试将图片URI转换为Drawable并创建ImageSpan
// 尝试将图片路径转换为Drawable并创建ImageSpan
try {
// 确保URI是有效的
Uri uri = Uri.parse(imageUri);
if (uri == null) {
Log.e(TAG, "Invalid URI: " + imageUri);
// 更新索引,继续处理下一个标签
startIndex = imageEnd + "[/IMAGE]".length();
imageStart = text.indexOf("[IMAGE]", startIndex);
continue;
}
Log.d(TAG, "Attempting to load image from URI: " + uri.toString());
// 使用BitmapFactory直接加载图片这是最可靠的方式
ContentResolver resolver = getContentResolver();
InputStream inputStream = null;
try {
inputStream = resolver.openInputStream(uri);
if (inputStream == null) {
Log.e(TAG, "Failed to open input stream for URI: " + uri.toString());
// 更新索引,继续处理下一个标签
startIndex = imageEnd + "[/IMAGE]".length();
imageStart = text.indexOf("[IMAGE]", startIndex);
continue;
}
// 解码图片
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap == null) {
Log.e(TAG, "Failed to decode bitmap from URI: " + uri.toString());
// 更新索引,继续处理下一个标签
startIndex = imageEnd + "[/IMAGE]".length();
imageStart = text.indexOf("[IMAGE]", startIndex);
continue;
Bitmap bitmap = null;
// 检查图片路径类型本地文件路径或URI
if (imageUri.startsWith("file://")) {
// 处理file://前缀的路径
String filePath = imageUri.substring(7);
Log.d(TAG, "Loading image from file path (with file:// prefix): " + filePath);
bitmap = BitmapFactory.decodeFile(filePath);
} else if (imageUri.startsWith("/")) {
// 处理直接的绝对路径
Log.d(TAG, "Loading image from absolute file path: " + imageUri);
bitmap = BitmapFactory.decodeFile(imageUri);
} else {
// 处理其他URI格式
Log.d(TAG, "Loading image from URI: " + imageUri);
Uri uri = Uri.parse(imageUri);
if (uri != null) {
ContentResolver resolver = getContentResolver();
try (InputStream inputStream = resolver.openInputStream(uri)) {
if (inputStream != null) {
bitmap = BitmapFactory.decodeStream(inputStream);
}
} catch (Exception e) {
Log.e(TAG, "Error loading image from URI: " + e.toString());
}
}
}
// 检查bitmap是否成功加载
if (bitmap != null) {
Log.d(TAG, "Successfully decoded bitmap with dimensions: " + bitmap.getWidth() + "x" + bitmap.getHeight());
// 计算图片的合适大小确保它能适应EditText的宽度
@ -544,20 +610,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 创建ImageSpan并添加到SpannableStringBuilder中
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
builder.setSpan(imageSpan, tagStart, tagStart + fullImageTag.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);
Log.d(TAG, "Successfully added ImageSpan for URI: " + imageUri);
} finally {
// 确保InputStream被正确关闭
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
Log.e(TAG, "Error closing input stream: " + e.toString());
}
}
Log.d(TAG, "Successfully added ImageSpan for: " + imageUri);
} else {
Log.e(TAG, "Failed to decode bitmap from: " + imageUri);
}
} catch (Exception e) {
Log.e(TAG, "Error loading image: " + e.toString());
e.printStackTrace();
}
// 更新索引,继续查找下一个[IMAGE]标签
@ -678,10 +736,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.e(TAG, "RichEditor is null! Check layout file.");
return;
}
// 初始化富文本编辑器配置
initRichEditor();
// 设置富文本编辑器监听器
mNoteEditor.setOnTextChangeListener(new RichEditor.OnTextChangeListener() {
@Override
@ -698,10 +756,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
);
}
});
// 开启图文混排支持
mNoteEditor.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
@ -1305,6 +1363,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
// 新增自己维护HTML内容不依赖RichEditor.getHtml()
private String mCurrentHtmlContent = "";
/**
*
*
@ -1328,10 +1389,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
mWorkingNote.setWorkingText(sb.toString());
} else {
// 确保获取最新的富文本内容
// 对于富文本模式保存当前的HTML内容包括Base64图片
String currentHtml = mNoteEditor.getHtml();
Log.d(TAG, "getWorkingText called for rich text mode, saving HTML content: " + currentHtml);
mWorkingNote.setWorkingText(currentHtml);
mText = currentHtml; // 更新mText变量确保保存时使用最新内容
}
return hasChecked;
}
@ -1431,6 +1492,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private static final int REQUEST_CODE_PERMISSION_STORAGE = 101;
private void pickImageFromGallery() {
// 检查运行时权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 请求权限
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION_STORAGE);
return;
}
}
try {
// 意图:打开系统相册选择图片
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
@ -1443,7 +1513,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
try {
startActivityForResult(intent, PHOTO_REQUEST);
} catch (ActivityNotFoundException ex) {
showToast(R.string.error_note_not_exist);
showToast(R.string.error_permission_denied);
Log.e(TAG, "No image picker available", ex);
}
}
@ -1472,17 +1542,30 @@ public class NoteEditActivity extends Activity implements OnClickListener,
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHOTO_REQUEST && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
String localImagePath = saveImageToLocal(uri);
if (localImagePath == null) return; // 保存失败就退出
// 核心修改适配RichEditor替换EditText的ImageSpan逻辑
// 1. 拼接RichEditor支持的<img>标签必须加file://前缀)
String imgUrl = "file://" + localImagePath;
String imgHtmlTag = "<img src=\"" + imgUrl + "\" width=\"200\" height=\"200\"/><br/>";
// 2. 插入图片到RichEditor
String curHtml = mNoteEditor.getHtml(); // 获取当前内容
String newHtml = curHtml + imgHtmlTag; // 追加图片标签
mNoteEditor.setHtml(newHtml); // 重新设置内容,实现插入
String imageBase64 = saveImageToBase64(uri);
if (imageBase64 == null) return; // 转换失败就退出
// 1. 拼接RichEditor支持的<img>标签使用Base64编码的图片数据
String imgHtmlTag = "<img src=\"" + imageBase64 + "\" width=\"200\" height=\"200\"/><br/>";
// 2. 直接保存到笔记内容中(结合原有插入逻辑)
String originalContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
Log.d(TAG, "Original note content: " + originalContent);
// 3. 插入图片到RichEditor兼容空内容情况
String curHtml = mNoteEditor.getHtml();
if (curHtml == null || curHtml.isEmpty()) {
// 对于空内容,直接使用图片标签
mNoteEditor.setHtml(imgHtmlTag);
} else {
// 对于已有内容,追加图片标签
String newHtml = curHtml + imgHtmlTag;
mNoteEditor.setHtml(newHtml);
}
// 4. 同时更新工作笔记内容,确保新建笔记也能正确保存
String updatedHtml = mNoteEditor.getHtml();
mWorkingNote.setWorkingText(updatedHtml);
// 弹窗依然保留
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@ -1492,59 +1575,93 @@ public class NoteEditActivity extends Activity implements OnClickListener,
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); // 加布局参数,避免图片显示不全
imageView.setImageURI(Uri.fromFile(new File(localImagePath)));//弹窗也显示本地图片
imageView.setImageURI(uri); // 弹窗显示原始图片
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); // 适配图片大小
builder.setView(imageView);
builder.setPositiveButton("确认保存", (dialog, which) -> {
String currentHtml = mNoteEditor.getHtml(); // 替换原EditText的getText()
String newContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
newContent += "\n[IMAGE]" + localImagePath + "[/IMAGE]"; // 保留原有[IMAGE]标记,供后续加载解析
Log.d("NoteDebug", "准备保存的内容:" + newContent); // 看Logcat里的输出
builder.setPositiveButton("确认", (dialog, which) -> {
// 保存HTML内容包含Base64编码的图片
String currentHtml = mNoteEditor.getHtml();
Log.d("NoteDebug", "准备保存的HTML内容" + currentHtml);
// 执行保存操作
mWorkingNote.setWorkingText(newContent);
mWorkingNote.setWorkingText(currentHtml);
boolean isSaved = mWorkingNote.saveNote();
// 根据保存结果提示(更友好)
if (isSaved) {
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "保存失败,请重试", Toast.LENGTH_SHORT).show();
// 如果保存返回false可能是因为内容未变化而不是真正的失败
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Note save returned false, but image was successfully inserted");
}
});
builder.setNegativeButton("取消", (dialog, which) -> {
// 如果用户取消,移除刚才插入的图片
String currentHtml = mNoteEditor.getHtml();
if (currentHtml != null && currentHtml.endsWith(imgHtmlTag)) {
String cancelNewHtml = currentHtml.substring(0, currentHtml.length() - imgHtmlTag.length());
mNoteEditor.setHtml(cancelNewHtml);
// 同时更新工作笔记
mWorkingNote.setWorkingText(cancelNewHtml);
} else if (currentHtml != null && currentHtml.equals(imgHtmlTag)) {
// 如果只有这一张图片,取消后清空内容
mNoteEditor.setHtml("");
mWorkingNote.setWorkingText("");
}
});
builder.show();
}
}
// 新增工具方法把临时URI的图片复制到应用私有目录返回真实路径
private String saveImageToLocal(Uri uri) {
// 新增工具方法把临时URI的图片转换为Base64编码直接嵌入HTML
private String saveImageToBase64(Uri uri) {
try {
// 1. 创建应用专属图片目录(不会被系统清理)
File appDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "note_images");
if (!appDir.exists()) appDir.mkdirs();
// 2. 生成唯一文件名(避免重复)
String fileName = "note_" + System.currentTimeMillis() + ".jpg";
File targetFile = new File(appDir, fileName);
// 3. 复制图片文件从临时URI到本地目录
// 1. 从URI读取图片数据
InputStream is = getContentResolver().openInputStream(uri);
OutputStream os = new FileOutputStream(targetFile);
byte[] buffer = new byte[1024];
if (is == null) {
Log.e(TAG, "Failed to open input stream for URI: " + uri);
Toast.makeText(this, "无法读取选择的图片", Toast.LENGTH_SHORT).show();
return null;
}
// 2. 将图片数据转换为Base64编码
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
os.write(buffer, 0, len);
baos.write(buffer, 0, len);
}
// 3. 获取图片MIME类型
String mimeType = getContentResolver().getType(uri);
if (mimeType == null) {
mimeType = "image/jpeg"; // 默认使用jpeg格式
}
// 4. 构建Base64编码的图片数据URL
String base64Data = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
String dataUrl = "data:" + mimeType + ";base64," + base64Data;
// 5. 关闭流
is.close();
os.close();
baos.close();
// 返回图片的真实本地路径不是URI
return targetFile.getAbsolutePath();
Log.d(TAG, "Image converted to Base64 successfully");
return dataUrl;
} catch (SecurityException e) {
Log.e(TAG, "Permission denied when reading image: " + e.getMessage());
Toast.makeText(this, "读取图片时权限被拒绝", Toast.LENGTH_SHORT).show();
return null;
} catch (IOException e) {
Log.e(TAG, "IO error when reading image: " + e.getMessage());
Toast.makeText(this, "图片读取失败IO错误", Toast.LENGTH_SHORT).show();
return null;
} catch (Exception e) {
Log.e("NoteEdit", "保存图片失败", e);
Toast.makeText(this, "图片保存失败", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unexpected error when converting image to Base64: " + e.getMessage(), e);
Toast.makeText(this, "图片转换失败,意外错误", Toast.LENGTH_SHORT).show();
return null;
}
}
@ -1588,7 +1705,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.undo();
}
});
// 加粗功能
findViewById(R.id.action_bold).setOnClickListener(new View.OnClickListener() {
@Override
@ -1596,7 +1713,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setBold();
}
});
// 斜体功能
findViewById(R.id.action_italic).setOnClickListener(new View.OnClickListener() {
@Override
@ -1604,7 +1721,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setItalic();
}
});
// 背景色功能
findViewById(R.id.action_bg_color).setOnClickListener(new View.OnClickListener() {
@Override

Loading…
Cancel
Save