├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASE.md ├── android.gradle ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── Roboto-Bold.ttf │ └── Roboto-Italic.ttf │ ├── java │ └── com │ │ └── nullgr │ │ └── androidcore │ │ ├── App.kt │ │ ├── MainActivity.kt │ │ ├── adapter │ │ ├── AdapterExampleActivity.kt │ │ ├── AdapterExampleWithPayloadsActivity.kt │ │ ├── BaseAdapterExampleActivity.kt │ │ ├── Event.kt │ │ ├── ExampleDelegatesFactory.kt │ │ ├── delegates │ │ │ ├── ExampleDelegate1.kt │ │ │ ├── ExampleDelegate2.kt │ │ │ ├── ExampleDelegate3.kt │ │ │ └── ExampleDelegateWithPayloads.kt │ │ └── items │ │ │ ├── ExampleItem1.kt │ │ │ ├── ExampleItem2.kt │ │ │ ├── ExampleItem3.kt │ │ │ └── ExampleItemWithPayloads.kt │ │ ├── date │ │ └── DateUtilsExampleActivity.kt │ │ ├── fingerprint │ │ ├── FingerprintExampleActivity.kt │ │ └── dialog │ │ │ └── SimpleFingerprintDialog.kt │ │ ├── fonts │ │ └── FontsAndSpansExampleActivity.kt │ │ ├── intents │ │ └── CommonIntentsExampleActivity.kt │ │ ├── interactor │ │ ├── data │ │ │ └── UserDataRepositoryExample.kt │ │ ├── domain │ │ │ ├── interactor │ │ │ │ ├── GetSuggestedFriendsUseCase.kt │ │ │ │ ├── GetUserFriendsPhotoUseCase.kt │ │ │ │ ├── GetUserPhoneUseCase.kt │ │ │ │ ├── GetUserPhotoUseCase.kt │ │ │ │ ├── GetUserUseCase.kt │ │ │ │ ├── GetUsersUseCase.kt │ │ │ │ └── ResetPasswordUseCase.kt │ │ │ └── repository │ │ │ │ └── UserRepositoryExample.kt │ │ └── presentation │ │ │ ├── InteractorExampleActivity.kt │ │ │ └── adapter │ │ │ ├── InteractorDelegatesFactory.kt │ │ │ ├── delegates │ │ │ └── InteractorDelegate.kt │ │ │ └── items │ │ │ └── InteractorItem.kt │ │ ├── keyboardanimator │ │ ├── KeyboardAnimatorExampleActivity.kt │ │ └── dialog │ │ │ └── SimpleBottomSheetDialog.kt │ │ ├── location │ │ └── RxLocationManagerExampleActivity.kt │ │ ├── resources │ │ └── ResourcesExampleActivity.kt │ │ └── rxcontacts │ │ ├── ContactsDelegateFactory.kt │ │ ├── RxContactsExampleActivity.kt │ │ ├── delegates │ │ ├── ContactDelegate.kt │ │ └── HeaderDelegate.kt │ │ └── items │ │ ├── ContactItem.kt │ │ └── HeaderItem.kt │ └── res │ ├── color │ └── bottom_navigation_selector.xml │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── background_fingerprint.xml │ ├── divider_adapter_item.xml │ ├── drawable_round.xml │ ├── ic_fingerprint.xml │ ├── ic_fingerprint_dark.xml │ ├── ic_fingerprint_error.xml │ ├── ic_fingerprint_success.xml │ ├── ic_first_tab.xml │ ├── ic_launcher_background.xml │ ├── ic_launcher_round.png │ └── ic_second_tab.xml │ ├── layout │ ├── activity_adapter_example.xml │ ├── activity_adapter_example_with_payloads.xml │ ├── activity_common_intents_example.xml │ ├── activity_date_utils_example.xml │ ├── activity_fingerprint_example.xml │ ├── activity_fonts_and_spans_example.xml │ ├── activity_interactor_example.xml │ ├── activity_keyboard_animator_example.xml │ ├── activity_main.xml │ ├── activity_resources_example.xml │ ├── activity_rx_contacts_example_activity.xml │ ├── activity_rx_location_manager_example.xml │ ├── dialog_simple_bottom_sheet.xml │ ├── dialog_simple_fingerprint.xml │ ├── item_contact.xml │ ├── item_example_1.xml │ ├── item_example_2.xml │ ├── item_example_3.xml │ ├── item_example_with_payloads.xml │ ├── item_header.xml │ └── item_interactor.xml │ ├── menu │ └── bottom_navigation.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 ├── build.gradle ├── core-adapter-ktx ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── adapter │ │ └── ktx │ │ ├── AdapterDelegate.kt │ │ ├── BaseViewHolder.kt │ │ ├── ParentAdapterDelegate.kt │ │ └── ViewHolder.kt │ └── res │ └── values │ └── strings.xml ├── core-adapter ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── nullgr │ │ │ └── core │ │ │ └── adapter │ │ │ ├── AdapterDelegate.kt │ │ │ ├── AdapterDelegatesFactory.kt │ │ │ ├── AdapterDelegatesManager.kt │ │ │ ├── BaseViewHolder.kt │ │ │ ├── Callback.kt │ │ │ ├── DiffUtilsExtensions.kt │ │ │ ├── DynamicAdapter.kt │ │ │ ├── HashCodeBasedAdapterDelegatesManager.kt │ │ │ ├── SparseAdapterDelegatesManager.kt │ │ │ ├── ViewHolderExtensions.kt │ │ │ ├── decor │ │ │ └── ConditionBasedDividerItemDecoration.kt │ │ │ ├── exceptions │ │ │ ├── DelegateNotDefinedException.kt │ │ │ └── DelegateNotFoundException.kt │ │ │ └── items │ │ │ ├── ListItem.kt │ │ │ ├── ParentItem.kt │ │ │ └── SingleLineItem.kt │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── adapter │ │ ├── HashCodeBasedManagerTest.kt │ │ ├── TestDelegates.kt │ │ └── TestItems.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── core-all ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── res │ └── values │ └── strings.xml ├── core-collections ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── collections │ │ ├── CollectionsExtensions.kt │ │ └── Predicate.java │ └── res │ └── values │ └── strings.xml ├── core-common ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── common │ │ └── SdkVersion.kt │ └── res │ └── values │ └── strings.xml ├── core-date ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── nullgr │ │ │ └── core │ │ │ └── date │ │ │ ├── DateFormatExtensions.kt │ │ │ └── DateHelperExtensions.kt │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── nullgr │ └── core │ └── date │ ├── DateFormatExtensionsTest.kt │ └── DateHelperExtensionsTest.kt ├── core-font ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── font │ │ ├── FontsExtensions.kt │ │ ├── SpanExtensions.kt │ │ ├── SpanSet.kt │ │ ├── SpannableStringDslExtensions.kt │ │ └── TypeFaceSpan.kt │ └── res │ └── values │ └── strings.xml ├── core-hardware ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── hardware │ │ ├── NetworkChecker.kt │ │ └── SupportedFeaturesExtensions.kt │ └── res │ └── values │ └── strings.xml ├── core-intents ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── intents │ │ ├── CommonIntentsExtensions.kt │ │ └── rxresult │ │ ├── RxActivityResult.kt │ │ ├── RxResolveResultActivity.kt │ │ └── delegates │ │ ├── BaseResolveResultActivityDelegate.kt │ │ ├── IntentActivityDelegate.kt │ │ └── IntentSenderActivityDelegate.kt │ └── res │ └── values │ └── strings.xml ├── core-interactor ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── interactor │ │ ├── CompletableUseCase.kt │ │ ├── FlowableListUseCase.kt │ │ ├── FlowableUseCase.kt │ │ ├── ObservableListUseCase.kt │ │ ├── ObservableUseCase.kt │ │ ├── SingleListUseCase.kt │ │ └── SingleUseCase.kt │ └── res │ └── values │ └── strings.xml ├── core-preferences ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── preferences │ │ └── PreferenceExtensions.kt │ └── res │ └── values │ └── strings.xml ├── core-resources ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── resources │ │ └── ResourceProvider.kt │ └── res │ └── values │ └── strings.xml ├── core-rx-contacts ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── nullgr │ │ └── core │ │ └── rx │ │ └── contacts │ │ ├── RxContactsProviderTestSuite.kt │ │ ├── engine │ │ ├── cursor │ │ │ ├── CursorFactoryTest.kt │ │ │ └── ProjectionFactoryTest.kt │ │ └── query │ │ │ └── SelectionArgsBuilderTest.kt │ │ ├── extensions │ │ └── ExtensionFunctionsTest.kt │ │ └── validator │ │ └── UriToMethodValidatorTest.kt │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── rx │ │ └── contacts │ │ ├── RxContactsProvider.kt │ │ ├── domain │ │ ├── BaseContact.kt │ │ ├── ContactEmail.kt │ │ ├── ContactPhone.kt │ │ └── UserContact.kt │ │ ├── engine │ │ ├── ContactsLoadEngine.kt │ │ ├── cursor │ │ │ ├── CursorFactory.kt │ │ │ └── ProjectionFactory.kt │ │ └── query │ │ │ ├── ContactsQueryBuilder.kt │ │ │ ├── PropertyToColumnNameMapper.kt │ │ │ ├── QueryProperties.kt │ │ │ └── SelectionArgsBuilder.kt │ │ ├── extensions │ │ └── ExtensionFunctions.kt │ │ ├── mapper │ │ ├── CursorMapper.kt │ │ ├── CursorToContactIdsMapper.kt │ │ ├── CursorToContactsMapper.kt │ │ ├── CursorToEmailMapper.kt │ │ └── CursorToPhoneMapper.kt │ │ └── validator │ │ └── UriToMethodValidator.kt │ └── res │ └── values │ └── strings.xml ├── core-rx-location ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── rx │ │ └── location │ │ ├── LocationExtensions.kt │ │ └── RxLocationManager.kt │ └── res │ └── values │ └── strings.xml ├── core-rx ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── rx │ │ ├── RxBus.kt │ │ ├── RxExtensions.kt │ │ ├── relay │ │ └── SingleSubscriberRelay.kt │ │ └── schedulers │ │ ├── ComputationSchedulersFacade.kt │ │ ├── ComputationToMainSchedulersFacade.kt │ │ ├── IoToMainSchedulersFacade.kt │ │ └── SchedulersFacade.kt │ └── res │ └── values │ └── strings.xml ├── core-security ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── nullgr │ │ └── core │ │ ├── CoreSecurityTestSuite.kt │ │ ├── prefs │ │ ├── CryptoPreferencesTest.kt │ │ └── PreferencesCryptonTest.kt │ │ └── security │ │ └── crypto │ │ ├── CryptoKeysFactoryTest.kt │ │ ├── CryptonTest.kt │ │ └── SecureUtilsExtensionsTest.kt │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── security │ │ ├── crypto │ │ ├── CryptoKeysFactory.kt │ │ ├── Crypton.kt │ │ ├── SecureConverterExtensions.kt │ │ └── internal │ │ │ ├── AesCbcCryptonImpl.kt │ │ │ ├── PbeCryptonImpl.kt │ │ │ └── RsaCryptonImpl.kt │ │ ├── fingerprint │ │ ├── FingerprintAuthenticationManager.kt │ │ ├── FingerprintResultListener.kt │ │ ├── FingerprintStatus.kt │ │ ├── FingerprintView.kt │ │ ├── crypto │ │ │ └── FingerprintCrypton.kt │ │ ├── errors │ │ │ └── FingerprintNotAvailableException.kt │ │ ├── rx │ │ │ ├── OptionalResult.kt │ │ │ ├── RxFingerprintAuthenticationManger.kt │ │ │ └── view │ │ │ │ ├── FingerprintViewState.kt │ │ │ │ └── RxFingerprintView.kt │ │ └── utils │ │ │ └── FingerprintHardwareExtensions.kt │ │ └── prefs │ │ ├── CryptoPreferences.kt │ │ └── crypto │ │ ├── KeyWrapper.kt │ │ └── PreferencesCrypton.kt │ └── res │ └── values │ └── strings.xml ├── core-ui ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── nullgr │ │ └── core │ │ └── ui │ │ ├── animation │ │ ├── AnimatorExtensions.kt │ │ ├── ViewAnimationsExtensions.kt │ │ └── ViewPropertyAnimatorExtension.kt │ │ ├── decor │ │ └── DividerItemDecoration.kt │ │ ├── extensions │ │ ├── EditTextExtensions.kt │ │ ├── KeyboardExtensions.kt │ │ ├── ScreenExtensions.kt │ │ ├── ViewExtensions.kt │ │ ├── ViewGroupExtension.kt │ │ └── WindowExtensions.kt │ │ ├── fragments │ │ └── FragmentManagerExtensions.kt │ │ ├── inputfilters │ │ ├── AllowedCharactersInputFilter.kt │ │ ├── InputFiltersFabricExtension.kt │ │ ├── OnlyDigitsInputFilter.kt │ │ └── OnlyLettersOrDigitsInputFilter.kt │ │ ├── keyboardanimator │ │ ├── BaseKeyboardAnimator.kt │ │ ├── customizable │ │ │ ├── Animator.kt │ │ │ ├── CustomizableKeyboardAnimator.kt │ │ │ ├── PaddingAnimator.kt │ │ │ └── WindowInsetsListener.kt │ │ └── simple │ │ │ └── SimpleKeyboardAnimator.kt │ │ ├── toast │ │ └── QuickToastExtensions.kt │ │ ├── utils │ │ └── SimpleTextWatcher.kt │ │ └── widgets │ │ ├── Button.kt │ │ ├── EditText.kt │ │ ├── Switch.kt │ │ ├── TextView.kt │ │ ├── WidthAdjustedFrameLayout.kt │ │ └── extensions │ │ └── TextViewFontsExtensions.kt │ └── res │ └── values │ ├── attrs.xml │ └── strings.xml ├── dependencies.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jcenter ├── bintray.gradle └── maven-install.gradle ├── release-bintray.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | local.properties 4 | .idea 5 | .DS_Store 6 | build 7 | captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | How to Contribute 2 | ----------------- 3 | We welcome your contributions to this project. There are various ways to contribute: 4 | 5 | * **Reporting issues** 6 | 7 | Help improve the project by reporting issues that you find by filing a new issue at the 8 | [App Core issue tracker](https://github.com/nullgr/app-core/issues/new). 9 | 10 | * **Features and ideas suggestions** 11 | 12 | You can also add feature suggestions by filing a new issue at the 13 | [App Core issue tracker](https://github.com/nullgr/app-core/issues/new). 14 | 15 | * **Improving README and examples** 16 | 17 | Also, we would be happy with your help in improving the documentation, tests and examples of use. 18 | 19 | **Pull requests** 20 | ----------------- 21 | 22 | Pull requests are welcome for minor bug fixes that do not involve any changes to existing API. 23 | Also you can create pull request for new features, new modules and additions to existing classes. 24 | 25 | **For success pull request you need to:** 26 | * Provide documentation for all new functions. 27 | * Provide a test case for new functions. 28 | * Provide an example for new functions 29 | * Request review from: 30 | [vchernyshov](https://github.com/vchernyshov) and [grishko188](https://github.com/grishko188) 31 | 32 | **Pull request must meet the requirements below:** 33 | * Fork the repo and create your branch from ```develop.``` 34 | * For new features call branch feature/short-feature-description 35 | * For bug fixes call branch bugfix/short-fix-description 36 | * Report an issue for each PR before submit it. Commits in your PR must starts from **[#issue_number]** 37 | * Also don’t forget to support your features with tests and/or examples how to use, to confirm the functionality. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Nullgravity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | Releasing 2 | ======== 3 | 4 | 1. Bump the `libraryVersion` property in `release-bintray.gradle` based on Major.Minor.Patch naming scheme 5 | 2. Check `bintrayRepo` at `release-bintray.gradle` property set to `maven` 6 | 3. Check `bintray.user` and `bintray.apikey` at `local.properties`. 7 | 4. Update `CHANGELOG.md` for the impending release. 8 | 5. Update `README.md` with the new version. 9 | 6. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the version you set in step 1) 10 | 7. `git tag -a X.Y.X -m "Version X.Y.Z"` (where X.Y.Z is the new version) 11 | 8. `./gradlew clean build bintrayUpload` 12 | 9. `git push && git push --tags` -------------------------------------------------------------------------------- /android.gradle: -------------------------------------------------------------------------------- 1 | android { 2 | def globalConfiguration = rootProject.extensions.getByName("ext") 3 | 4 | compileSdkVersion globalConfiguration["androidCompileSdkVersion"] 5 | buildToolsVersion globalConfiguration["androidBuildToolsVersion"] 6 | 7 | defaultConfig { 8 | minSdkVersion globalConfiguration["androidMinSdkVersion"] 9 | targetSdkVersion globalConfiguration["androidTargetSdkVersion"] 10 | 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | multiDexEnabled true 16 | } 17 | 18 | compileOptions { 19 | sourceCompatibility JavaVersion.VERSION_1_8 20 | targetCompatibility JavaVersion.VERSION_1_8 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | 30 | lintOptions { 31 | abortOnError false 32 | } 33 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/assets/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nullgr/app-core/6cb588384090aa76d94f052f32de6c26cbd042e3/app/src/main/assets/Roboto-Bold.ttf -------------------------------------------------------------------------------- /app/src/main/assets/Roboto-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nullgr/app-core/6cb588384090aa76d94f052f32de6c26cbd042e3/app/src/main/assets/Roboto-Italic.ttf -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/App.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore 2 | 3 | import android.app.Application 4 | import com.jakewharton.threetenabp.AndroidThreeTen 5 | 6 | class App : Application() { 7 | 8 | override fun onCreate() { 9 | super.onCreate() 10 | AndroidThreeTen.init(this) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/BaseAdapterExampleActivity.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter 2 | 3 | import android.os.Bundle 4 | import androidx.annotation.CallSuper 5 | import androidx.appcompat.app.AppCompatActivity 6 | import com.jakewharton.rxrelay2.BehaviorRelay 7 | import com.nullgr.core.adapter.AdapterDelegatesFactory 8 | import com.nullgr.core.adapter.DynamicAdapter 9 | import com.nullgr.core.adapter.bindTo 10 | import com.nullgr.core.adapter.items.ListItem 11 | import com.nullgr.core.rx.RxBus 12 | import com.nullgr.core.rx.schedulers.ComputationToMainSchedulersFacade 13 | import com.nullgr.core.rx.schedulers.SchedulersFacade 14 | import io.reactivex.disposables.CompositeDisposable 15 | 16 | /** 17 | * @author chernyshov. 18 | */ 19 | abstract class BaseAdapterExampleActivity : AppCompatActivity() { 20 | 21 | protected lateinit var bus: RxBus 22 | protected lateinit var delegatesFactory: AdapterDelegatesFactory 23 | protected lateinit var schedulersFacade: SchedulersFacade 24 | protected lateinit var adapter: DynamicAdapter 25 | protected val compositeUnBind = CompositeDisposable() 26 | protected val itemsRelay = BehaviorRelay.create>() 27 | 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | init() 31 | } 32 | 33 | override fun onStart() { 34 | super.onStart() 35 | itemsRelay.bindTo(adapter, compositeUnBind) 36 | } 37 | 38 | override fun onStop() { 39 | compositeUnBind.clear() 40 | super.onStop() 41 | 42 | } 43 | 44 | abstract fun provideDelegatesFactory(): AdapterDelegatesFactory 45 | 46 | @CallSuper 47 | protected open fun init() { 48 | bus = RxBus() 49 | schedulersFacade = ComputationToMainSchedulersFacade() 50 | delegatesFactory = provideDelegatesFactory() 51 | adapter = DynamicAdapter(delegatesFactory) 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/Event.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter 2 | 3 | import com.nullgr.core.adapter.items.ListItem 4 | 5 | /** 6 | * @author chernyshov. 7 | */ 8 | sealed class Event { 9 | class Click(val item: Any) : Event() 10 | class Payload(val payload: Any): Event() 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/ExampleDelegatesFactory.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter 2 | 3 | import com.nullgr.androidcore.adapter.delegates.ExampleDelegate1 4 | import com.nullgr.androidcore.adapter.delegates.ExampleDelegate2 5 | import com.nullgr.androidcore.adapter.delegates.ExampleDelegate3 6 | import com.nullgr.androidcore.adapter.delegates.ExampleDelegateWithPayloads 7 | import com.nullgr.androidcore.adapter.items.ExampleItem1 8 | import com.nullgr.androidcore.adapter.items.ExampleItem2 9 | import com.nullgr.androidcore.adapter.items.ExampleItem3 10 | import com.nullgr.androidcore.adapter.items.ExampleItemWithPayloads 11 | import com.nullgr.core.adapter.AdapterDelegate 12 | import com.nullgr.core.adapter.AdapterDelegatesFactory 13 | import com.nullgr.core.adapter.exceptions.DelegateNotDefinedException 14 | import com.nullgr.core.adapter.items.ListItem 15 | import com.nullgr.core.rx.RxBus 16 | 17 | class ExampleDelegatesFactory(val bus: RxBus) : AdapterDelegatesFactory { 18 | 19 | override fun createDelegate(clazz: Class): AdapterDelegate = 20 | when (clazz) { 21 | ExampleItem1::class.java -> ExampleDelegate1() 22 | ExampleItem2::class.java -> ExampleDelegate2() 23 | ExampleItem3::class.java -> ExampleDelegate3() 24 | ExampleItemWithPayloads::class.java -> ExampleDelegateWithPayloads(bus) 25 | else -> throw DelegateNotDefinedException(clazz) 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/delegates/ExampleDelegate1.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.delegates 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import com.nullgr.androidcore.R 5 | import com.nullgr.androidcore.adapter.items.ExampleItem1 6 | import com.nullgr.core.adapter.AdapterDelegate 7 | import com.nullgr.core.adapter.items.ListItem 8 | import com.squareup.picasso.Picasso 9 | import kotlinx.android.synthetic.main.item_example_1.view.* 10 | 11 | class ExampleDelegate1 : AdapterDelegate() { 12 | 13 | override val layoutResource: Int = R.layout.item_example_1 14 | override val itemType: Any = ExampleItem1::class 15 | 16 | override fun onBindViewHolder(items: List, position: Int, holder: RecyclerView.ViewHolder) { 17 | val item = items[position] as ExampleItem1 18 | 19 | with(holder.itemView) { 20 | Picasso.get().load(item.icon).into(iconView) 21 | textView.text = item.text 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/delegates/ExampleDelegate2.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.delegates 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import com.nullgr.androidcore.R 5 | import com.nullgr.androidcore.adapter.items.ExampleItem2 6 | import com.nullgr.core.adapter.AdapterDelegate 7 | import com.nullgr.core.adapter.items.ListItem 8 | import com.squareup.picasso.Picasso 9 | import kotlinx.android.synthetic.main.item_example_2.view.* 10 | 11 | class ExampleDelegate2 : AdapterDelegate() { 12 | 13 | override val layoutResource: Int = R.layout.item_example_2 14 | override val itemType: Any = ExampleItem2::class 15 | 16 | override fun onBindViewHolder(items: List, position: Int, holder: RecyclerView.ViewHolder) { 17 | val item = items[position] as ExampleItem2 18 | 19 | with(holder.itemView) { 20 | Picasso.get().load(item.icon).into(iconView) 21 | text1View.text = item.text1 22 | text2View.text = item.text2 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/delegates/ExampleDelegate3.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.delegates 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import com.nullgr.androidcore.R 5 | import com.nullgr.androidcore.adapter.items.ExampleItem3 6 | import com.nullgr.core.adapter.AdapterDelegate 7 | import com.nullgr.core.adapter.items.ListItem 8 | import com.squareup.picasso.Picasso 9 | import kotlinx.android.synthetic.main.item_example_3.view.* 10 | 11 | class ExampleDelegate3 : AdapterDelegate() { 12 | 13 | override val layoutResource: Int = R.layout.item_example_3 14 | override val itemType: Any = ExampleItem3::class 15 | 16 | override fun onBindViewHolder(items: List, position: Int, holder: RecyclerView.ViewHolder) { 17 | val item = items[position] as ExampleItem3 18 | 19 | with(holder.itemView) { 20 | Picasso.get().load(item.icon1).into(icon1View) 21 | textView.text = item.text 22 | Picasso.get().load(item.icon2).into(icon2View) 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/items/ExampleItem1.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.items 2 | 3 | import com.nullgr.core.adapter.items.ListItem 4 | 5 | /** 6 | * @author vchernyshov. 7 | */ 8 | data class ExampleItem1(val icon: String, val text: String): ListItem { 9 | override fun getUniqueProperty(): Any = text 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/items/ExampleItem2.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.items 2 | 3 | import com.nullgr.core.adapter.items.ListItem 4 | 5 | /** 6 | * @author vchernyshov. 7 | */ 8 | data class ExampleItem2(val icon: String, val text1: String, val text2: String) : ListItem { 9 | override fun getUniqueProperty(): Any = text1 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/items/ExampleItem3.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.items 2 | 3 | import com.nullgr.core.adapter.items.ListItem 4 | 5 | /** 6 | * @author vchernyshov. 7 | */ 8 | data class ExampleItem3(val icon1: String, val text: String, val icon2: String) : ListItem { 9 | override fun getUniqueProperty(): Any = text 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/adapter/items/ExampleItemWithPayloads.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.adapter.items 2 | 3 | import androidx.annotation.ColorInt 4 | import com.nullgr.core.adapter.items.ListItem 5 | 6 | /** 7 | * @author chernyshov. 8 | */ 9 | data class ExampleItemWithPayloads(val title: String, val subTitle: String, @ColorInt val color: Int) : ListItem { 10 | 11 | override fun getChangePayload(other: ListItem): Any { 12 | if (this::class == other::class) { 13 | other as ExampleItemWithPayloads 14 | return mutableSetOf().apply { 15 | if (title != other.title) add(Payload.TITLE_CHANGED) 16 | if (subTitle != other.subTitle) add(Payload.SUB_TITLE_CHANGED) 17 | if (color != other.color) add(Payload.COLOR_CHANGED) 18 | } 19 | } 20 | return super.getChangePayload(other) 21 | } 22 | 23 | enum class Payload { 24 | TITLE_CHANGED, SUB_TITLE_CHANGED, COLOR_CHANGED 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/GetSuggestedFriendsUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.SingleListUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Single 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class GetSuggestedFriendsUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : SingleListUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: String?): Single> { 17 | if (params == null) { 18 | throw IllegalArgumentException("Params is required for ${this.javaClass.name}") 19 | } 20 | return userRepository.getSuggestedFriends(params) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/GetUserFriendsPhotoUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.ObservableListUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Observable 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class GetUserFriendsPhotoUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : ObservableListUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: String?): Observable> { 17 | if (params == null) { 18 | throw IllegalArgumentException("Params is required for ${this.javaClass.name}") 19 | } 20 | return userRepository.getUserFriends(params) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/GetUserPhoneUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.SingleUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Single 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class GetUserPhoneUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : SingleUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: String?): Single { 17 | if (params == null) { 18 | throw IllegalArgumentException("Params is required for ${this.javaClass.name}") 19 | } 20 | return userRepository.getUserPhone(params) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/GetUserPhotoUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.ObservableUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Observable 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class GetUserPhotoUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : ObservableUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: String?): Observable { 17 | if (params == null) { 18 | throw IllegalArgumentException("Params is required for ${this.javaClass.name}") 19 | } 20 | return userRepository.getUserPhoto(params) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/GetUserUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.FlowableUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Flowable 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class GetUserUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : FlowableUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: String?): Flowable { 17 | if (params == null) { 18 | throw IllegalArgumentException("Params is required for ${this.javaClass.name}") 19 | } 20 | return userRepository.getUser(params) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/GetUsersUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.FlowableListUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Flowable 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class GetUsersUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : FlowableListUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: Unit?): Flowable> { 17 | return userRepository.getUsers() 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/interactor/ResetPasswordUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.interactor 2 | 3 | import com.nullgr.androidcore.interactor.domain.repository.UserRepositoryExample 4 | import com.nullgr.core.interactor.CompletableUseCase 5 | import com.nullgr.core.rx.schedulers.SchedulersFacade 6 | import io.reactivex.Completable 7 | 8 | /** 9 | * @author chernyshov. 10 | */ 11 | class ResetPasswordUseCase( 12 | private val userRepository: UserRepositoryExample, 13 | schedulersFacade: SchedulersFacade) 14 | : CompletableUseCase(schedulersFacade) { 15 | 16 | override fun buildUseCaseObservable(params: String?): Completable { 17 | if (params == null) { 18 | throw IllegalArgumentException("Params is required for ${this.javaClass.name}") 19 | } 20 | return userRepository.requestPasswordReset(params) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/domain/repository/UserRepositoryExample.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.domain.repository 2 | 3 | import io.reactivex.Completable 4 | import io.reactivex.Flowable 5 | import io.reactivex.Observable 6 | import io.reactivex.Single 7 | 8 | /** 9 | * @author vchernyshov 10 | */ 11 | interface UserRepositoryExample { 12 | 13 | fun requestPasswordReset(userId: String): Completable 14 | 15 | fun getUsers(): Flowable> 16 | 17 | fun getUser(id: String): Flowable 18 | 19 | fun getUserFriends(userId: String): Observable> 20 | 21 | fun getUserPhoto(userId: String): Observable 22 | 23 | fun getSuggestedFriends(userId: String): Single> 24 | 25 | fun getUserPhone(userId: String): Single 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/presentation/adapter/InteractorDelegatesFactory.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.presentation.adapter 2 | 3 | import com.nullgr.androidcore.interactor.presentation.adapter.delegates.InteractorDelegate 4 | import com.nullgr.androidcore.interactor.presentation.adapter.items.InteractorItem 5 | import com.nullgr.core.adapter.AdapterDelegate 6 | import com.nullgr.core.adapter.AdapterDelegatesFactory 7 | import com.nullgr.core.adapter.exceptions.DelegateNotDefinedException 8 | import com.nullgr.core.adapter.items.ListItem 9 | import com.nullgr.core.rx.RxBus 10 | 11 | class InteractorDelegatesFactory(private val bus: RxBus) : AdapterDelegatesFactory { 12 | 13 | override fun createDelegate(clazz: Class): AdapterDelegate = 14 | when (clazz) { 15 | InteractorItem::class.java -> InteractorDelegate(bus) 16 | else -> throw DelegateNotDefinedException(clazz) 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/presentation/adapter/delegates/InteractorDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.presentation.adapter.delegates 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import com.nullgr.androidcore.R 5 | import com.nullgr.androidcore.interactor.presentation.adapter.items.InteractorItem 6 | import com.nullgr.core.adapter.AdapterDelegate 7 | import com.nullgr.core.adapter.items.ListItem 8 | import com.nullgr.core.rx.RxBus 9 | import kotlinx.android.synthetic.main.item_interactor.view.* 10 | 11 | class InteractorDelegate(private val bus: RxBus) : AdapterDelegate() { 12 | 13 | override val layoutResource: Int = R.layout.item_interactor 14 | override val itemType: Any = InteractorItem::class 15 | 16 | override fun onBindViewHolder(items: List, position: Int, holder: RecyclerView.ViewHolder) { 17 | val item = items[position] as InteractorItem 18 | 19 | with(holder.itemView) { 20 | interactorTitleView.text = item.title 21 | executeButtonView.setOnClickListener { 22 | bus.post(event = item) 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/interactor/presentation/adapter/items/InteractorItem.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.interactor.presentation.adapter.items 2 | 3 | import com.nullgr.core.adapter.items.ListItem 4 | 5 | /** 6 | * @author chernyshov. 7 | */ 8 | data class InteractorItem(val type: Type, val title: String) : ListItem { 9 | 10 | enum class Type { 11 | OBSERVABLE, OBSERVABLE_LIST, 12 | FLOWABLE, FLOWABLE_LIST, 13 | SINGLE, SINGLE_LIST, 14 | COMPLETABLE 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/keyboardanimator/KeyboardAnimatorExampleActivity.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.keyboardanimator 2 | 3 | import android.annotation.TargetApi 4 | import android.os.Build 5 | import android.os.Bundle 6 | import androidx.annotation.RequiresApi 7 | import androidx.appcompat.app.AppCompatActivity 8 | import android.view.WindowManager 9 | import com.nullgr.androidcore.R 10 | import com.nullgr.androidcore.keyboardanimator.dialog.SimpleBottomSheetDialog 11 | import com.nullgr.core.ui.keyboardanimator.BaseKeyboardAnimator 12 | import com.nullgr.core.ui.keyboardanimator.simple.SimpleKeyboardAnimator 13 | import kotlinx.android.synthetic.main.activity_keyboard_animator_example.* 14 | 15 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP) 16 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 17 | class KeyboardAnimatorExampleActivity : AppCompatActivity() { 18 | 19 | private val animator: BaseKeyboardAnimator by lazy(LazyThreadSafetyMode.NONE) { SimpleKeyboardAnimator(window) } 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) 24 | setContentView(R.layout.activity_keyboard_animator_example) 25 | showBottomSheetView.setOnClickListener { 26 | SimpleBottomSheetDialog(this, checkBoxView.isChecked).show() 27 | } 28 | checkBoxView.setOnCheckedChangeListener { _, isChecked -> 29 | if (isChecked) animator.start() else animator.stop() 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/keyboardanimator/dialog/SimpleBottomSheetDialog.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.keyboardanimator.dialog 2 | 3 | import android.annotation.TargetApi 4 | import android.content.Context 5 | import android.os.Build 6 | import androidx.annotation.RequiresApi 7 | import com.google.android.material.bottomsheet.BottomSheetBehavior 8 | import com.google.android.material.bottomsheet.BottomSheetDialog 9 | import android.view.View 10 | import android.view.WindowManager 11 | import com.nullgr.androidcore.R 12 | import com.nullgr.core.ui.keyboardanimator.simple.SimpleKeyboardAnimator 13 | 14 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP) 15 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 16 | class SimpleBottomSheetDialog(context: Context, private val enableAnimation: Boolean) : BottomSheetDialog(context) { 17 | 18 | init { 19 | setContentView(R.layout.dialog_simple_bottom_sheet) 20 | } 21 | 22 | override fun onStart() { 23 | super.onStart() 24 | val bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet) 25 | BottomSheetBehavior.from(bottomSheet).apply { 26 | state = BottomSheetBehavior.STATE_EXPANDED 27 | skipCollapsed = true 28 | } 29 | window?.let { window -> 30 | if (enableAnimation) { 31 | SimpleKeyboardAnimator(window).start() 32 | } else { 33 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/rxcontacts/ContactsDelegateFactory.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.rxcontacts 2 | 3 | import com.nullgr.androidcore.rxcontacts.delegates.ContactDelegate 4 | import com.nullgr.androidcore.rxcontacts.delegates.HeaderDelegate 5 | import com.nullgr.androidcore.rxcontacts.items.ContactItem 6 | import com.nullgr.androidcore.rxcontacts.items.HeaderItem 7 | import com.nullgr.core.adapter.AdapterDelegate 8 | import com.nullgr.core.adapter.AdapterDelegatesFactory 9 | import com.nullgr.core.adapter.exceptions.DelegateNotDefinedException 10 | import com.nullgr.core.adapter.items.ListItem 11 | 12 | /** 13 | * Created by Grishko Nikita on 01.02.18. 14 | */ 15 | class ContactsDelegateFactory : AdapterDelegatesFactory { 16 | 17 | override fun createDelegate(clazz: Class): AdapterDelegate = 18 | when (clazz) { 19 | ContactItem::class.java -> ContactDelegate() 20 | HeaderItem::class.java -> HeaderDelegate() 21 | else -> throw DelegateNotDefinedException(clazz) 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/rxcontacts/delegates/HeaderDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.rxcontacts.delegates 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import android.widget.TextView 5 | import com.nullgr.androidcore.R 6 | import com.nullgr.androidcore.rxcontacts.items.HeaderItem 7 | import com.nullgr.core.adapter.AdapterDelegate 8 | import com.nullgr.core.adapter.items.ListItem 9 | 10 | /** 11 | * Created by Grishko Nikita on 01.02.18. 12 | */ 13 | class HeaderDelegate : AdapterDelegate() { 14 | 15 | override val layoutResource: Int = R.layout.item_header 16 | override val itemType: Any = HeaderItem::class 17 | 18 | override fun onBindViewHolder(items: List, position: Int, vh: RecyclerView.ViewHolder) { 19 | val item = items[position] as HeaderItem 20 | (vh.itemView as TextView).text = item.title 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/rxcontacts/items/ContactItem.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.rxcontacts.items 2 | 3 | import android.net.Uri 4 | import com.nullgr.core.adapter.items.ListItem 5 | 6 | /** 7 | * Created by Grishko Nikita on 01.02.18. 8 | */ 9 | data class ContactItem(val id: Long, 10 | val displayName: String?, 11 | val isFavorite: Boolean, 12 | val photo: Uri?, 13 | var phones: List?, 14 | var emails: List?) : ListItem { 15 | 16 | override fun getUniqueProperty() = id 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/nullgr/androidcore/rxcontacts/items/HeaderItem.kt: -------------------------------------------------------------------------------- 1 | package com.nullgr.androidcore.rxcontacts.items 2 | 3 | import com.nullgr.core.adapter.items.ListItem 4 | 5 | /** 6 | * Created by Grishko Nikita on 01.02.18. 7 | */ 8 | data class HeaderItem(val title: String) : ListItem { 9 | override fun getUniqueProperty() = title 10 | } -------------------------------------------------------------------------------- /app/src/main/res/color/bottom_navigation_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /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/res/drawable/background_fingerprint.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/divider_adapter_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/drawable_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fingerprint_error.xml: -------------------------------------------------------------------------------- 1 | 16 | 21 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fingerprint_success.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 25 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_first_tab.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nullgr/app-core/6cb588384090aa76d94f052f32de6c26cbd042e3/app/src/main/res/drawable/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_second_tab.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_adapter_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 |