├── .gitignore
├── LICENSE
├── README.md
├── README_CN.md
├── build.gradle
├── docs
├── .nojekyll
├── README.md
├── _sidebar.md
├── apis
│ ├── commonapis.md
│ └── designapis.md
├── img
│ ├── alignCenter.png
│ ├── alignOpposite.png
│ ├── backgroudColor.png
│ ├── blur.png
│ ├── bold.png
│ ├── bullet.png
│ ├── color.png
│ ├── fontFamily.png
│ ├── image.png
│ ├── italic.png
│ ├── leadingMargin.png
│ ├── quote.png
│ ├── scale.png
│ ├── size.png
│ ├── space.png
│ ├── strikeThrough.png
│ ├── subscript.png
│ ├── superscript.png
│ ├── underline.png
│ └── url.png
├── index.html
├── others
│ └── q&a.md
└── usage
│ ├── activity.md
│ ├── activityresult.md
│ ├── customview.md
│ ├── datetime.md
│ ├── dialogs.md
│ ├── fragment.md
│ ├── intents.md
│ ├── json.md
│ ├── keyboard.md
│ ├── logger.md
│ ├── mmkv.md
│ ├── permissions.md
│ ├── spannablestring.md
│ ├── systembars.md
│ ├── uri.md
│ └── viewmodels.md
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── longan-design
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── dylanc
│ │ └── longan
│ │ └── design
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── dylanc
│ │ └── longan
│ │ └── design
│ │ ├── Dialogs.kt
│ │ ├── Internal.kt
│ │ ├── RecyclerView.kt
│ │ ├── Snackbar.kt
│ │ ├── TabLayout.kt
│ │ └── ViewPager2.kt
│ └── test
│ └── java
│ └── com
│ └── dylanc
│ └── longan
│ └── design
│ └── ExampleUnitTest.kt
├── longan
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── dylanc
│ │ └── longan
│ │ ├── DateTimeTest.kt
│ │ ├── ExampleInstrumentedTest.kt
│ │ └── StringTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── dylanc
│ │ │ └── longan
│ │ │ ├── Activity.kt
│ │ │ ├── ActivityResult.kt
│ │ │ ├── Annotations.kt
│ │ │ ├── AppInitializer.kt
│ │ │ ├── Application.kt
│ │ │ ├── Arrays.kt
│ │ │ ├── Bluetooth.kt
│ │ │ ├── Bundle.kt
│ │ │ ├── Canvas.kt
│ │ │ ├── Clipboard.kt
│ │ │ ├── Collections.kt
│ │ │ ├── ContentResolver.kt
│ │ │ ├── Crash.kt
│ │ │ ├── DateTime.kt
│ │ │ ├── DeviceInfo.kt
│ │ │ ├── Dimensions.kt
│ │ │ ├── DownloadManager.kt
│ │ │ ├── Encode.kt
│ │ │ ├── Encrypt.kt
│ │ │ ├── File.kt
│ │ │ ├── Flow.kt
│ │ │ ├── Fragment.kt
│ │ │ ├── Intents.kt
│ │ │ ├── Internal.kt
│ │ │ ├── Keyboard.kt
│ │ │ ├── Lifecycle.kt
│ │ │ ├── Location.kt
│ │ │ ├── Logger.kt
│ │ │ ├── MetaData.kt
│ │ │ ├── MultiLanguage.kt
│ │ │ ├── Network.kt
│ │ │ ├── Paths.kt
│ │ │ ├── PdfDocument.kt
│ │ │ ├── Resource.kt
│ │ │ ├── Rom.kt
│ │ │ ├── Screen.kt
│ │ │ ├── Share.kt
│ │ │ ├── Shell.kt
│ │ │ ├── Spannable.kt
│ │ │ ├── String.kt
│ │ │ ├── SystemBars.kt
│ │ │ ├── TextView.kt
│ │ │ ├── Threads.kt
│ │ │ ├── Toast.kt
│ │ │ ├── Uri.kt
│ │ │ ├── View.kt
│ │ │ ├── ViewModel.kt
│ │ │ └── activityresult
│ │ │ ├── ActivityResultLauncher.kt
│ │ │ ├── CreateDocument.kt
│ │ │ ├── CropPicture.kt
│ │ │ ├── EnableBluetooth.kt
│ │ │ ├── EnableLocation.kt
│ │ │ ├── GetContent.kt
│ │ │ ├── GetMultipleContents.kt
│ │ │ ├── LaunchAppSettings.kt
│ │ │ ├── LaunchNotificationSettings.kt
│ │ │ ├── LaunchWifiSettings.kt
│ │ │ ├── OpenDocument.kt
│ │ │ ├── OpenDocumentTree.kt
│ │ │ ├── OpenMultipleDocuments.kt
│ │ │ ├── PickContact.kt
│ │ │ ├── PickContent.kt
│ │ │ ├── RequestMultiplePermissions.kt
│ │ │ ├── RequestPermission.kt
│ │ │ ├── StartActivityForResult.kt
│ │ │ ├── StartIntentSenderForResult.kt
│ │ │ ├── TakePicture.kt
│ │ │ ├── TakePicturePreview.kt
│ │ │ └── TakeVideo.kt
│ └── res
│ │ ├── layout
│ │ └── design_layout_snackbar_include.xml
│ │ └── values
│ │ └── ids.xml
│ └── test
│ └── java
│ └── com
│ └── dylanc
│ └── longan
│ └── ExampleUnitTest.kt
├── sample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── dylanc
│ │ └── longan
│ │ └── sample
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── dylanc
│ │ │ └── longan
│ │ │ └── sample
│ │ │ ├── App.kt
│ │ │ └── ui
│ │ │ ├── ActivityResultActivity.kt
│ │ │ ├── DialogsActivity.kt
│ │ │ ├── InputTextActivity.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── PictureActivity.kt
│ │ │ └── SpannableStringActivity.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable-xhdpi
│ │ └── leaf.png
│ │ ├── drawable
│ │ ├── ic_baseline_arrow_back_24.xml
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_input_text.xml
│ │ ├── activity_picture.xml
│ │ ├── activity_recycler_view.xml
│ │ ├── activity_result.xml
│ │ ├── activity_spannable_string.xml
│ │ └── item_text.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ └── file_paths.xml
│ └── test
│ └── java
│ └── com
│ └── dylanc
│ └── longan
│ └── sample
│ └── ExampleUnitTest.kt
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .idea
4 | /local.properties
5 | /.idea/caches
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | /.idea/navEditor.xml
10 | /.idea/assetWizardSettings.xml
11 | .DS_Store
12 | /build
13 | /captures
14 | .externalNativeBuild
15 | .cxx
16 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.buildConfig = [
3 | 'versionCode' : 1,
4 | 'versionName' : "1.0.0",
5 | 'compileSdkVersion': 30,
6 | 'minSdkVersion' : 21,
7 | 'targetSdkVersion' : 30
8 | ]
9 | ext {
10 | appcompatVersion = '1.3.1'
11 | constraintLayoutVersion = '2.1.1'
12 | coilVersion = '1.4.0'
13 | coreVersion = '1.7.0-alpha01'
14 | espressoVersion = '3.4.0'
15 | glideVersion = '4.12.0'
16 | fragmentVersion = '1.3.6'
17 | lifecycleVersion = '2.4.0-alpha03'
18 | junitExtVersion = '1.1.3'
19 | junitVersion = '4.13.2'
20 | kotlinVersion = "1.5.31"
21 | materialVersion = '1.4.0'
22 | okioVersion = '3.0.0'
23 | starupVersion = '1.1.0'
24 | serializationVersion = "1.2.1"
25 | viewBindingKTXVersion = '2.1.0'
26 | }
27 | repositories {
28 | google()
29 | jcenter()
30 | }
31 | dependencies {
32 | classpath 'com.android.tools.build:gradle:4.2.1'
33 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
34 | classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
35 | }
36 | }
37 |
38 | allprojects {
39 | repositories {
40 | google()
41 | jcenter()
42 | maven { url 'https://www.jitpack.io' }
43 | }
44 | }
45 |
46 | task clean(type: Delete) {
47 | delete rootProject.buildDir
48 | }
49 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Longan
2 |
3 | [](https://www.jitpack.io/#DylanCaiCoding/Longan)
4 | [](https://github.com/DylanCaiCoding/Longan/blob/master/LICENSE)
5 | [](https://github.com/DylanCaiCoding/Longan)
6 |
7 | Longan 是一个简化 Android 开发的 Kotlin 工具库,可以使代码更加简洁易读。**目前有超过 500 个常用方法或属性,能有效提高开发效率**。
8 |
9 | 个人认为 API 设计对 Kotlin 工具类来说非常重要,因为 Kotlin 玩法很多,可以设计出很骚的用法,但不一定好用。所以个人花了大量时间去斟酌每一个扩展的用法,每个命名和用法都是经过了非常多的考虑,既要简洁易用又要清晰地描述功能不产生歧义。有的会参考官方 KTX 库的命名规则和用法,与官方用法统一能降低点学习成本。会用尽可能简洁轻量的代码实现功能,有兴趣的可以读下源码。整体会比大多数人封装的工具类好用。
10 |
11 | 本库会长期维护,有任何使用上的问题或者想要的功能都可以反馈。
12 |
13 | ## Gradle
14 |
15 | 在根目录的 build.gradle 添加:
16 |
17 | ```groovy
18 | allprojects {
19 | repositories {
20 | // ...
21 | maven { url 'https://www.jitpack.io' }
22 | }
23 | }
24 | ```
25 |
26 | 添加依赖:
27 |
28 | ```groovy
29 | dependencies {
30 | implementation 'com.github.DylanCaiCoding.Longan:longan:1.1.1'
31 | // Optional
32 | implementation 'com.github.DylanCaiCoding.Longan:longan-design:1.1.1'
33 | }
34 | ```
35 |
36 | ## 更新日志
37 |
38 | [Releases](https://github.com/DylanCaiCoding/Longan/releases)
39 |
40 | ## 作者其它的库
41 |
42 | | 库 | 简介 |
43 | | ------------------------------------------------------------ | ---------------------------------------------- |
44 | | [LoadingStateView](https://github.com/DylanCaiCoding/LoadingStateView) | 深度解耦标题栏或加载中、加载失败、无数据等视图 |
45 | | [ViewBindingKTX](https://github.com/DylanCaiCoding/ViewBindingKTX) | 最全面的 ViewBinding 工具 |
46 | | [MMKV-KTX](https://github.com/DylanCaiCoding/MMKV-KTX) | 用属性委托的方式使用 MMKV |
47 | | [Tracker](https://github.com/DylanCaiCoding/Tracker) | 基于西瓜视频的责任链埋点思路实现的轻量级埋点框架 |
48 |
49 | ## License
50 |
51 | ```
52 | Copyright (C) 2021. Dylan Cai
53 |
54 | Licensed under the Apache License, Version 2.0 (the "License");
55 | you may not use this file except in compliance with the License.
56 | You may obtain a copy of the License at
57 |
58 | http://www.apache.org/licenses/LICENSE-2.0
59 |
60 | Unless required by applicable law or agreed to in writing, software
61 | distributed under the License is distributed on an "AS IS" BASIS,
62 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63 | See the License for the specific language governing permissions and
64 | limitations under the License.
65 | ```
66 |
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 | * [介绍](/)
2 |
3 | * 所有 APIs
4 | * [Common APIS](/apis/commonapis)
5 | * [Design APIS](/apis/designapis)
6 |
7 | * 部分用法
8 | * [Activity](/usage/activity)
9 | * [ActivityResult](/usage/activityresult)
10 | * [CustomView](/usage/customview)
11 | * [DateTime](/usage/datetime)
12 | * [Dialogs](/usage/dialogs)
13 | * [Fragment](/usage/fragment)
14 | * [Intents](/usage/intents)
15 | * [Json](/usage/json)
16 | * [Keyboard](/usage/keyboard)
17 | * [Logger](/usage/logger)
18 | * [MMKV](/usage/mmkv)
19 | * [Permissions](/usage/permissions)
20 | * [SpannableString](/usage/spannablestring)
21 | * [SystemBars](/usage/systembars)
22 | * [Uri](/usage/uri)
23 | * [ViewModels](/usage/viewmodels)
24 |
25 | * 其它
26 | * [Q&A](/others/q&a)
--------------------------------------------------------------------------------
/docs/apis/designapis.md:
--------------------------------------------------------------------------------
1 | # Design APIs
2 |
3 | ## Gradle
4 |
5 | 添加依赖到 `build.gradle`:
6 |
7 | ```groovy
8 | dependencies {
9 | implementation 'com.github.DylanCaiCoding.Longan:longan-design:1.1.1'
10 | }
11 | ```
12 |
13 | > 下面用法中含有方括号 `[]` 的参数是可选的。
14 |
15 | ## [Dialogs.kt](https://github.com/DylanCaiCoding/Longan/blob/master/longan-design/src/main/java/com/dylanc/longan/design/Dialogs.kt)
16 |
17 | | 用法 | 作用 |
18 | | ------------------------------------------------------------ | ------------------ |
19 | | `Context/Fragment.alert([factory], message, [title]) {...}` | 显示消息弹框 |
20 | | `Context/Fragment.selector([factory], items, [title]) {...}` | 显示选项弹框 |
21 | | `Context/Fragment.singleChoiceSelector([factory], items, checkIndex, [title]) {...}` | 显示单选弹框 |
22 | | `Context/Fragment.singleChoiceSelector([factory], items, checkItems, [title]) {...}` | 显示多选弹框 |
23 | | `Context/Fragment.alertDialog([factory]) {...}` | 显示弹框 |
24 | | `initAlertBuilderFactory(factory)` | 初始化默认弹框样式 |
25 | | `Dialog/DialogInterface.doOnCancel {...}` | 监听取消事件 |
26 | | `Dialog/DialogInterface.doOnDismiss{...}` | 监听消失事件 |
27 | | `Dialog/DialogInterface.doOnShow{...}` | 监听显示事件 |
28 |
29 | ## [RecyclerView.kt](https://github.com/DylanCaiCoding/Longan/blob/master/longan-design/src/main/java/com/dylanc/longan/design/RecyclerView.kt)
30 |
31 | | 用法 | 作用 |
32 | | ------------------------------------------------------- | -------------------- |
33 | | `RecyclerView.setEmptyView(owner, emptyView)` | 设置空布局 |
34 | | `RecyclerView.Adapter<*>.observeDataEmpty(owner) {...}` | 观察数据是否为空 |
35 | | `RecyclerView.smoothScrollToStartPosition(position)` | 顺滑地滚动到起始位置 |
36 | | `RecyclerView.smoothScrollToEndPosition(position)` | 顺滑地滚动到末端位置 |
37 | | `RecyclerView.addItemPadding(...)` | 列表每一项都加边距 |
38 |
39 | ## [Snackbar.kt](https://github.com/DylanCaiCoding/Longan/blob/master/longan-design/src/main/java/com/dylanc/longan/design/Snackbar.kt)
40 |
41 | | 用法 | 作用 |
42 | | ------------------------------------------------------------ | ------------------- |
43 | | `Activity/Fragment/View.snackbar(message, [actionText], [action])` | 显示 Snackbar |
44 | | `Activity/Fragment/View.longSnackbar(message, [actionText], [action])` | 长时间显示 Snackbar |
45 | | `Activity/Fragment/View.indefiniteSnackbar(message, [actionText], [action])` | 永久显示 Snackbar |
46 |
47 | ## [TabLayout.kt](https://github.com/DylanCaiCoding/Longan/blob/master/longan-design/src/main/java/com/dylanc/longan/design/TabLayout.kt)
48 |
49 | | 用法 | 作用 |
50 | | ------------------------------------------------------------ | ---------------- |
51 | | `TabLayout.setupWithViewPager(viewPager, [autoRefresh]) {...}` | 设置 ViewPager |
52 | | `TabLayout.setupWithViewPager2(viewPager, [autoRefresh], [enableScroll]) {...}` | 设置 ViewPager2 |
53 | | `TabLayout.Tab.setCustomView(layoutId) {...}` | 设置自定义布局 |
54 | | `TabLayout.addTab(text) {...}` | 添加标签 |
55 | | `TabLayout.doOnTabSelected {...}` | 监听标签被选中 |
56 | | `TabLayout.doOnTabUnselected {...}` | 监听标签取消选中 |
57 | | `TabLayout.doOnTabReselected {...}` | 监听标签重新选中 |
58 | | `TabLayout.addOnTabSelectedListener(onTabSelected, onTabUnselected, onTabReselected) ` | 监听标签选中事件 |
59 |
60 | ## [ViewPager2.kt](https://github.com/DylanCaiCoding/Longan/blob/master/longan-design/src/main/java/com/dylanc/longan/design/ViewPager2.kt)
61 |
62 | | 用法 | 作用 |
63 | | ------------------------------------------------------------ | ------------------------- |
64 | | `FragmentActivity/Fragment.FragmentStateAdapter(fragments, [isLazyLoading])` | 创建 FragmentStateAdapter |
65 | | `FragmentActivity/Fragment.FragmentStateAdapter(itemCount, [isLazyLoading]) {...}` | 创建 FragmentStateAdapter |
66 | | `ViewPager2.findFragment(fragmentManager, position)` | 获取 Fragment |
--------------------------------------------------------------------------------
/docs/img/alignCenter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/alignCenter.png
--------------------------------------------------------------------------------
/docs/img/alignOpposite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/alignOpposite.png
--------------------------------------------------------------------------------
/docs/img/backgroudColor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/backgroudColor.png
--------------------------------------------------------------------------------
/docs/img/blur.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/blur.png
--------------------------------------------------------------------------------
/docs/img/bold.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/bold.png
--------------------------------------------------------------------------------
/docs/img/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/bullet.png
--------------------------------------------------------------------------------
/docs/img/color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/color.png
--------------------------------------------------------------------------------
/docs/img/fontFamily.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/fontFamily.png
--------------------------------------------------------------------------------
/docs/img/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/image.png
--------------------------------------------------------------------------------
/docs/img/italic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/italic.png
--------------------------------------------------------------------------------
/docs/img/leadingMargin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/leadingMargin.png
--------------------------------------------------------------------------------
/docs/img/quote.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/quote.png
--------------------------------------------------------------------------------
/docs/img/scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/scale.png
--------------------------------------------------------------------------------
/docs/img/size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/size.png
--------------------------------------------------------------------------------
/docs/img/space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/space.png
--------------------------------------------------------------------------------
/docs/img/strikeThrough.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/strikeThrough.png
--------------------------------------------------------------------------------
/docs/img/subscript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/subscript.png
--------------------------------------------------------------------------------
/docs/img/superscript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/superscript.png
--------------------------------------------------------------------------------
/docs/img/underline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/underline.png
--------------------------------------------------------------------------------
/docs/img/url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DylanCaiCoding/Longan/817e5061fbec303d84f51a79e18d59e89843434e/docs/img/url.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/docs/others/q&a.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ## 为什么叫 `Longan`?
4 |
5 | 个人想用个水果名来作为库名,最初想到的是 `Guava` (石榴),感觉非常有代表性。但是发现有一个谷歌的同名库,所以换了另一个也是多子的水果 `Longan` (龙眼)。
--------------------------------------------------------------------------------
/docs/usage/activity.md:
--------------------------------------------------------------------------------
1 | # Activity 用法
2 |
3 | ## 跳转 Activity
4 |
5 | 简单地跳转:
6 |
7 | ```kotlin
8 | startActivity()
9 | ```
10 |
11 | 带参数跳转:
12 |
13 | ```kotlin
14 | startActivity("id" to 5)
15 | ```
16 |
17 | 带参数跳转推荐用下面的写法:
18 |
19 | ```kotlin
20 | class SomeActivity : AppCompatActivity() {
21 | private val id: String by safeIntentExtras(KEY_ID)
22 |
23 | //...
24 |
25 | companion object {
26 | fun start(id: String) = startActivity(KEY_ID to id)
27 | }
28 | }
29 | ```
30 |
31 | ```kotlin
32 | SomeActivity.start(id)
33 | ```
34 |
35 | 编写一个静态的 `start()` 方法传入所需的参数并跳转,在跳转的页面通过委托的方式获取值,可查看 [Intent](/intents) 的用法。调用静态方法跳转可以避免传漏或传错参数。
36 |
37 | ## 结束 Activity 时回调结果
38 |
39 | 在 `startActivityForResult()` 跳转的页面通常需要在结束的时候带上回调的结果,一般需要几行代码来实现。比如:
40 |
41 | ```kotlin
42 | val intent = Intent()
43 | intent.putExtra("id", 5)
44 | intent.putExtra("name", name)
45 | setResult(RESULT_OK, intent)
46 | finish()
47 | ```
48 |
49 | 几行代码有点繁琐,所以提供了一种更简单的方式能用一行代码实现:
50 |
51 | ```kotlin
52 | finishWithResult("id" to 5, "name" to name)
53 | ```
54 |
55 | ## Activity 堆栈管理
56 |
57 | 可使用 `topActivity` 获取栈顶的 Activity,使用 `activityList` 获取 Activity 堆栈的列表。
58 |
59 | 判断 Activity 是否在堆栈中:
60 |
61 | ```kotlin
62 | if (isActivityExistsInStack()) {
63 | // ...
64 | }
65 | ```
66 |
67 | 结束某个 Activity:
68 |
69 | ```kotlin
70 | finishActivity()
71 | ```
72 |
73 | 结束所有 Activity:
74 |
75 | ```kotlin
76 | finishAllActivities()
77 | ```
78 |
79 | 结束除了最新以外的所有 Activity:
80 |
81 | ```kotlin
82 | finishAllActivitiesExceptNewest()
83 | ```
84 |
85 | ## 双击返回键退出
86 |
87 | 快速实现双击返回键退出:
88 |
89 | ```kotlin
90 | pressBackTwiceToExitApp("再次点击退出应用")
91 | ```
92 |
93 | 默认 2 秒内第二次点击返回键才退出,可以传多一个参数修改间隔时间:
94 |
95 | ```kotlin
96 | pressBackTwiceToExitApp("再次点击退出应用", delayMillis = 1500)
97 | ```
98 |
99 | 如果需要自定义吐司或者换成 `Snackbar`:
100 |
101 | ```kotlin
102 | pressBackTwiceToExitApp {
103 | snackbar("再次点击退出应用")
104 | }
105 | ```
106 |
107 | ## 点击返回键不退出
108 |
109 | 有时需要点击返回不退出应用,直接返回桌面:
110 |
111 | ```kotlin
112 | pressBackToNotExitApp()
113 | ```
114 |
115 | ## 强转 Activity
116 |
117 | 有些时候作用域内的 this 不是 Activity,这时我们用到 Activity 就要指明用哪个 this,比如 `this@SignInActivity`。所以增加了拓展属性 `context`, `activity`, `fragmentActivity`, `lifecycleOwner`,将 Activity 强转成对应的类型进行使用,可以简化代码,提高代码的可读性。
--------------------------------------------------------------------------------
/docs/usage/customview.md:
--------------------------------------------------------------------------------
1 | # 自定义 View 用法
2 |
3 | ## 获取自定义属性
4 |
5 | 获取自定义属性需要不少代码来实现。
6 |
7 | ```kotlin
8 | val attr = context.obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0)
9 | textSize = attr.getDimension(R.styleable.CustomView_textSize, 12.sp)
10 | textColor = attr.getColor(R.styleable.CustomView_textColor, ContextCompat.getColor(context, R.color.text_normal))
11 | icon = attr.getDrawable(R.styleable.CustomView_icon) ?: ContextCompat.getDrawable(context, R.drawable.default_icon)
12 | iconSize = attr.getDimension(R.styleable.CustomView_iconSize, 30.dp)
13 | attr.recycle()
14 | ```
15 |
16 | 所以提供了更简洁的方式来获取自定义属性:
17 |
18 | ```kotlin
19 | withStyledAttrs(attrs, R.styleable.CustomView) {
20 | textSize = getDimension(R.styleable.CustomView_textSize, 12.sp)
21 | textColor = getColor(R.styleable.CustomView_textColor, getCompatColor(R.color.text_normal))
22 | icon = getDrawable(R.styleable.CustomView_icon) ?: getCompatDrawable(R.drawable.default_icon)
23 | iconSize = getDimension(R.styleable.CustomView_iconSize, 30.dp)
24 | }
25 | ```
26 |
27 | ## 绘制居中文字
28 |
29 | 绘制居中或者垂直居中的文字:
30 |
31 | ```kotlin
32 | canvas.drawCenterText(text, centerX, centerY, paint)
33 | canvas.drawCenterVerticalText(text, centerX, centerY, paint)
34 | ```
35 |
36 | ## 触摸相关
37 |
38 | 获取当前触摸位置的子 View:
39 |
40 | ```kotlin
41 | val touchedView = findTouchedChild(ev.rawX, ev.rawY)
42 | ```
43 |
44 | 判断某个 View 是不是在触摸位置上:
45 | ```kotlin
46 | if (view.isTouchedAt(ev.rawX, ev.rawY)) {
47 | // ...
48 | }
49 | ```
--------------------------------------------------------------------------------
/docs/usage/datetime.md:
--------------------------------------------------------------------------------
1 | # DateTime 用法
2 |
3 | 推荐用 Java8 的 `LocalDataTime`,后续会封装扩展方法简化用法。
4 |
--------------------------------------------------------------------------------
/docs/usage/dialogs.md:
--------------------------------------------------------------------------------
1 | # Dialogs 用法
2 |
3 | 保留了 `Anko` 的用法并做了优化。
4 |
5 | ## Toasts
6 |
7 | 简单地显示 [Toast](https://developer.android.com/guide/topics/ui/notifiers/toasts.html) 消息,修复了 Android 7.x 的 `BadTokenException` 异常。
8 |
9 | ```kotlin
10 | toast("Hi there!")
11 | toast(R.string.message)
12 | longToast("Wow, such duration")
13 | ```
14 |
15 | ## SnackBars
16 |
17 | 简单地显示 [SnackBar](https://developer.android.com/reference/android/support/design/widget/Snackbar.html) 消息。
18 |
19 | ```kotlin
20 | snackbar("Hi there!")
21 | snackbar(R.string.message)
22 | longSnackbar("Wow, such duration")
23 | indefiniteSnackbar("Wow, always show")
24 | snackbar("Action, reaction", "Click me!") { doStuff() }
25 | ```
26 |
27 | ## Alerts
28 |
29 | 用 DSL 语法显示[对话框](https://developer.android.com/guide/topics/ui/dialogs.html).
30 |
31 | ```kotlin
32 | alert("Hi, I'm Roy", "Have you tried turning it off and on again?") {
33 | okButton { toast("Oh…") }
34 | cancelButton {}
35 | }
36 | ```
37 |
38 | 上面的代码默认显示 `MaterialAlertDialog`,如果你想切换成默认使用 Appcompat 的`AlertDialog`,可以配置 `AlertFactory`:
39 |
40 | ```kotlin
41 | initAlertBuilderFactory(Appcompat)
42 | ```
43 |
44 | 或者切换某一次对话框的样式:
45 |
46 | ```kotlin
47 | alert(Appcompat, "Some text message")
48 | ```
49 |
50 | 默认提供 `Appcompat` 和 `Material` 可选,你可以实现 `AlertBuilderFactory` 接口进行自定义。后续会对更多的弹框样式进行支持。
51 |
52 | ## Selectors
53 |
54 | `selector()` 显示一个带有文本项列表的对话框:
55 |
56 | ```kotlin
57 | val countries = listOf("China", "Russia", "USA", "Australia")
58 | selector(countries, "Where are you from?") { dialog, i ->
59 | toast("So you're living in ${countries[i]}, right?")
60 | }
61 | ```
62 |
63 | `singleChoiceSelector()` 显示一个单选列表的对话框:
64 |
65 | ```kotlin
66 | private var checkedCountry = "China"
67 |
68 | private fun selectCountry() {
69 | val countries = listOf("China", "Russia", "USA", "Australia")
70 | val checkedIndex = countries.indexOfFirst { it == checkedCountry }
71 | singleChoiceSelector(countries, checkedIndex, "Where are you from?") { dialog, i ->
72 | checkedCountry = countries[i]
73 | toast("You're living in ${checkedCountry}.")
74 | dialog.dismiss()
75 | }
76 | }
77 | ```
78 |
79 | `multiChoiceSelector()` 显示一个多选列表的对话框:
80 |
81 | ```kotlin
82 | private val foods = listOf("Apple", "Banana", "Pear", "Peach")
83 | private val checkedItems = BooleanArray(foods.size)
84 |
85 | private fun selectFoods() {
86 | multiChoiceSelector(foods, checkedItems, "What do you want to eat?") { dialog, i, isChecked ->
87 | checkedItems[i] = isChecked
88 | }.doOnDismiss {
89 | toast("So you want to eat ${checkedItems.filter { it }.size} foods.")
90 | }
91 | }
92 | ```
93 |
94 |
95 |
--------------------------------------------------------------------------------
/docs/usage/fragment.md:
--------------------------------------------------------------------------------
1 | # Fragment 用法
2 |
3 | ## 创建带参数的 Fragment
4 |
5 | 传参给 Fragment 需要设置 Bundle 对象,通常 Bundle 对象每增加一个额外的参数,就需要增加一行代码。例如:
6 |
7 | ```kotlin
8 | val fragment = SomeFragment()
9 | val arguments = Bundle()
10 | arguments.putInt("id", 5)
11 | arguments.putString("title", title)
12 | fragment.arguments = arguments
13 | ```
14 |
15 | 而 `Longan` 提供了更简单的方式实现上面的功能。
16 |
17 | ```kotlin
18 | val fragment = SomeFragment().withArguments("id" to 5, "title" to title)
19 | ```
20 |
21 | ## Fragment 的 arguments 委托
22 |
23 | 使用 `arguments()` 委托获取传递给 Fragment 的数据。
24 |
25 | ```kotlin
26 | val name: String? by arguments(KEY_NAME)
27 | val count: Int by arguments(KEY_COUNT, default = 0)
28 | ```
29 |
30 | 如果可以人为确保一定能获取到值,又不想传默认值,可以用 `safeArguments()` 进行委托。
31 |
32 | ```kotlin
33 | val phone: String by safeArguments(KEY_PHONE)
34 | ```
35 |
36 | 创建带参数 Fragment 的推荐写法:
37 |
38 | ```kotlin
39 | class SomeFragment : Fragment() {
40 | private val id: String by safeArguments(KEY_ID)
41 |
42 | // ...
43 |
44 | companion object {
45 | fun newInstance(id: String) = SomeFragment().withArguments(KEY_ID to id)
46 | }
47 | }
48 | ```
49 |
50 | ```kotlin
51 | val fragment = SomeFragment.newInstance(id)
52 | ```
53 |
54 | 编写一个静态的 `newInstance()` 方法传入所需的参数并创建 Fragment,在 Fragment 内通过委托的方式获取值。调用静态方法可以防止传漏或传错参数。
55 |
--------------------------------------------------------------------------------
/docs/usage/intents.md:
--------------------------------------------------------------------------------
1 | # Intents 用法
2 |
3 | 参考和保留了 `Anko` 部分功能。
4 |
5 | ## 创建 Intent
6 |
7 | 通常 Intent 每增加一个额外的参数或 flag,就需要增加一行代码。例如:
8 |
9 | ```kotlin
10 | val intent = Intent(this, SomeOtherActivity::class.java)
11 | intent.putExtra("id", 5)
12 | intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP)
13 | startActivity(intent)
14 | ```
15 |
16 | 而 `Longan` 提供了更简单的方式实现上面的功能。
17 |
18 | ```kotlin
19 | startActivity(intentOf("id" to 5).singleTop())
20 | ```
21 |
22 | ## 获取 Intent 的参数
23 |
24 | 使用 `intentExtras()` 委托获取 `Intent` 的数据。
25 |
26 | ```kotlin
27 | val name: String? by intentExtras(KEY_NAME)
28 | val count: Int by intentExtras(KEY_COUNT, default = 0)
29 | ```
30 |
31 | 如果可以人为确保一定能获取到值,又不想传默认值,可以用 `safeIntentExtras()` 进行委托。
32 |
33 | ```kotlin
34 | val phone: String by safeIntentExtras(KEY_PHONE)
35 | ```
36 |
37 | ## 常用的 Intent 操作
38 |
39 | 拨号(并未呼叫),无需权限:
40 |
41 | ```kotlin
42 | dial(number)
43 | ```
44 |
45 | 拨打电话,需要 `CALL_PHONE` 权限:
46 |
47 | ```kotlin
48 | makeCall(number)
49 | ```
50 |
51 | 发送短信:
52 |
53 | ```kotlin
54 | sendSMS(number, content)
55 | ```
56 |
57 | 发送邮件:
58 |
59 | ```kotlin
60 | email(email, subject, text)
61 | ```
62 |
63 | 安装 APK:
64 |
65 | ```kotlin
66 | installAPK(uri)
67 | ```
68 |
69 | 以上方法如果发送了 `Intent`,则方法返回 true。
70 |
71 | ## 分享的 Intent
72 |
73 | 分享功能是用 `ShareCompat` 实现,无返回值。
74 |
75 | 分享文字:
76 |
77 | ```kotlin
78 | shareText(text)
79 | ```
80 |
81 | 分享单张图片:
82 |
83 | ```kotlin
84 | shareImage(uri)
85 | ```
86 |
87 | 分享多张图片:
88 |
89 | ```kotlin
90 | shareImages(uris)
91 | ```
92 |
93 | 分享文字和单张图片:
94 |
95 | ```kotlin
96 | shareTextAndImage(text, uri)
97 | ```
98 |
99 | 分享文字和多张图片:
100 |
101 | ```kotlin
102 | shareTextAndImages(text, uris)
103 | ```
104 |
105 | 分享单个文件:
106 |
107 | ```kotlin
108 | shareFile(uri)
109 | ```
110 |
111 |
112 | 分享多个文件:
113 |
114 | ```kotlin
115 | shareFiles(uris)
116 | ```
--------------------------------------------------------------------------------
/docs/usage/json.md:
--------------------------------------------------------------------------------
1 | # Json 用法
2 |
3 | 暂未对 Json 序列化进行封装,可以选择使用以下的库:
4 |
5 | - [kotlinx-serialization](https://github.com/Kotlin/kotlinx.serialization)
6 | - [moshi](https://github.com/square/moshi)
7 |
8 | 不推荐用 `Gson` 序列化。
--------------------------------------------------------------------------------
/docs/usage/keyboard.md:
--------------------------------------------------------------------------------
1 | # 键盘用法
2 |
3 | ## 显示或隐藏键盘
4 |
5 | 显示键盘:
6 |
7 | ```kotlin
8 | edtName.showKeyboard()
9 | ```
10 |
11 | 隐藏键盘:
12 |
13 | ```kotlin
14 | edtName.hideKeyboard()
15 | ```
16 |
17 | 切换键盘:
18 |
19 | ```kotlin
20 | edtName.toggleKeyboard()
21 | ```
22 |
23 | 判断键盘是否显示:
24 |
25 | ```kotlin
26 | if (edtName.isKeyboardVisible) {
27 | // ...
28 | }
29 | ```
--------------------------------------------------------------------------------
/docs/usage/logger.md:
--------------------------------------------------------------------------------
1 | # 日志用法
2 |
3 | 参考了 `AnkoLogger` 并进行了优化和改进。
4 |
5 | ## 打印日志
6 |
7 | 相对于 [android.util.Log](https://developer.android.com/reference/android/util/Log.html) 会更加易用,不需要传 tag,默认 tag 是当前的类名。例如:
8 |
9 | ```kotlin
10 | class MainActivity : AppCompatActivity() {
11 |
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | logInfo("test")
15 | logDebug(5) // 执行 `.toString()` 后再打印
16 | logWarn(null) // 将会打印 "null"
17 | }
18 | }
19 | ```
20 |
21 | | android.util.Log | Logger |
22 | | ---------------- | -------------- |
23 | | `v()` | `logVerbose()` |
24 | | `d()` | `logDebug()` |
25 | | `i()` | `logInfo()` |
26 | | `w()` | `logWarn()` |
27 | | `e()` | `logError()` |
28 | | `wtf()` | `logWtf()` |
29 |
30 | ## 修改 Tag
31 |
32 | 实现 `Logger` 接口,重写 `loggerTag` 属性,就能修改在该类下打印日志的 tag。
33 |
34 | ```kotlin
35 | class MainActivity : AppCompatActivity(), Logger {
36 |
37 | override val loggerTag: String get() = "new tag"
38 |
39 | override fun onCreate(savedInstanceState: Bundle?) {
40 | super.onCreate(savedInstanceState)
41 | logInfo("test")
42 | logDebug(5)
43 | logWarn(null)
44 | }
45 | }
46 | ```
47 |
48 | 或者创建 `Logger` 对象去调用对应的打印方法。
49 |
50 | ```kotlin
51 | class MainActivity : AppCompatActivity() {
52 |
53 | private val logger = Logger() // 用其它类的类名作为 tag
54 | private val loggerWithSpecificTag = Logger("my_tag")
55 |
56 | override fun onCreate(savedInstanceState: Bundle?) {
57 | super.onCreate(savedInstanceState)
58 | logger.logInfo("test")
59 | loggerWithSpecificTag.logDebug(5)
60 | }
61 | }
62 | ```
63 |
64 | ## 过滤日志
65 |
66 | 可以在初始化时配置是否打印日志。
67 |
68 | ```kotlin
69 | initLogger(BuildConfig.DEBUG)
70 | ```
71 |
72 | 更复杂的过滤规则可以设置 `Logger.isLoggable`。
73 |
74 | ```kotlin
75 | Logger.isLoggable = { level, tag ->
76 | // 可根据打印等级和标签判断是否需要打印
77 | }
78 | ```
79 |
80 | ## 自定义打印格式
81 |
82 | 创建一个类实现 `LoggerPrinter` 接口,实现打印方法。
83 |
84 | ```kotlin
85 | class CustomLoggerPrinter : LoggerPrinter {
86 | override fun log(level: LogLevel, tag: String, message: String, thr: Throwable?) {
87 | when (level) {
88 | LogLevel.VERBOSE -> //...
89 | LogLevel.DEBUG -> //...
90 | LogLevel.INFO -> //...
91 | LogLevel.WARN -> //...
92 | LogLevel.ERROR -> //...
93 | }
94 | }
95 |
96 | override fun logWtf(tag: String, message: String, thr: Throwable?) {
97 | //...
98 | }
99 | }
100 | ```
101 |
102 | 初始化时设置 printer。
103 |
104 | ```kotlin
105 | initLogger(printer = CustomLoggerPrinter())
106 | ```
107 |
108 | 后续会对默认的打印格式进行升级。
--------------------------------------------------------------------------------
/docs/usage/mmkv.md:
--------------------------------------------------------------------------------
1 | # MMKV 用法
2 |
3 | 由于官方已经不推荐用 `SharedPreferences`,所以把之前封装的 `SharedPreferences` 工具类改成用 `MMKV` 实现。
4 |
5 | 考虑到有些人可能会用官方的 `DataStore`,就另写了一个库 [MMKV-KTX](https://github.com/DylanCaiCoding/MMKV-KTX) 作为可选项。
6 |
7 | ## Gradle
8 |
9 | 在根目录的 `build.gradle` 添加:
10 |
11 | ```groovy
12 | allprojects {
13 | repositories {
14 | //...
15 | maven { url 'https://www.jitpack.io' }
16 | }
17 | }
18 | ```
19 |
20 | 在模块的 `build.gradle` 添加依赖:
21 |
22 | ```groovy
23 | dependencies {
24 | implementation 'com.github.DylanCaiCoding:MMKV-KTX:1.2.15'
25 | }
26 | ```
27 |
28 | ## 基础用法
29 |
30 | 让一个类实现 `MMKVOwner` 接口,即可通过 `by mmkvXXXX()` 方法将属性委托给 `MMKV`,例如:
31 |
32 | ```kotlin
33 | object DataRepository : MMKVOwner {
34 | var isFirstLaunch by mmkvBool(default = true)
35 | var user by mmkvParcelable()
36 | }
37 | ```
38 |
39 | 设置或获取属性的值会调用对应的 encode() 或 decode() 函数,**用属性名作为 key 值**。
40 |
41 | 支持以下类型:
42 |
43 | | 方法 | 默认值 |
44 | | ------------------ | ------ |
45 | | `mmkvInt()` | 0 |
46 | | `mmkvLong()` | 0L |
47 | | `mmkvBool()` | false |
48 | | `mmkvFloat()` | 0f |
49 | | `mmkvDouble()` | 0.0 |
50 | | `mmkvString()` | / |
51 | | `mmkvStringSet()` | / |
52 | | `mmkvBytes()` | / |
53 | | `mmkvParcelable()` | / |
54 |
55 | 1.2.15 版本新增 `mmkvXXXX().asLiveData()` 函数将属性委托给 `LiveData`,例如:
56 |
57 | ```kotlin
58 | object SettingRepository : MMKVOwner {
59 | val nightMode by mmkvBool().asLiveData()
60 | }
61 |
62 | SettingRepository.nightMode.observe(this) {
63 | checkBox.isChecked = it
64 | }
65 |
66 | SettingRepository.nightMode.value = true
67 | ```
68 |
69 | 在 `MMKVOwner` 的实现类可以获取 `kv` 对象进行删除值或清理缓存等操作:
70 |
71 | ```kotlin
72 | kv.removeValueForKey(::isFirstLaunch.name)
73 | kv.clearAll()
74 | ```
75 |
76 | ## 进阶用法
77 |
78 | ### 取消自动初始化
79 |
80 | 本库会自动调用 `MMKV.initialize(context)` 进行初始化,如果在用了 MMKV 的项目中使用本库,建议把自动初始化给取消了,多次初始化可能会导致数据异常。
81 |
82 | 需要添加 App Startup 的依赖:
83 |
84 | ```groovy
85 | implementation "androidx.startup:startup-runtime:1.1.0"
86 | ```
87 |
88 | 然后在 `AndroidManifest.xml` 添加以下代码就能取消自动初始化操作:
89 |
90 | ```xml
91 |
92 |
97 |
100 |
101 |
102 | ```
103 |
104 | ### 重写 kv 对象
105 |
106 | 有一些场景需要使用新的 MMKV 对象,此时可以重写 `kv` 属性。
107 |
108 | #### 区别存储
109 |
110 | 比如我们在组件化项目进行开发,各自负责的模块是不知道别人用了什么 key 值,重名了可能被覆盖。这就可以重写 `kv` 属性创建不同的 `MMKV` 实例来规避这个问题。
111 |
112 | ```kotlin
113 | object UserRepository : MMKVOwner {
114 | // ...
115 |
116 | override val kv: MMKV = MMKV.mmkvWithID("user")
117 | }
118 | ```
119 |
120 | #### 多进程
121 |
122 | MMKV 默认是单进程模式,如果你需要多进程支持:
123 |
124 | ```kotlin
125 | object DataRepository : MMKVOwner {
126 | // ...
127 |
128 | override val kv: MMKV = MMKV.mmkvWithID("InterProcessKV", MMKV.MULTI_PROCESS_MODE)
129 | }
130 | ```
131 |
132 | #### 加密
133 |
134 | MMKV 默认明文存储所有 key-value,依赖 Android 系统的沙盒机制保证文件加密。如果你担心信息泄露,你可以选择加密 MMKV。
135 |
136 | ```kotlin
137 | object DataRepository : MMKVOwner {
138 | // ...
139 |
140 | private const val cryptKey = "My-Encrypt-Key"
141 |
142 | override val kv: MMKV = MMKV.mmkvWithID("MyID", MMKV.SINGLE_PROCESS_MODE, cryptKey)
143 | }
144 | ```
145 |
146 | ## 更新日志
147 |
148 | [Releases](https://github.com/DylanCaiCoding/MMKV-KTX/releases)
--------------------------------------------------------------------------------
/docs/usage/permissions.md:
--------------------------------------------------------------------------------
1 | # 权限用法
2 |
3 | 基于 [Activity Result API](https://developer.android.com/training/basics/intents/result?hl=zh-cn) 进行封装。
4 |
5 | ## 请求单个权限
6 |
7 | ```kotlin
8 | private val requestPermissionLauncher = registerForRequestPermissionResult(
9 | onGranted = {
10 | // 已同意
11 | },
12 | onDenied = {
13 | // 拒绝且不再询问,可弹框引导用户到设置里授权该权限
14 | // 弹框提示后可调用 launchAppSettings() 方法跳到设置页
15 | },
16 | onShowRequestRationale = {
17 | // 拒绝了一次,可弹框解释为什么要获取该权限
18 | // 弹框提示后可调用 requestPermissionAgain() 方法重新请求
19 | })
20 |
21 | override fun onCreate(savedInstanceState: Bundle?) {
22 | // ...
23 | requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
24 | }
25 | ```
26 |
27 | ## 请求多个权限
28 |
29 | ```kotlin
30 | private val requestMultiplePermissionsLauncher = requestMultiplePermissionsLauncher(
31 | onAllGranted = {
32 | // 已全部同意
33 | },
34 | onDenied = { deniedList ->
35 | // 部分权限已拒绝且不再询问,可弹框引导用户到设置里授权该权限
36 | // 弹框提示后可调用 launchAppSettings() 方法跳到设置页
37 | },
38 | onShowRequestRationale = { deniedList ->
39 | // 部分权限拒绝了一次,可弹框解释为什么要获取该权限
40 | // 弹框提示后可调用 requestDeniedPermissions() 方法请求拒绝的权限
41 | })
42 |
43 | override fun onCreate(savedInstanceState: Bundle?) {
44 | // ...
45 | requestMultiplePermissionsLauncher.launch(
46 | Manifest.permission.ACCESS_FINE_LOCATION,
47 | Manifest.permission.READ_EXTERNAL_STORAGE,
48 | )
49 | }
50 | ```
51 |
--------------------------------------------------------------------------------
/docs/usage/systembars.md:
--------------------------------------------------------------------------------
1 | # SystemBars 用法
2 |
3 | 使用最新的 `WindowInsets` 实现,兼容了 Android 10。
4 |
5 | ## SystemBars
6 |
7 | 应用全屏:
8 |
9 | ```kotlin
10 | isFullScreen = true
11 | ```
12 |
13 | ## StatusBar
14 |
15 | 实现沉浸式状态栏,并且给标题栏的顶边距增加状态栏高度,可以适配刘海水滴屏:
16 |
17 | ```kotlin
18 | immerseStatusBar(lightMode = false)
19 | toolbar.addStatusBarHeightToMarginTop()
20 | // toolbar.addStatusBarHeightToPaddingTop()
21 | ```
22 |
23 | 透明状态栏:
24 |
25 | ```kotlin
26 | transparentStatusBar()
27 | ```
28 |
29 | 其它状态栏属性:
30 |
31 | - `statusBarColor`,设置或获取状态栏颜色
32 | - `isLightStatusBar`,设置或判断状态栏是否为浅色模式
33 | - `isStatusBarVisible`,设置或判断状态栏是否为显示
34 | - `statusBarHeight`,获取状态栏高度
35 |
36 | ## NavigationBar
37 |
38 | 给控件的底边距增加导航栏高度:
39 |
40 | ```kotlin
41 | view.addNavigationBarHeightToMarginBottom()
42 | // view.addNavigationBarHeightToPaddingBottom()
43 | ```
44 |
45 | 其它状态栏属性:
46 |
47 | - `navigationBarColor`,设置或获取导航栏颜色
48 | - `isLightNavigationBar`,设置或判断导航栏是否为浅色模式
49 | - `isNavigationBarVisible`,设置或判断导航栏是否为显示
50 | - `navigationBarHeight`,获取导航栏高度
--------------------------------------------------------------------------------
/docs/usage/uri.md:
--------------------------------------------------------------------------------
1 | # Uri 用法
2 |
3 | ## 查询多媒体文件
4 |
5 | 查询多媒体视频的示例:
6 |
7 | ```kotlin
8 | // Container for information about each video.
9 | data class Video(
10 | val uri: Uri,
11 | val name: String,
12 | val duration: Int,
13 | val size: Int
14 | )
15 |
16 | val videoList = mutableListOf