├── app ├── .gitignore ├── src │ └── main │ │ ├── ic_launcher-web.png │ │ ├── res │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_main.png │ │ │ ├── ico_md.png │ │ │ ├── img_add.png │ │ │ ├── ic_launcher.png │ │ │ ├── img_history.png │ │ │ ├── img_back_down.png │ │ │ ├── img_back_white.png │ │ │ ├── img_import_tip.png │ │ │ ├── img_more_gray.png │ │ │ ├── img_more_white.png │ │ │ ├── img_paper_bkg.png │ │ │ └── img_write_bkg.png │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ │ ├── img_toolbar_bkg.9.png │ │ │ ├── button_toolbar.xml │ │ │ ├── button_toolbar_down.xml │ │ │ └── button_toolbar_normal.xml │ │ ├── values │ │ │ ├── ic_launcher_background.xml │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── drawable-xxxhdpi │ │ │ └── bkg_paper.xml │ │ ├── xml │ │ │ └── file_path.xml │ │ ├── anim │ │ │ ├── slide_out_bottom.xml │ │ │ ├── slide_out_top.xml │ │ │ ├── slide_in_left.xml │ │ │ ├── slide_in_right.xml │ │ │ ├── slide_out_left.xml │ │ │ ├── slide_out_right.xml │ │ │ ├── slide_in_top.xml │ │ │ ├── slide_in_bottom.xml │ │ │ ├── back.xml │ │ │ ├── fade.xml │ │ │ └── hold.xml │ │ ├── drawable │ │ │ ├── scrollbar_vertical_track.xml │ │ │ └── ic_launcher_background.xml │ │ ├── menu │ │ │ └── history.xml │ │ ├── layout │ │ │ ├── dialog_import_data.xml │ │ │ ├── item_ground.xml │ │ │ ├── activity_about.xml │ │ │ ├── activity_history.xml │ │ │ └── activity_main.xml │ │ └── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ └── com │ │ │ └── kongzue │ │ │ └── notes │ │ │ ├── util │ │ │ ├── Base64Util.java │ │ │ ├── ViewWrapper.java │ │ │ └── DBUtil.java │ │ │ ├── NotesApp.java │ │ │ └── activity │ │ │ ├── AboutActivity.java │ │ │ ├── Importer.java │ │ │ ├── HistoryActivity.java │ │ │ └── MainActivity.java │ │ └── AndroidManifest.xml ├── build.gradle └── proguard-rules.pro ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── caches │ └── build_file_checksums.ser ├── dictionaries │ └── myzcx.xml ├── encodings.xml ├── markdown-navigator │ └── profiles_settings.xml ├── runConfigurations.xml ├── gradle.xml ├── misc.xml ├── assetWizardSettings.xml └── markdown-navigator.xml ├── .gitignore ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/ic_main.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ico_md.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/ico_md.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_add.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_history.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_back_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_back_down.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_back_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_back_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_import_tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_import_tip.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_more_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_more_gray.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_more_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_more_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_paper_bkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_paper_bkg.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_write_bkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/mipmap-xxhdpi/img_write_bkg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_toolbar_bkg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongzue/Notes/HEAD/app/src/main/res/drawable-xxhdpi/img_toolbar_bkg.9.png -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/bkg_paper.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /.idea/dictionaries/myzcx.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | kongzue 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/xml/file_path.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 16 20:58:59 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/scrollbar_vertical_track.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/menu/history.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/button_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/button_toolbar_down.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/button_toolbar_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/util/Base64Util.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.util; 2 | 3 | import android.util.Base64; 4 | 5 | public class Base64Util { 6 | 7 | public static String decode(String b){ 8 | if (b.isEmpty()){ 9 | return ""; 10 | } 11 | return new String(Base64.decode(b, Base64.NO_WRAP)); 12 | } 13 | 14 | public static String encode(String s){ 15 | return new String(Base64.encode(s.getBytes(), Base64.NO_WRAP)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #ffffff 5 | #3e3e3e 6 | #B0B0B0 7 | #00000000 8 | #000000 9 | #80000000 10 | #1e000000 11 | #202020 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 欢迎使用「记」 5 | 更新日志 6 | 无法读取要导入的数据 7 | 导入到「记」 8 | 需要权限 9 | 导入文件需要读取存储的权限 10 | 开始授权 11 | 取消 12 | 导入错误 13 | 导入成功 14 | 导出完成 15 | 导出失败 16 | 您可以将文本文件存到手机后,通过文件管理器找到它,以发送/分享/打开方式,导入到「记」。 17 | 如何导入 18 | 我知道了 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/anim/back.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/anim/hold.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/util/ViewWrapper.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.util; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Author: @Kongzue 7 | * Github: https://github.com/kongzue/ 8 | * Homepage: http://kongzue.com/ 9 | * Mail: myzcxhh@live.cn 10 | * CreateTime: 2018/7/5 17:06 11 | */ 12 | public class ViewWrapper { 13 | 14 | private View mTargetView; 15 | 16 | public ViewWrapper(View target) { 17 | mTargetView = target; 18 | } 19 | 20 | public int getWidth() { 21 | return mTargetView.getLayoutParams().width; 22 | } 23 | 24 | public int getHeight() { 25 | return mTargetView.getLayoutParams().height; 26 | } 27 | 28 | public void setWidth(int width) { 29 | mTargetView.getLayoutParams().width = width; 30 | mTargetView.requestLayout(); 31 | } 32 | 33 | public void setHeight(int height) { 34 | mTargetView.getLayoutParams().height = height; 35 | mTargetView.requestLayout(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_import_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 17 | 18 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.kongzue.notes" 7 | minSdkVersion 21 8 | targetSdkVersion 28 9 | versionCode 6 10 | versionName "1.5" 11 | renderscriptTargetApi 19 12 | renderscriptSupportModeEnabled true 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled true 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | android.applicationVariants.all { variant -> 20 | variant.outputs.all { 21 | outputFileName = "记@${defaultConfig.versionName}.apk" 22 | } 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(include: ['*.jar'], dir: 'libs') 29 | //Kongzue 30 | implementation 'com.kongzue.dialog:dialog:2.5.1' 31 | implementation 'com.kongzue.baseframework:baseframework:6.6.7' 32 | implementation 'com.kongzue.kongzuedb:kongzuedb:1.0.6' 33 | implementation 'com.android.support:appcompat-v7:28.0.0' 34 | implementation 'com.android.support:support-v4:28.0.0' 35 | //Other 36 | implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-14' 37 | implementation 'com.hanks:lineheightedittext-library:1.0' 38 | implementation 'ren.qinc.edit:lib:0.0.3' 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/NotesApp.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes; 2 | 3 | import android.app.Application; 4 | 5 | import com.kongzue.baseframework.BaseActivity; 6 | import com.kongzue.baseframework.BaseFrameworkSettings; 7 | import com.kongzue.dialog.v2.DialogSettings; 8 | import com.kongzue.notes.util.DBUtil; 9 | 10 | import static com.kongzue.dialog.v2.DialogSettings.STYLE_KONGZUE; 11 | import static com.kongzue.dialog.v2.DialogSettings.THEME_DARK; 12 | import static com.kongzue.dialog.v2.DialogSettings.TYPE_IOS; 13 | import static com.kongzue.dialog.v2.DialogSettings.TYPE_KONGZUE; 14 | 15 | /** 16 | * Author: @Kongzue 17 | * Github: https://github.com/kongzue/ 18 | * Homepage: http://kongzue.com/ 19 | * Mail: myzcxhh@live.cn 20 | * CreateTime: 2018/8/16 21:03 21 | */ 22 | public class NotesApp extends Application { 23 | 24 | public static boolean DEBUGMODE = true; 25 | private static NotesApp me; 26 | 27 | public static int screenWidth; 28 | public static int screenHeight; 29 | public static int navigationHeight; 30 | 31 | @Override 32 | public void onCreate() { 33 | super.onCreate(); 34 | me = this; 35 | 36 | BaseFrameworkSettings.DEBUGMODE = DEBUGMODE; 37 | DialogSettings.DEBUGMODE = DEBUGMODE; 38 | 39 | DialogSettings.style = STYLE_KONGZUE; 40 | 41 | DBUtil.getInstance().init(me); 42 | DBUtil.getInstance().createTable(); 43 | } 44 | 45 | public static NotesApp getInstance() { 46 | return me; 47 | } 48 | 49 | @Override 50 | public void onTerminate() { 51 | DBUtil.getInstance().close(); 52 | super.onTerminate(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 「记」 2 | 3 | 摒除杂质,专注创作 4 | 5 | - 点击进入编辑,底部工具栏可以方便地进行缩进、撤销和粘贴操作 6 | - 向下滑动进入历史笔记,向上滑动快速创建新笔记 7 | 8 | 无广告、无联网权限,本地备份和恢复数据。 9 | 10 | 11 | Notes 12 | 13 | 14 | Notes 15 | 16 | 17 | Maven 18 | 19 | 20 | Maven 21 | 22 | 23 | ![Notes](https://github.com/kongzue/Res/raw/master/app/src/main/res/mipmap-xxxhdpi/img_kongzue_notes.png) 24 | 25 | ### 下载 26 | 酷安: https://www.coolapk.com/apk/203224 下载 27 | 28 | ### 使用框架 29 | ``` 30 | 'com.kongzue.dialog:dialog:2.3.4' 31 | 'com.kongzue.baseframework:baseframework:6.5.6.2' 32 | 'com.kongzue.kongzuedb:kongzuedb:1.0.1' 33 | 34 | 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-14' 35 | 'com.hanks:lineheightedittext-library:1.0' 36 | 'ren.qinc.edit:lib:0.0.3' 37 | ``` 38 | 39 | ### 开源协议 40 | ``` 41 | Copyright (C) 2016 Kongzue.Notes 42 | 43 | Licensed under the Apache License, Version 2.0 (the "License"); 44 | you may not use this file except in compliance with the License. 45 | You may obtain a copy of the License at 46 | 47 | http://www.apache.org/licenses/LICENSE-2.0 48 | 49 | Unless required by applicable law or agreed to in writing, software 50 | distributed under the License is distributed on an "AS IS" BASIS, 51 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 52 | See the License for the specific language governing permissions and 53 | limitations under the License. 54 | ``` 55 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/activity/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.activity; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.kongzue.baseframework.BaseActivity; 12 | import com.kongzue.baseframework.interfaces.Layout; 13 | import com.kongzue.baseframework.interfaces.NavigationBarBackgroundColor; 14 | import com.kongzue.baseframework.util.JumpParameter; 15 | import com.kongzue.notes.BuildConfig; 16 | import com.kongzue.notes.R; 17 | 18 | @Layout(R.layout.activity_about) 19 | @NavigationBarBackgroundColor(a = 0) 20 | public class AboutActivity extends BaseActivity { 21 | 22 | private ImageView btnBack; 23 | private TextView ver; 24 | private TextView btnKongzue; 25 | 26 | @Override 27 | public void initViews() { 28 | btnBack = findViewById(R.id.btn_back); 29 | ver = findViewById(R.id.ver); 30 | btnKongzue = findViewById(R.id.btn_kongzue); 31 | } 32 | 33 | @Override 34 | public void initDatas(JumpParameter paramer) { 35 | ver.setText("v"+BuildConfig.VERSION_NAME); 36 | } 37 | 38 | @Override 39 | public void setEvents() { 40 | btnBack.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View view) { 43 | finish(); 44 | } 45 | }); 46 | 47 | btnKongzue.setOnClickListener(new View.OnClickListener() { 48 | @Override 49 | public void onClick(View v) { 50 | Intent intent = new Intent(); 51 | intent.setAction("android.intent.action.VIEW"); 52 | Uri content_url = Uri.parse("http://www.kongzue.com/");//此处填链接 53 | intent.setData(content_url); 54 | startActivity(intent); 55 | } 56 | }); 57 | } 58 | 59 | @Override 60 | public void finish() { 61 | super.finish(); 62 | jumpAnim(R.anim.hold, R.anim.back); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_ground.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 16 | 17 | 37 | 38 | 39 | 40 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/util/DBUtil.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.util; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.kongzue.baseframework.util.Preferences; 7 | import com.kongzue.kongzuedb.DB; 8 | import com.kongzue.kongzuedb.DBData; 9 | import com.kongzue.notes.BuildConfig; 10 | import com.kongzue.notes.R; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Author: @Kongzue 16 | * Github: https://github.com/kongzue/ 17 | * Homepage: http://kongzue.com/ 18 | * Mail: myzcxhh@live.cn 19 | * CreateTime: 2018/8/26 21:26 20 | */ 21 | public class DBUtil { 22 | 23 | private static DB db; 24 | private static DBUtil dbUtil; 25 | private Context context; 26 | 27 | private DBUtil() { 28 | } 29 | 30 | public static DBUtil getInstance() { 31 | if (dbUtil == null) { 32 | synchronized (DBUtil.class) { 33 | dbUtil = new DBUtil(); 34 | } 35 | } 36 | return dbUtil; 37 | } 38 | 39 | public void init(Context context) { 40 | this.context = context; 41 | db = new DB(context, "notes"); 42 | } 43 | 44 | 45 | public void close() { 46 | db.closeDB(); 47 | db = null; 48 | context = null; 49 | dbUtil = null; 50 | } 51 | 52 | public void createTable() { 53 | boolean isUsed = Preferences.getInstance().getBoolean(context, "cache", "isUsed"); 54 | if (!isUsed) { 55 | DBData dbData = new DBData("notes"); 56 | dbData.set("title", Base64Util.encode(context.getString(R.string.new_tip_title))); 57 | dbData.set("content", Base64Util.encode( 58 | "你好!\n  这是 @Kongzue 为你带来的纯净、易用、绿色的文字写作工具。\n  随时随地打开,继续你的创作~\n\n  - 点击文本即可编辑,底部工具栏可以方便地进行缩进、撤销和粘贴操作\n  - 收起输入法,向下滑动进入历史笔记,向上滑动快速创建新笔记\n\n  在这里你可以体验到最纯粹的写作方式,没有多余任何界面或功能的打扰\n  Enjoy it and have Fun !" 59 | )); 60 | dbData.set("time", System.currentTimeMillis()); 61 | dbData.set("isSync", false); 62 | db.add(dbData, false); 63 | dbData.set("title", Base64Util.encode(BuildConfig.VERSION_NAME + context.getString(R.string.update_title))); 64 | dbData.set("content", Base64Util.encode( 65 | "  「记」现已全新发布,和「给未来写封信」一样的风格,一张信纸,一片记忆,带给你更好的体验。\n  Less is more,相信这一份简洁能带给你不一样的创作体验!\n  1.5版本更换了信纸样式,支持了更好的分辨率并优化了界面动画效果,以带来更加完美的用户体验。" 66 | )); 67 | dbData.set("time", System.currentTimeMillis()); 68 | dbData.set("isSync", false); 69 | db.add(dbData, false); 70 | Preferences.getInstance().set(context, "cache", "isUsed", true); 71 | Preferences.getInstance().set(context, "cache", "id", 1); 72 | } 73 | } 74 | 75 | public DB getDb() { 76 | return db; 77 | } 78 | 79 | public List getDatas() { 80 | return db.findAll("notes"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | -------------------------------------------------------------------------------- /.idea/assetWizardSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 73 | 74 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 22 | 23 | 29 | 30 | 34 | 35 | 36 | 37 | 43 | 44 | 49 | 50 | 56 | 57 | 64 | 65 | 74 | 75 | 76 | 77 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -ignorewarnings 23 | -optimizationpasses 5 # 指定代码的压缩级别 24 | -dontusemixedcaseclassnames # 是否使用大小写混合 25 | -dontpreverify # 混淆时是否做预校验 26 | -verbose # 混淆时是否记录日志 27 | 28 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法 29 | 30 | -keep public class * extends android.app.Activity # 保持哪些类不被混淆 31 | -keep public class * extends android.app.Application # 保持哪些类不被混淆 32 | -keep public class * extends android.app.Service # 保持哪些类不被混淆 33 | -keep public class * extends android.content.BroadcastReceiver # 保持哪些类不被混淆 34 | -keep public class * extends android.content.ContentProvider # 保持哪些类不被混淆 35 | -keep public class * extends android.app.backup.BackupAgentHelper # 保持哪些类不被混淆 36 | -keep public class * extends android.preference.Preference # 保持哪些类不被混淆 37 | -keep public class com.android.vending.licensing.ILicensingService # 保持哪些类不被混淆 38 | -keep public class com.kongzue.secretinput.util.viewutils.ViewWrapper 39 | -keep class com.facebook.** { *; } 40 | -keep class com.tencent.** { *; } 41 | -keep class com.android.volley.** {*;} 42 | -keep class com.android.volley.toolbox.** {*;} 43 | -keep class com.android.volley.Response$* { *; } 44 | -keep class com.android.volley.Request$* { *; } 45 | -keep class com.android.volley.RequestQueue$* { *; } 46 | -keep class com.android.volley.toolbox.HurlStack$* { *; } 47 | -keep class com.android.volley.toolbox.ImageLoader$* { *; } 48 | -keep class org.apache.http.** {*;} 49 | -keep class android.support.v7.app.** {*;} 50 | -keep class com.kongzue.secretinput.util.viewutils.** {*;} 51 | -keep class org.spongycastle.** {*;} 52 | 53 | # MeiZuFingerprint 54 | -keep class com.fingerprints.service.** { *; } 55 | 56 | # SmsungFingerprint 57 | -keep class com.samsung.android.sdk.** { *; } 58 | 59 | #fresco 60 | # Keep our interfaces so they can be used by other ProGuard rules. 61 | # See http://sourceforge.net/p/proguard/bugs/466/ 62 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 63 | -keep,allowobfuscation @interface com.facebook.soloader.DoNotOptimize 64 | 65 | # Do not strip any method/class that is annotated with @DoNotStrip 66 | -keep @com.facebook.common.internal.DoNotStrip class * 67 | -keepclassmembers class * { 68 | @com.facebook.common.internal.DoNotStrip *; 69 | } 70 | 71 | # Do not strip any method/class that is annotated with @DoNotOptimize 72 | -keep @com.facebook.soloader.DoNotOptimize class * 73 | -keepclassmembers class * { 74 | @com.facebook.soloader.DoNotOptimize *; 75 | } 76 | 77 | # Keep native methods 78 | -keepclassmembers class * { 79 | native ; 80 | } 81 | 82 | -dontwarn okio.** 83 | -dontwarn com.squareup.okhttp.** 84 | -dontwarn okhttp3.** 85 | -dontwarn javax.annotation.** 86 | -dontwarn com.android.volley.toolbox.** 87 | -dontwarn com.facebook.infer.** 88 | 89 | # Bugly 90 | -dontwarn com.tencent.bugly.** 91 | -keep public class com.tencent.bugly.**{*;} 92 | 93 | -keepclassmembers,allowshrinking,allowobfuscation class com.android.volley.NetworkDispatcher { 94 | void processRequest(); 95 | } 96 | -keepclassmembers,allowshrinking,allowobfuscation class com.android.volley.CacheDispatcher { 97 | void processRequest(); 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 27 | 28 | 32 | 33 | 39 | 40 | 41 | 42 | 46 | 47 | 53 | 54 | 55 | 56 | 67 | 68 | 74 | 75 | 80 | 81 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/activity/Importer.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.util.Log; 9 | 10 | import com.kongzue.baseframework.util.AppManager; 11 | import com.kongzue.baseframework.util.JumpParameter; 12 | import com.kongzue.baseframework.util.ParameterCache; 13 | import com.kongzue.dialog.v2.DialogSettings; 14 | import com.kongzue.dialog.v2.Notification; 15 | import com.kongzue.notes.R; 16 | 17 | import java.util.Timer; 18 | import java.util.TimerTask; 19 | 20 | import static com.kongzue.notes.NotesApp.DEBUGMODE; 21 | 22 | /** 23 | * Author: @Kongzue 24 | * Github: https://github.com/kongzue/ 25 | * Homepage: http://kongzue.com/ 26 | * Mail: myzcxhh@live.cn 27 | * CreateTime: 2018/9/12 02:36 28 | */ 29 | public class Importer extends Activity { 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | Intent intent = getIntent(); 35 | if (intent != null) { 36 | String action = intent.getAction(); 37 | if (action != null) { 38 | if (intent.ACTION_VIEW.equals(action)) { 39 | final String file = intent.getDataString(); 40 | log("Importer>>>" + "ACTION_VIEW: " + file); 41 | if (!isNull(file)) { 42 | AppManager.getInstance().killAllActivity(); 43 | Timer timer = new Timer(); 44 | timer.schedule(new TimerTask() { 45 | @Override 46 | public void run() { 47 | jump(MainActivity.class, new JumpParameter().put("import", file)); 48 | jumpAnim(R.anim.slide_in_bottom, R.anim.slide_out_top); 49 | } 50 | },500); 51 | 52 | } else { 53 | doErrorTip(); 54 | } 55 | } 56 | if (intent.ACTION_SEND.equals(action)) { 57 | Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); 58 | if (uri != null) { 59 | String file = uri.getPath(); 60 | log("Importer>>>" + "ACTION_SEND: " + file); 61 | if (!isNull(file)) { 62 | if (MainActivity.getMainActivity()!=null)MainActivity.getMainActivity().finish(); 63 | jump(MainActivity.class, new JumpParameter().put("import", file)); 64 | jumpAnim(R.anim.slide_in_bottom, R.anim.slide_out_top); 65 | } else { 66 | doErrorTip(); 67 | } 68 | } else { 69 | doErrorTip(); 70 | } 71 | } 72 | } else { 73 | doErrorTip(); 74 | } 75 | } else { 76 | doErrorTip(); 77 | } 78 | finish(); 79 | } 80 | 81 | //可以传任何类型参数的跳转方式 82 | public boolean jump(Class cls, JumpParameter jumpParameter) { 83 | try { 84 | if (jumpParameter != null) 85 | ParameterCache.getInstance().set(cls.getName(), jumpParameter); 86 | startActivity(new Intent(Importer.this, cls)); 87 | } catch (Exception e) { 88 | if (DEBUGMODE) e.printStackTrace(); 89 | return false; 90 | } 91 | return true; 92 | } 93 | 94 | public void jumpAnim(int enterAnim, int exitAnim) { 95 | int version = Integer.valueOf(android.os.Build.VERSION.SDK); 96 | if (version > 5) { 97 | overridePendingTransition(enterAnim, exitAnim); 98 | } 99 | } 100 | 101 | private void log(Object s) { 102 | if (s == null) return; 103 | if (!DEBUGMODE) return; 104 | Log.i(">>>", s.toString()); 105 | } 106 | 107 | private void doErrorTip() { 108 | DialogSettings.style = DialogSettings.STYLE_KONGZUE; 109 | Notification.show(this, 0, getString(R.string.cannot_import), Notification.TYPE_ERROR); 110 | } 111 | 112 | private boolean isNull(String s) { 113 | if (s == null || s.trim().isEmpty() || s.equals("null")) { 114 | return true; 115 | } 116 | return false; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 19 | 23 | 24 | 25 | 26 | 30 | 31 | 36 | 37 | 42 | 43 | 52 | 53 | 54 | 55 | 59 | 60 | 69 | 70 | 74 | 75 | 91 | 92 | 93 | 94 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 131 | 132 | 137 | 138 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 162 | 163 | 169 | 170 | 176 | 177 | 181 | 182 | 191 | 192 | 198 | 199 | 208 | 209 | 215 | 216 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/activity/HistoryActivity.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.activity; 2 | 3 | import android.app.AlertDialog; 4 | import android.app.Dialog; 5 | import android.content.ClipboardManager; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | import android.content.Intent; 9 | import android.net.Uri; 10 | import android.os.Build; 11 | import android.os.Environment; 12 | import android.os.Handler; 13 | import android.support.annotation.NonNull; 14 | import android.support.v4.content.FileProvider; 15 | import android.support.v7.app.AppCompatActivity; 16 | import android.os.Bundle; 17 | import android.view.Gravity; 18 | import android.view.LayoutInflater; 19 | import android.view.MenuInflater; 20 | import android.view.MenuItem; 21 | import android.view.View; 22 | import android.widget.AdapterView; 23 | import android.widget.ImageView; 24 | import android.widget.LinearLayout; 25 | import android.widget.ListView; 26 | import android.widget.PopupMenu; 27 | import android.widget.TextView; 28 | import android.widget.Toast; 29 | 30 | import com.hanks.lineheightedittext.LineHeightEditText; 31 | import com.kongzue.baseframework.BaseActivity; 32 | import com.kongzue.baseframework.BaseAdapter; 33 | import com.kongzue.baseframework.interfaces.DarkNavigationBarTheme; 34 | import com.kongzue.baseframework.interfaces.DarkStatusBarTheme; 35 | import com.kongzue.baseframework.interfaces.Layout; 36 | import com.kongzue.baseframework.interfaces.NavigationBarBackgroundColor; 37 | import com.kongzue.baseframework.interfaces.SimpleAdapterSettings; 38 | import com.kongzue.baseframework.interfaces.SimpleMapAdapterSettings; 39 | import com.kongzue.baseframework.util.JumpParameter; 40 | import com.kongzue.baseframework.util.OnPermissionResponseListener; 41 | import com.kongzue.baseframework.util.Preferences; 42 | import com.kongzue.dialog.listener.DialogLifeCycleListener; 43 | import com.kongzue.dialog.listener.OnMenuItemClickListener; 44 | import com.kongzue.dialog.v2.BottomMenu; 45 | import com.kongzue.dialog.v2.DialogSettings; 46 | import com.kongzue.dialog.v2.MessageDialog; 47 | import com.kongzue.dialog.v2.SelectDialog; 48 | import com.kongzue.dialog.v2.TipDialog; 49 | import com.kongzue.dialog.v2.WaitDialog; 50 | import com.kongzue.kongzuedb.DB; 51 | import com.kongzue.kongzuedb.DBData; 52 | import com.kongzue.notes.BuildConfig; 53 | import com.kongzue.notes.R; 54 | import com.kongzue.notes.util.Base64Util; 55 | import com.kongzue.notes.util.DBUtil; 56 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 57 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 58 | import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener; 59 | 60 | import org.json.JSONArray; 61 | import org.json.JSONObject; 62 | 63 | import java.io.File; 64 | import java.io.FileOutputStream; 65 | import java.text.SimpleDateFormat; 66 | import java.util.ArrayList; 67 | import java.util.Date; 68 | import java.util.HashMap; 69 | import java.util.List; 70 | import java.util.Map; 71 | 72 | import static com.kongzue.baseframework.BaseFrameworkSettings.DEBUGMODE; 73 | 74 | @Layout(R.layout.activity_history) 75 | @NavigationBarBackgroundColor(a = 0) 76 | public class HistoryActivity extends BaseActivity { 77 | 78 | private ImageView btnMore; 79 | private SmartRefreshLayout refreshLayout; 80 | private LinearLayout boxRefresher; 81 | private ListView list; 82 | private LinearLayout boxFooter; 83 | private ImageView imgLoadMore; 84 | private TextView txtLoadMore; 85 | 86 | @Override 87 | public void initViews() { 88 | btnMore = findViewById(R.id.btn_more); 89 | refreshLayout = findViewById(R.id.refreshLayout); 90 | boxRefresher = findViewById(R.id.box_refresher); 91 | list = findViewById(R.id.list); 92 | boxFooter = findViewById(R.id.box_footer); 93 | imgLoadMore = findViewById(R.id.img_loadMore); 94 | txtLoadMore = findViewById(R.id.txt_loadMore); 95 | } 96 | 97 | private List dbDataList; 98 | private List> datas; 99 | private BaseAdapter baseAdapter; 100 | 101 | @Override 102 | public void initDatas(JumpParameter paramer) { 103 | refreshLayout.setEnableOverScrollBounce(true); 104 | refreshLayout.setEnableOverScrollDrag(true); 105 | refreshLayout.setEnableRefresh(false); 106 | refreshLayout.setEnableAutoLoadMore(false); 107 | 108 | loadDatas(); 109 | baseAdapter = new BaseAdapter(me, datas, R.layout.item_ground, new SimpleMapAdapterSettings() { 110 | @Override 111 | public Object setViewHolder(View convertView) { 112 | ViewHolder viewHolder = new ViewHolder(); 113 | viewHolder.txtText = convertView.findViewById(R.id.txt_text); 114 | viewHolder.txtTime = convertView.findViewById(R.id.txt_time); 115 | return viewHolder; 116 | } 117 | 118 | @Override 119 | public void setData(Object viewHolder, Map data, int index) { 120 | ViewHolder viewHolders = (ViewHolder) viewHolder; 121 | viewHolders.txtText.setText((String) data.get("title")); 122 | viewHolders.txtTime.setText((String) data.get("content")); 123 | } 124 | 125 | }); 126 | 127 | list.setAdapter(baseAdapter); 128 | 129 | } 130 | 131 | private void loadDatas() { 132 | dbDataList = new ArrayList<>(); 133 | dbDataList = DBUtil.getInstance().getDatas(); 134 | datas = new ArrayList<>(); 135 | for (DBData dbData : dbDataList) { 136 | Map map = new HashMap<>(); 137 | map.put("title", titleParse(dbData)); 138 | map.put("content", contentParse(dbData)); 139 | datas.add(map); 140 | } 141 | } 142 | 143 | private String contentParse(DBData dbData) { 144 | String content = Base64Util.decode(dbData.getString("content")); 145 | content = content.replace(" ", ""); 146 | content = content.replace("\n", " "); 147 | return content; 148 | } 149 | 150 | private String titleParse(DBData dbData) { 151 | String title = Base64Util.decode(dbData.getString("title")); 152 | if (isNull(title)) { 153 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM月dd日"); 154 | Date date = new Date(dbData.getLong("time")); 155 | title = simpleDateFormat.format(date); 156 | } 157 | 158 | title = title.replace(" ", ""); 159 | title = title.replace("\n", " "); 160 | return title; 161 | } 162 | 163 | @Override 164 | public void setEvents() { 165 | refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { 166 | @Override 167 | public void onLoadMore(@NonNull RefreshLayout refreshLayout) { 168 | refreshLayout.finishLoadMore(500); 169 | if (MainActivity.getMainActivity() != null) { 170 | finish(); 171 | } else { 172 | jump(MainActivity.class, new JumpParameter().put("newNote", true)); 173 | finish(); 174 | jumpAnim(R.anim.slide_in_bottom, R.anim.slide_out_top); 175 | } 176 | } 177 | }); 178 | 179 | btnMore.setOnClickListener(new View.OnClickListener() { 180 | @Override 181 | public void onClick(View view) { 182 | PopupMenu popup = new PopupMenu(me, btnMore); 183 | MenuInflater inflater = popup.getMenuInflater(); 184 | inflater.inflate(R.menu.history, popup.getMenu()); 185 | popup.setOnMenuItemClickListener(onMenuItemClickListener); 186 | popup.show(); 187 | } 188 | }); 189 | 190 | list.setOnItemClickListener(new AdapterView.OnItemClickListener() { 191 | @Override 192 | public void onItemClick(AdapterView parent, View view, int position, long id) { 193 | log("p:" + position); 194 | if (MainActivity.getMainActivity() != null) { 195 | MainActivity.getMainActivity().setData(dbDataList.get(position)); 196 | onBackPressed(); 197 | } else { 198 | jump(MainActivity.class, new JumpParameter().put("data", dbDataList.get(position))); 199 | jumpAnim(R.anim.slide_in_bottom, R.anim.slide_out_top); 200 | } 201 | } 202 | }); 203 | 204 | list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 205 | @Override 206 | public boolean onItemLongClick(AdapterView adapterView, View view, final int position, long l) { 207 | String[] areas = new String[]{"导出...", "发送...", "删除"}; 208 | BottomMenu.show(me, areas, new OnMenuItemClickListener() { 209 | @Override 210 | public void onClick(String text, int index) { 211 | switch (index) { 212 | case 0: 213 | if (!checkPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"})) { 214 | SelectDialog.show(me, getString(R.string.need_permission_title), getString(R.string.import_need_permission), getString(R.string.start_get_permission), new DialogInterface.OnClickListener() { 215 | @Override 216 | public void onClick(DialogInterface dialog, int which) { 217 | requestPermission(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, new OnPermissionResponseListener() { 218 | @Override 219 | public void onSuccess(String[] permissions) { 220 | exportFile(dbDataList.get(position), true); 221 | } 222 | 223 | @Override 224 | public void onFail() { 225 | 226 | } 227 | }); 228 | } 229 | }, getString(R.string.cancel), new DialogInterface.OnClickListener() { 230 | @Override 231 | public void onClick(DialogInterface dialog, int which) { 232 | 233 | } 234 | }); 235 | } else { 236 | new Handler().postDelayed(new Runnable() { 237 | @Override 238 | public void run() { 239 | if (isActive) { 240 | exportFile(dbDataList.get(position), true); 241 | } 242 | } 243 | }, 500); 244 | } 245 | 246 | break; 247 | case 1: 248 | shareText(dbDataList.get(position)); 249 | break; 250 | case 2: 251 | DBUtil.getInstance().getDb().delete(dbDataList.get(position)); 252 | loadDatas(); 253 | baseAdapter.refreshMapDataChanged(datas); 254 | if (MainActivity.getMainActivity() != null) 255 | MainActivity.getMainActivity().finish(); 256 | break; 257 | default: 258 | break; 259 | } 260 | } 261 | },true,"取消").setTitle(titleParse(dbDataList.get(position))); 262 | return true; 263 | } 264 | }); 265 | } 266 | 267 | private void shareText(DBData dbData) { 268 | String text = Base64Util.decode(dbData.getString("content")); 269 | 270 | Intent intent = new Intent(Intent.ACTION_SEND); 271 | intent.setType("text/plain"); 272 | intent.putExtra(Intent.EXTRA_SUBJECT, titleParse(dbData)); 273 | intent.putExtra(Intent.EXTRA_TEXT, text); 274 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 275 | startActivity(Intent.createChooser(intent, "分享到")); 276 | } 277 | 278 | private int sameFileIndex; 279 | 280 | private void exportFile(DBData dbData, final boolean isShownWaitTip) { 281 | if (isShownWaitTip) WaitDialog.show(me, "请稍候..."); 282 | JSONArray backUpData = new JSONArray(); 283 | 284 | try { 285 | FileOutputStream fos = null; 286 | try { 287 | File file = new File(getInnerSDCardPath(), titleParse(dbData) 288 | + ".txt"); 289 | if (file.exists()) { 290 | if (isShownWaitTip) { 291 | file.delete(); 292 | } else { 293 | sameFileIndex = 0; 294 | while (file.exists()) { 295 | sameFileIndex++; 296 | file = new File(getInnerSDCardPath(), titleParse(dbData) + "_" + sameFileIndex 297 | + ".txt"); 298 | } 299 | } 300 | } 301 | fos = new FileOutputStream(file); 302 | 303 | String text = Base64Util.decode(dbData.getString("content")); 304 | 305 | byte[] buffer = text.getBytes(); 306 | fos.write(buffer); 307 | fos.close(); 308 | 309 | log(file.getPath()); 310 | 311 | if (isShownWaitTip) { 312 | runOnMainDelayed(new Runnable() { 313 | @Override 314 | public void run() { 315 | WaitDialog.dismiss(); 316 | TipDialog.show(me, getString(R.string.export_to_local_finish), TipDialog.TYPE_FINISH); 317 | 318 | Toast.makeText(me, "已存储在“内存”目录下的“记”文件夹中", Toast.LENGTH_LONG).show(); 319 | } 320 | }, 500); 321 | } 322 | 323 | } catch (Exception e) { 324 | if (isShownWaitTip) { 325 | WaitDialog.dismiss(); 326 | TipDialog.show(me, getString(R.string.export_to_local_error), TipDialog.TYPE_ERROR); 327 | if (DEBUGMODE) e.printStackTrace(); 328 | } 329 | } finally { 330 | if (fos != null) fos.close(); 331 | } 332 | 333 | } catch (Exception e) { 334 | if (isShownWaitTip) { 335 | WaitDialog.dismiss(); 336 | TipDialog.show(me, getString(R.string.export_to_local_error), TipDialog.TYPE_ERROR); 337 | if (DEBUGMODE) e.printStackTrace(); 338 | } 339 | } 340 | } 341 | 342 | private void exportAll() { 343 | WaitDialog.show(me, "请稍候..."); 344 | 345 | sameFileIndex = 0; 346 | for (DBData dbData : dbDataList) { 347 | exportFile(dbData, false); 348 | } 349 | runOnMainDelayed(new Runnable() { 350 | @Override 351 | public void run() { 352 | WaitDialog.dismiss(); 353 | TipDialog.show(me, getString(R.string.export_to_local_finish), TipDialog.TYPE_FINISH); 354 | 355 | Toast.makeText(me, "已存储在“内存”目录下的“记”文件夹中", Toast.LENGTH_LONG).show(); 356 | } 357 | }, 1000); 358 | } 359 | 360 | public String getInnerSDCardPath() { 361 | String path = Environment.getExternalStorageDirectory().getPath() + "/记"; 362 | File file = new File(path); 363 | if (!file.exists()) 364 | file.mkdir(); 365 | return path; 366 | } 367 | 368 | private PopupMenu.OnMenuItemClickListener onMenuItemClickListener = new PopupMenu.OnMenuItemClickListener() { 369 | @Override 370 | public boolean onMenuItemClick(MenuItem menuItem) { 371 | switch (menuItem.getItemId()) { 372 | case R.id.menu_importText: 373 | LayoutInflater inflater = (LayoutInflater) me.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 374 | View view = inflater.inflate(R.layout.dialog_import_data, null); 375 | MessageDialog.show(me, getString(R.string.how_to_import), null, getString(R.string.iknow), new DialogInterface.OnClickListener() { 376 | @Override 377 | public void onClick(DialogInterface dialog, int which) { 378 | 379 | } 380 | }).setCustomView(view); 381 | break; 382 | case R.id.menu_exportAll: 383 | if (!checkPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"})) { 384 | DialogSettings.style = DialogSettings.STYLE_MATERIAL; 385 | SelectDialog.show(me, getString(R.string.need_permission_title), getString(R.string.import_need_permission), getString(R.string.start_get_permission), new DialogInterface.OnClickListener() { 386 | @Override 387 | public void onClick(DialogInterface dialog, int which) { 388 | requestPermission(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, new OnPermissionResponseListener() { 389 | @Override 390 | public void onSuccess(String[] permissions) { 391 | exportAll(); 392 | } 393 | 394 | @Override 395 | public void onFail() { 396 | 397 | } 398 | }); 399 | } 400 | }, getString(R.string.cancel), new DialogInterface.OnClickListener() { 401 | @Override 402 | public void onClick(DialogInterface dialog, int which) { 403 | 404 | } 405 | }); 406 | DialogSettings.style = DialogSettings.STYLE_KONGZUE; 407 | } else { 408 | new Handler().postDelayed(new Runnable() { 409 | @Override 410 | public void run() { 411 | if (isActive) { 412 | exportAll(); 413 | } 414 | } 415 | }, 500); 416 | } 417 | break; 418 | case R.id.menu_about: 419 | jump(AboutActivity.class); 420 | jumpAnim(R.anim.fade, R.anim.hold); 421 | break; 422 | } 423 | return false; 424 | } 425 | }; 426 | 427 | @Override 428 | public void finish() { 429 | super.finish(); 430 | jumpAnim(R.anim.slide_in_bottom, R.anim.slide_out_top); 431 | } 432 | 433 | class ViewHolder { 434 | TextView txtText; 435 | TextView txtTime; 436 | } 437 | } 438 | -------------------------------------------------------------------------------- /app/src/main/java/com/kongzue/notes/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.kongzue.notes.activity; 2 | 3 | import android.app.Dialog; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import android.content.DialogInterface; 7 | import android.content.Intent; 8 | import android.database.Cursor; 9 | import android.graphics.Bitmap; 10 | import android.graphics.BitmapFactory; 11 | import android.graphics.Canvas; 12 | import android.graphics.Typeface; 13 | import android.media.MediaMetadataRetriever; 14 | import android.net.Uri; 15 | import android.os.Build; 16 | import android.os.Environment; 17 | import android.os.Handler; 18 | import android.provider.MediaStore; 19 | import android.support.v4.content.FileProvider; 20 | import android.support.v7.app.AppCompatActivity; 21 | import android.os.Bundle; 22 | import android.text.Editable; 23 | import android.view.KeyEvent; 24 | import android.view.MotionEvent; 25 | import android.view.View; 26 | import android.view.ViewTreeObserver; 27 | import android.widget.ImageView; 28 | import android.widget.LinearLayout; 29 | import android.widget.RelativeLayout; 30 | import android.widget.ScrollView; 31 | import android.widget.TextView; 32 | import android.widget.Toast; 33 | 34 | import com.hanks.lineheightedittext.LineHeightEditText; 35 | import com.hanks.lineheightedittext.TextWatcher; 36 | import com.kongzue.baseframework.BaseActivity; 37 | import com.kongzue.baseframework.interfaces.DarkNavigationBarTheme; 38 | import com.kongzue.baseframework.interfaces.DarkStatusBarTheme; 39 | import com.kongzue.baseframework.interfaces.Layout; 40 | import com.kongzue.baseframework.interfaces.LifeCircleListener; 41 | import com.kongzue.baseframework.interfaces.NavigationBarBackgroundColor; 42 | import com.kongzue.baseframework.util.JumpParameter; 43 | import com.kongzue.baseframework.util.OnPermissionResponseListener; 44 | import com.kongzue.baseframework.util.Preferences; 45 | import com.kongzue.dialog.listener.DialogLifeCycleListener; 46 | import com.kongzue.dialog.listener.OnMenuItemClickListener; 47 | import com.kongzue.dialog.v2.BottomMenu; 48 | import com.kongzue.dialog.v2.DialogSettings; 49 | import com.kongzue.dialog.v2.MessageDialog; 50 | import com.kongzue.dialog.v2.SelectDialog; 51 | import com.kongzue.dialog.v2.TipDialog; 52 | import com.kongzue.dialog.v2.WaitDialog; 53 | import com.kongzue.kongzuedb.DBData; 54 | import com.kongzue.notes.R; 55 | import com.kongzue.notes.util.Base64Util; 56 | import com.kongzue.notes.util.DBUtil; 57 | import com.kongzue.notes.util.ViewWrapper; 58 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 59 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 60 | import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener; 61 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 62 | 63 | import org.json.JSONArray; 64 | import org.json.JSONObject; 65 | 66 | import java.io.File; 67 | import java.io.FileInputStream; 68 | import java.io.FileNotFoundException; 69 | import java.io.FileOutputStream; 70 | import java.io.IOException; 71 | import java.text.SimpleDateFormat; 72 | import java.util.Date; 73 | import java.util.Timer; 74 | import java.util.TimerTask; 75 | 76 | import ren.qinc.edit.PerformEdit; 77 | 78 | import static com.kongzue.baseframework.BaseFrameworkSettings.DEBUGMODE; 79 | import static com.kongzue.notes.NotesApp.navigationHeight; 80 | import static com.kongzue.notes.NotesApp.screenHeight; 81 | import static com.kongzue.notes.NotesApp.screenWidth; 82 | 83 | @Layout(R.layout.activity_main) 84 | @DarkNavigationBarTheme(true) 85 | @DarkStatusBarTheme(true) 86 | @NavigationBarBackgroundColor(a = 0) 87 | public class MainActivity extends BaseActivity { 88 | 89 | private static MainActivity mainActivity; 90 | private int boxRefresherBigHeight = -1; 91 | 92 | private RelativeLayout boxRoot; 93 | private RelativeLayout boxBody; 94 | private SmartRefreshLayout refreshLayout; 95 | private LinearLayout boxRefresher; 96 | private ImageView imgRefresher; 97 | private TextView txtRefresher; 98 | private LinearLayout boxEditor; 99 | private ScrollView scroller; 100 | private LineHeightEditText editTitle; 101 | private LineHeightEditText editNotes; 102 | private LinearLayout boxFooter; 103 | private ImageView imgLoadMore; 104 | private TextView txtLoadMore; 105 | private LinearLayout boxToolBar; 106 | private ImageView btnMore; 107 | private TextView btnDoubleSpace; 108 | private TextView btnUnDo; 109 | private TextView btnPaste; 110 | 111 | @Override 112 | public void initViews() { 113 | boxRoot = findViewById(R.id.box_root); 114 | boxBody = findViewById(R.id.box_body); 115 | refreshLayout = findViewById(R.id.refreshLayout); 116 | boxRefresher = findViewById(R.id.box_refresher); 117 | imgRefresher = findViewById(R.id.img_refresher); 118 | txtRefresher = findViewById(R.id.txt_refresher); 119 | boxEditor = findViewById(R.id.box_editor); 120 | scroller = findViewById(R.id.scroller); 121 | editTitle = findViewById(R.id.edit_title); 122 | editNotes = findViewById(R.id.edit_notes); 123 | boxFooter = findViewById(R.id.box_footer); 124 | imgLoadMore = findViewById(R.id.img_loadMore); 125 | txtLoadMore = findViewById(R.id.txt_loadMore); 126 | boxToolBar = findViewById(R.id.box_toolBar); 127 | btnMore = findViewById(R.id.btn_more); 128 | btnDoubleSpace = findViewById(R.id.btn_doubleSpace); 129 | btnUnDo = findViewById(R.id.btn_unDo); 130 | btnPaste = findViewById(R.id.btn_paste); 131 | } 132 | 133 | private PerformEdit performEdit; 134 | 135 | @Override 136 | public void initDatas(JumpParameter paramer) { 137 | mainActivity = this; 138 | 139 | navigationHeight = getNavbarHeight(); 140 | screenWidth = getDisplayWidth(); 141 | screenHeight = getRootHeight(); 142 | 143 | boxToolBar.setVisibility(View.GONE); 144 | //editNotes.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/SourceHanSerifCN-Light.otf")); 145 | 146 | performEdit = new PerformEdit(editNotes); 147 | performEdit.clearHistory(); 148 | 149 | if (paramer != null) { 150 | boolean newNote = paramer.getBoolean("newNote"); 151 | if (newNote) { 152 | dbData = null; 153 | editTitle.setText(""); 154 | editNotes.setText(""); 155 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM月dd日"); 156 | Date date = new Date(System.currentTimeMillis()); 157 | editTitle.setHint(simpleDateFormat.format(date)); 158 | } else { 159 | String importFilePath = paramer.getString("import"); 160 | if (!isNull(importFilePath)) { 161 | importFile(importFilePath); 162 | } else { 163 | DBData data = (DBData) paramer.get("data"); 164 | if (data != null) { 165 | setData(data); 166 | } else { 167 | int id = Preferences.getInstance().getInt(me, "cache", "id"); 168 | if (id != 0) { 169 | log(">>>id=" + id); 170 | try { 171 | dbData = DBUtil.getInstance().getDb().find(new DBData("notes").set("_id", id)).get(0); 172 | setData(dbData); 173 | } catch (Exception e) { 174 | Preferences.getInstance().set(me, "cache", "id", 0); 175 | } 176 | 177 | } 178 | } 179 | } 180 | } 181 | } else { 182 | int id = Preferences.getInstance().getInt(me, "cache", "id"); 183 | if (id != 0) { 184 | log(">>>id=" + id); 185 | try { 186 | dbData = DBUtil.getInstance().getDb().find(new DBData("notes").set("_id", id)).get(0); 187 | setData(dbData); 188 | } catch (Exception e) { 189 | Preferences.getInstance().set(me, "cache", "id", 0); 190 | } 191 | } else { 192 | dbData = null; 193 | editTitle.setText(""); 194 | editNotes.setText(""); 195 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM月dd日"); 196 | Date date = new Date(System.currentTimeMillis()); 197 | editTitle.setHint(simpleDateFormat.format(date)); 198 | } 199 | } 200 | 201 | refreshLayout.setEnableOverScrollBounce(true); 202 | refreshLayout.setEnableOverScrollDrag(true); 203 | refreshLayout.setEnableAutoLoadMore(false); 204 | 205 | boxRefresher.setPadding(0, getStatusBarHeight(), 0, 0); 206 | 207 | boxBody.post(new Runnable() { 208 | @Override 209 | public void run() { 210 | editNotes.setPadding( 211 | dip2px(20), 212 | dip2px(20), 213 | dip2px(10), 214 | dip2px(65) + navigationHeight 215 | ); 216 | } 217 | }); 218 | } 219 | 220 | private void importFile(final String importFilePath) { 221 | if (!checkPermissions(new String[]{"android.permission.READ_EXTERNAL_STORAGE"})) { 222 | SelectDialog.show(me, getString(R.string.need_permission_title), getString(R.string.import_need_permission), getString(R.string.start_get_permission), new DialogInterface.OnClickListener() { 223 | @Override 224 | public void onClick(DialogInterface dialog, int which) { 225 | requestPermission(new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, new OnPermissionResponseListener() { 226 | @Override 227 | public void onSuccess(String[] permissions) { 228 | WaitDialog.show(me, "请稍候..."); 229 | doImportData(importFilePath); 230 | } 231 | 232 | @Override 233 | public void onFail() { 234 | 235 | } 236 | }); 237 | } 238 | }, getString(R.string.cancel), new DialogInterface.OnClickListener() { 239 | @Override 240 | public void onClick(DialogInterface dialog, int which) { 241 | 242 | } 243 | }); 244 | } else { 245 | WaitDialog.show(me, "请稍候..."); 246 | new Handler().postDelayed(new Runnable() { 247 | @Override 248 | public void run() { 249 | if (isActive) { 250 | doImportData(importFilePath); 251 | } 252 | } 253 | }, 500); 254 | } 255 | } 256 | 257 | private void doImportData(String importFile) { 258 | try { 259 | importFile = java.net.URLDecoder.decode(importFile, "UTF-8"); 260 | } catch (Exception e) { 261 | if (DEBUGMODE) e.printStackTrace(); 262 | } 263 | 264 | importFile = FuckContent(importFile); 265 | 266 | importFile = importFile.replace("file:///", ""); 267 | if (!importFile.startsWith("/")) importFile = "/" + importFile; 268 | 269 | try { 270 | File file = new File(importFile); 271 | int length = (int) file.length(); 272 | byte[] buff = new byte[length]; 273 | FileInputStream fin = new FileInputStream(file); 274 | fin.read(buff); 275 | fin.close(); 276 | String result = new String(buff, "UTF-8"); 277 | 278 | WaitDialog.dismiss(); 279 | editTitle.setText(file.getName().replace(".txt", "")); 280 | editNotes.setText(result); 281 | 282 | TipDialog.show(me, getString(R.string.import_succeed), TipDialog.TYPE_FINISH); 283 | 284 | } catch (Exception e) { 285 | WaitDialog.dismiss(); 286 | if (DEBUGMODE) e.printStackTrace(); 287 | TipDialog.show(me, getString(R.string.import_error), TipDialog.TYPE_ERROR); 288 | } 289 | } 290 | 291 | private String FuckContent(String importFile) { 292 | String result = importFile; 293 | try { 294 | String[] us = importFile.split(":"); 295 | result = Environment.getExternalStorageDirectory().getPath() + "/" + us[us.length - 1]; 296 | } catch (Exception e) { 297 | 298 | } 299 | return result; 300 | } 301 | 302 | @Override 303 | public void setEvents() { 304 | btnMore.setOnClickListener(new View.OnClickListener() { 305 | @Override 306 | public void onClick(View v) { 307 | showIME(false, editNotes); 308 | String[] menu = {"全部复制", "生成长图片"}; 309 | BottomMenu.show(me, menu, new OnMenuItemClickListener() { 310 | @Override 311 | public void onClick(String text, int index) { 312 | switch (index) { 313 | case 0: 314 | String title = editTitle.getText().toString(); 315 | String contant = editNotes.getText().toString(); 316 | if (isNull(title)) { 317 | if (isNull(contant)) { 318 | TipDialog.show(me, "没有可复制的内容", TipDialog.SHOW_TIME_SHORT, TipDialog.TYPE_WARNING); 319 | return; 320 | } else { 321 | copy(contant); 322 | } 323 | } else { 324 | copy(title + "\n\n" + contant); 325 | } 326 | TipDialog.show(me, "已复制", TipDialog.SHOW_TIME_SHORT, TipDialog.TYPE_FINISH); 327 | break; 328 | case 1: 329 | if (!checkPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"})) { 330 | DialogSettings.style = DialogSettings.STYLE_MATERIAL; 331 | SelectDialog.show(me, getString(R.string.need_permission_title), getString(R.string.import_need_permission), getString(R.string.start_get_permission), new DialogInterface.OnClickListener() { 332 | @Override 333 | public void onClick(DialogInterface dialog, int which) { 334 | requestPermission(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, new OnPermissionResponseListener() { 335 | @Override 336 | public void onSuccess(String[] permissions) { 337 | exportBitmap(); 338 | } 339 | 340 | @Override 341 | public void onFail() { 342 | 343 | } 344 | }); 345 | } 346 | }, getString(R.string.cancel), new DialogInterface.OnClickListener() { 347 | @Override 348 | public void onClick(DialogInterface dialog, int which) { 349 | 350 | } 351 | }); 352 | DialogSettings.style = DialogSettings.STYLE_KONGZUE; 353 | } else { 354 | new Handler().postDelayed(new Runnable() { 355 | @Override 356 | public void run() { 357 | if (isActive) { 358 | exportBitmap(); 359 | } 360 | } 361 | }, 500); 362 | } 363 | break; 364 | } 365 | } 366 | }, true, "取消"); 367 | } 368 | }); 369 | 370 | refreshLayout.setOnRefreshListener(new OnRefreshListener() { 371 | @Override 372 | public void onRefresh(RefreshLayout refreshlayout) { 373 | refreshlayout.finishRefresh(500); 374 | jump(HistoryActivity.class); 375 | jumpAnim(R.anim.slide_in_top, R.anim.slide_out_bottom); 376 | } 377 | }); 378 | refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { 379 | @Override 380 | public void onLoadMore(RefreshLayout refreshlayout) { 381 | refreshlayout.finishLoadMore(500); 382 | jump(MainActivity.class, new JumpParameter().put("newNote", true)); 383 | finish(); 384 | jumpAnim(R.anim.slide_in_bottom, R.anim.slide_out_top); 385 | } 386 | }); 387 | 388 | refreshLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 389 | @Override 390 | public void onGlobalLayout() { 391 | int s = 0; 392 | if (refreshLayout.getHeight() >= boxRefresherBigHeight) { 393 | boxRefresherBigHeight = refreshLayout.getHeight(); 394 | boxToolBar.setVisibility(View.GONE); 395 | refreshLayout.setEnableRefresh(true); 396 | refreshLayout.setEnableLoadMore(true); 397 | s = 0; 398 | } else { 399 | boxToolBar.setVisibility(View.VISIBLE); 400 | refreshLayout.setEnableRefresh(false); 401 | refreshLayout.setEnableLoadMore(false); 402 | //scroller.smoothScrollBy(0,dip2px(me,30)); 403 | s = dip2px(44); 404 | } 405 | 406 | boxEditor.setPadding( 407 | 0, 408 | 0, 409 | 0, 410 | s 411 | ); 412 | } 413 | }); 414 | 415 | btnDoubleSpace.setOnClickListener(new View.OnClickListener() { 416 | @Override 417 | public void onClick(View view) { 418 | editNotes.getText().insert(editNotes.getSelectionStart(), "  "); 419 | } 420 | }); 421 | 422 | btnUnDo.setOnClickListener(new View.OnClickListener() { 423 | @Override 424 | public void onClick(View view) { 425 | performEdit.undo(); 426 | } 427 | }); 428 | 429 | btnPaste.setOnClickListener(new View.OnClickListener() { 430 | @Override 431 | public void onClick(View view) { 432 | String text = ""; 433 | try { 434 | ClipboardManager clip = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 435 | text = clip.getPrimaryClip().getItemAt(0).getText().toString(); 436 | } catch (Exception e) { 437 | } 438 | editNotes.getText().insert(editNotes.getSelectionStart(), text); 439 | } 440 | }); 441 | 442 | editNotes.addTextWatcher(new TextWatcher() { 443 | @Override 444 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 445 | 446 | } 447 | 448 | @Override 449 | public void onTextChanged(CharSequence s, int start, int before, int count) { 450 | 451 | } 452 | 453 | @Override 454 | public void afterTextChanged(Editable s) { 455 | whenTextChange(); 456 | } 457 | }); 458 | 459 | editNotes.setOnEditorActionListener(new TextView.OnEditorActionListener() { 460 | @Override 461 | public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 462 | if (editNotes.getText().toString().contains("  ")){ 463 | runOnMainDelayed(new Runnable() { 464 | @Override 465 | public void run() { 466 | editNotes.getText().insert(editNotes.getSelectionStart(),"  "); 467 | } 468 | },50); 469 | } 470 | return false; 471 | } 472 | }); 473 | 474 | editTitle.addTextWatcher(new TextWatcher() { 475 | @Override 476 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 477 | 478 | } 479 | 480 | @Override 481 | public void onTextChanged(CharSequence s, int start, int before, int count) { 482 | 483 | } 484 | 485 | @Override 486 | public void afterTextChanged(Editable s) { 487 | whenTextChange(); 488 | } 489 | }); 490 | } 491 | 492 | private void exportBitmap() { 493 | Bitmap bitmap = convertViewToBitmap(); 494 | final File saveFile = saveBitmap(bitmap); 495 | TipDialog.show(me, getString(R.string.export_to_local_finish), TipDialog.TYPE_FINISH); 496 | //Toast.makeText(me, "已存储在“内存”目录下的“记”文件夹中", Toast.LENGTH_LONG).show(); 497 | 498 | runOnMainDelayed(new Runnable() { 499 | @Override 500 | public void run() { 501 | WaitDialog.dismiss(); 502 | TipDialog.show(me, getString(R.string.export_to_local_finish), TipDialog.TYPE_FINISH).setDialogLifeCycleListener(new DialogLifeCycleListener() { 503 | @Override 504 | public void onCreate(Dialog alertDialog) { 505 | 506 | } 507 | 508 | @Override 509 | public void onShow(Dialog alertDialog) { 510 | 511 | } 512 | 513 | @Override 514 | public void onDismiss() { 515 | try { 516 | Intent share = new Intent(Intent.ACTION_SEND); 517 | share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(saveFile)); 518 | share.setType("image/jpeg");//此处可发送多种文件 519 | share.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 520 | share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 521 | 522 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 523 | Uri contentUri = FileProvider.getUriForFile(me, "com.kongzue.notes.fileProvider", saveFile); 524 | share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 525 | share.setDataAndType(contentUri,"image/jpeg"); 526 | } else { 527 | share.setDataAndType(Uri.fromFile(saveFile), "image/jpeg"); 528 | } 529 | startActivity(Intent.createChooser(share, "分享截图")); 530 | } catch (Exception e) { 531 | WaitDialog.dismiss(); 532 | TipDialog.show(me, getString(R.string.export_to_local_error), TipDialog.TYPE_ERROR); 533 | if (DEBUGMODE) e.printStackTrace(); 534 | } 535 | } 536 | }); 537 | } 538 | }, 500); 539 | } 540 | 541 | private File saveBitmap(Bitmap bm) { 542 | try { 543 | String title = textParse(editNotes.getText().toString()); 544 | if (isNull(title)) title = "img_" + ((int) ((Math.random() * 9 + 1) * 100000)) + ""; 545 | String path = Environment.getExternalStorageDirectory().getPath() + "/记"; 546 | File f = new File(path, title + ".jpg"); 547 | if (!f.exists()) { 548 | f.getParentFile().mkdirs(); 549 | f.createNewFile(); 550 | } 551 | FileOutputStream out = new FileOutputStream(f); 552 | bm.compress(Bitmap.CompressFormat.JPEG, 90, out); 553 | out.flush(); 554 | out.close(); 555 | return f; 556 | } catch (FileNotFoundException e) { 557 | e.printStackTrace(); 558 | } catch (IOException e) { 559 | e.printStackTrace(); 560 | } 561 | return null; 562 | } 563 | 564 | private String textParse(String text) { 565 | text = text.substring(0,10); 566 | text = text.replace(" ", ""); 567 | text = text.replace("\n", " "); 568 | return text; 569 | } 570 | 571 | private Timer timer = new Timer(); 572 | 573 | private void whenTextChange() { 574 | if (timer != null) { 575 | timer.cancel(); 576 | timer = new Timer(); 577 | } 578 | timer.schedule(new TimerTask() { 579 | @Override 580 | public void run() { 581 | if (isNull(editTitle.getText().toString().trim()) && isNull(editNotes.getText().toString().trim())) { 582 | return; 583 | } 584 | log("存储开始>>>"); 585 | if (dbData == null) { 586 | //创建操作 587 | dbData = new DBData("notes"); 588 | dbData.set("title", Base64Util.encode(editTitle.getText().toString())); 589 | dbData.set("content", Base64Util.encode(editNotes.getText().toString())); 590 | dbData.set("time", System.currentTimeMillis()); 591 | dbData.set("isSync", false); 592 | DBUtil.getInstance().getDb().add(dbData, false); 593 | dbData = DBUtil.getInstance().getDb().find(dbData).get(0); 594 | log("_id:" + dbData.getInt("_id")); 595 | } else { 596 | if (dbData.getInt("_id") != 0) { 597 | dbData.set("title", Base64Util.encode(editTitle.getText().toString())); 598 | dbData.set("content", Base64Util.encode(editNotes.getText().toString())); 599 | dbData.set("time", System.currentTimeMillis()); 600 | dbData.set("isSync", false); 601 | DBUtil.getInstance().getDb().update(dbData); 602 | } 603 | } 604 | } 605 | }, 500); // 延时1秒 606 | } 607 | 608 | @Override 609 | public void onBackPressed() { 610 | mainActivity = null; 611 | super.onBackPressed(); 612 | } 613 | 614 | @Override 615 | public void finish() { 616 | mainActivity = null; 617 | super.finish(); 618 | } 619 | 620 | public static MainActivity getMainActivity() { 621 | return mainActivity; 622 | } 623 | 624 | private DBData dbData; 625 | 626 | public void setData(DBData data) { 627 | log("setData"); 628 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM月dd日"); 629 | Date date = new Date(data.getLong("time")); 630 | editTitle.setHint(simpleDateFormat.format(date)); 631 | editTitle.setText(Base64Util.decode(data.getString("title"))); 632 | editNotes.setText(Base64Util.decode(data.getString("content"))); 633 | dbData = data; 634 | performEdit.clearHistory(); 635 | } 636 | 637 | @Override 638 | public void onPause() { 639 | if (dbData != null) 640 | Preferences.getInstance().set(me, "cache", "id", dbData.getInt("_id")); 641 | super.onPause(); 642 | } 643 | 644 | public Bitmap convertViewToBitmap() { 645 | // view.setDrawingCacheEnabled(true); 646 | // view.buildDrawingCache(); 647 | // Bitmap bitmap = view.getDrawingCache(); 648 | // return bitmap; 649 | 650 | Bitmap bkgImage = BitmapFactory.decodeResource(getResources(), R.mipmap.img_write_bkg); 651 | int h = 0; 652 | Bitmap bitmap = null; 653 | for (int i = 0; i < scroller.getChildCount(); i++) { 654 | h += scroller.getChildAt(i).getHeight(); 655 | } 656 | bitmap = Bitmap.createBitmap(scroller.getWidth(), h, Bitmap.Config.ARGB_8888); 657 | Canvas canvas = new Canvas(bitmap); 658 | 659 | //绘制背景 660 | int count = (h + bkgImage.getHeight() - 1) / bkgImage.getHeight(); 661 | for(int idx = 0; idx < count; ++ idx){ 662 | canvas.drawBitmap(bkgImage, 0, idx * bkgImage.getHeight(), null); 663 | } 664 | 665 | //绘制内容 666 | scroller.draw(canvas); 667 | return bitmap; 668 | } 669 | } 670 | --------------------------------------------------------------------------------