├── layer-core ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ └── values │ │ │ ├── ids.xml │ │ │ ├── attrs.xml │ │ │ └── styles.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── core │ │ ├── listener │ │ ├── DefaultOnShowListener.java │ │ ├── DefaultOnDismissListener.java │ │ ├── DefaultOnVisibleChangedListener.java │ │ ├── DefaultAnimatorListener.java │ │ └── WindowCallbackDelegate.java │ │ ├── anim │ │ ├── NullAnimatorCreator.java │ │ ├── CircularRevealAnimatorCreator.java │ │ └── AnimStyle.java │ │ ├── Layers.java │ │ ├── widget │ │ ├── LayerContainer.java │ │ └── MaxSizeFrameLayout.java │ │ ├── utils │ │ └── ScrollCompat.java │ │ └── ActivityHolder.java └── build.gradle ├── layer-guide ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── guide │ │ └── HoleView.java └── build.gradle ├── layer-popup ├── .gitignore ├── src │ └── main │ │ └── AndroidManifest.xml └── build.gradle ├── layer-toast ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── res │ │ └── values │ │ └── ids.xml └── build.gradle ├── layer-core-ktx ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── core │ │ └── ktx │ │ ├── FrameLayer.kt │ │ └── Layer.kt └── build.gradle ├── layer-design-res ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── res │ │ ├── values-night │ │ └── colors.xml │ │ └── values │ │ ├── colors.xml │ │ └── dimens.xml └── build.gradle ├── layer-dialog-ktx ├── .gitignore ├── src │ └── main │ │ └── AndroidManifest.xml └── build.gradle ├── layer-dialog ├── .gitignore ├── build.gradle └── src │ └── main │ ├── java │ └── per │ │ └── goweii │ │ └── layer │ │ └── dialog │ │ ├── DefaultDialogOnSwipeListener.java │ │ ├── DialogLayerActivity.java │ │ └── ContainerLayout.java │ └── AndroidManifest.xml ├── layer-guide-ktx ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── guide │ │ └── ktx │ │ └── GuideLayer.kt └── build.gradle ├── layer-keyboard ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── raw │ │ │ └── layer_keyboard_click.mp3 │ │ ├── drawable-hdpi │ │ │ ├── layer_keyboard_ic_del.png │ │ │ ├── layer_keyboard_ic_caps.png │ │ │ ├── layer_keyboard_ic_enter.png │ │ │ ├── layer_keyboard_ic_space.png │ │ │ ├── layer_keyboard_ic_arrow_down.png │ │ │ └── layer_keyboard_ic_caps_lock.png │ │ ├── drawable-mdpi │ │ │ ├── layer_keyboard_ic_del.png │ │ │ ├── layer_keyboard_ic_caps.png │ │ │ ├── layer_keyboard_ic_enter.png │ │ │ ├── layer_keyboard_ic_space.png │ │ │ ├── layer_keyboard_ic_arrow_down.png │ │ │ └── layer_keyboard_ic_caps_lock.png │ │ ├── drawable-xhdpi │ │ │ ├── layer_keyboard_ic_caps.png │ │ │ ├── layer_keyboard_ic_del.png │ │ │ ├── layer_keyboard_ic_enter.png │ │ │ ├── layer_keyboard_ic_space.png │ │ │ ├── layer_keyboard_ic_arrow_down.png │ │ │ └── layer_keyboard_ic_caps_lock.png │ │ ├── drawable-xxhdpi │ │ │ ├── layer_keyboard_ic_caps.png │ │ │ ├── layer_keyboard_ic_del.png │ │ │ ├── layer_keyboard_ic_enter.png │ │ │ ├── layer_keyboard_ic_space.png │ │ │ ├── layer_keyboard_ic_caps_lock.png │ │ │ └── layer_keyboard_ic_arrow_down.png │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ ├── drawable │ │ │ ├── layer_keyboard_ic_caps_selector.xml │ │ │ ├── layer_keyboard_btn_bg_selector.xml │ │ │ ├── layer_keyboard_btn_bg_normal.xml │ │ │ └── layer_keyboard_btn_bg_pressed.xml │ │ ├── drawable-anydpi │ │ │ ├── layer_keyboard_ic_space.xml │ │ │ ├── layer_keyboard_ic_caps.xml │ │ │ ├── layer_keyboard_ic_arrow_down.xml │ │ │ ├── layer_keyboard_ic_enter.xml │ │ │ ├── layer_keyboard_ic_caps_lock.xml │ │ │ └── layer_keyboard_ic_del.xml │ │ ├── values-night │ │ │ └── colors.xml │ │ └── layout │ │ │ └── layer_keyboard.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── keyboard │ │ ├── BindingActionListener.java │ │ ├── KeyboardVibratorEffect.java │ │ ├── KeyboardSoundEffect.java │ │ ├── DefaultBindingActionListener.java │ │ ├── KeyAction.java │ │ └── KeyboardGesture.java └── build.gradle ├── layer-overlay ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── res │ │ └── values │ │ └── ids.xml └── build.gradle ├── layer-popup-ktx ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── popup │ │ └── ktx │ │ └── PopupLayer.kt └── build.gradle ├── layer-startup ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── per │ └── goweii │ └── layer │ └── startup │ └── LayerInitializer.java ├── layer-toast-ktx ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── toast │ │ └── ktx │ │ └── ToastLayer.kt └── build.gradle ├── layer-design-material ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ ├── values │ │ │ ├── colors.xml │ │ │ └── dimens.xml │ │ ├── values-night │ │ │ └── colors.xml │ │ ├── drawable │ │ │ ├── layer_design_material_dialog_actions_gap.xml │ │ │ ├── layer_design_material_dialog_btn_bg_normal.xml │ │ │ ├── layer_design_material_dialog_btn_bg_pressed.xml │ │ │ ├── layer_design_material_dialog_btn_bg.xml │ │ │ └── layer_design_material_toast_bg.xml │ │ ├── drawable-v21 │ │ │ └── layer_design_material_dialog_btn_bg.xml │ │ └── layout │ │ │ ├── layer_design_material_dialog_action.xml │ │ │ ├── layer_design_material_toast.xml │ │ │ └── layer_design_material_dialog.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── design │ │ └── material │ │ └── MaterialPopupLayer.java └── build.gradle ├── layer-keyboard-ktx ├── .gitignore ├── src │ └── main │ │ └── AndroidManifest.xml └── build.gradle ├── layer-notification ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── notification │ │ └── DefaultNotificationOnSwipeListener.java └── build.gradle ├── layer-overlay-ktx ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── overlay │ │ └── ktx │ │ └── OverlayLayer.kt └── build.gradle ├── layer-design-cupertino ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── res │ │ ├── values │ │ ├── ids.xml │ │ ├── colors.xml │ │ └── dimens.xml │ │ ├── drawable │ │ ├── layer_design_cupertino_divider_h.xml │ │ ├── layer_design_cupertino_divider_v.xml │ │ ├── layer_design_cupertino_alert_bg.xml │ │ └── layer_design_cupertino_toast_bg.xml │ │ ├── values-night │ │ └── colors.xml │ │ └── layout │ │ ├── layer_design_cupertino_alert_action.xml │ │ ├── layer_design_cupertino_toast.xml │ │ ├── layer_design_cupertino_alert.xml │ │ └── layer_design_cupertino_notification.xml └── build.gradle ├── layer-notification-ktx ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── notification │ │ └── ktx │ │ └── NotificationLayer.kt └── build.gradle ├── layer-visualeffectview ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ └── values │ │ │ └── attrs.xml │ │ └── java │ │ └── per │ │ └── goweii │ │ └── layer │ │ └── visualeffectview │ │ ├── BackdropIgnoreView.java │ │ └── BackdropBlurView.java └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── simple ├── release │ ├── per.goweii.layer.simple.apk │ └── output-metadata.json ├── src │ └── main │ │ ├── ic_launcher-playstore.png │ │ ├── res │ │ ├── drawable-xxhdpi │ │ │ ├── ic_back.png │ │ │ ├── ic_fail.png │ │ │ ├── ic_more.png │ │ │ ├── ic_success.png │ │ │ ├── ic_warning.png │ │ │ ├── ic_fail_big.png │ │ │ ├── ic_notification.png │ │ │ ├── ic_success_big.png │ │ │ └── ic_warning_big.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ ├── drawable-night-xxhdpi │ │ │ ├── ic_back.png │ │ │ ├── ic_fail.png │ │ │ ├── ic_more.png │ │ │ ├── ic_success.png │ │ │ └── ic_warning.png │ │ ├── drawable │ │ │ ├── shape_divider_h.xml │ │ │ ├── popup_bg.xml │ │ │ ├── shape_send_bg.xml │ │ │ ├── shape_input_bg.xml │ │ │ └── shape_dialog_fullscreen_bg.xml │ │ ├── layout │ │ │ ├── guide_i_know.xml │ │ │ ├── overlay.xml │ │ │ ├── activity_main.xml │ │ │ ├── guide_content.xml │ │ │ ├── dialog_fullscreen.xml │ │ │ ├── activity_material_simple.xml │ │ │ ├── toast.xml │ │ │ ├── dialog_input.xml │ │ │ ├── activity_cupertino_simple.xml │ │ │ ├── layout_list_20.xml │ │ │ ├── activity_layers_simple.xml │ │ │ ├── popup_meun.xml │ │ │ ├── dialog_normal.xml │ │ │ └── bottom_sheet.xml │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── values-night │ │ │ └── colors.xml │ │ ├── java │ │ └── per │ │ │ └── goweii │ │ │ └── layer │ │ │ └── simple │ │ │ ├── App.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MaterialSimpleActivity.kt │ │ │ └── CupertinoSimpleActivity.kt │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── maven-upload.gradle ├── settings.gradle ├── library.gradle ├── gradle.properties ├── .github └── FUNDING.yml ├── .gitignore ├── gradlew.bat └── README.md /layer-core/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-guide/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-popup/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-toast/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-core-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-design-res/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-dialog-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-dialog/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-guide-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-keyboard/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-overlay/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-popup-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-startup/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-toast-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-design-material/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-keyboard-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-notification/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-overlay-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-design-cupertino/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-notification-ktx/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /layer-visualeffectview/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /simple/release/per.goweii.layer.simple.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/release/per.goweii.layer.simple.apk -------------------------------------------------------------------------------- /simple/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /layer-core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_back.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_fail.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_more.png -------------------------------------------------------------------------------- /layer-guide/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-popup/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-toast/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_success.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_warning.png -------------------------------------------------------------------------------- /simple/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /layer-core-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-core/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-overlay/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_fail_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_fail_big.png -------------------------------------------------------------------------------- /layer-core/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | } 9 | -------------------------------------------------------------------------------- /layer-design-res/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-dialog-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-guide-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-popup-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-toast-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable-night-xxhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-night-xxhdpi/ic_back.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-night-xxhdpi/ic_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-night-xxhdpi/ic_fail.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-night-xxhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-night-xxhdpi/ic_more.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_notification.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_success_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_success_big.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-xxhdpi/ic_warning_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-xxhdpi/ic_warning_big.png -------------------------------------------------------------------------------- /simple/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /layer-design-res/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | } 9 | -------------------------------------------------------------------------------- /layer-keyboard-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/raw/layer_keyboard_click.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/raw/layer_keyboard_click.mp3 -------------------------------------------------------------------------------- /layer-notification/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-overlay-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-toast/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable-night-xxhdpi/ic_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-night-xxhdpi/ic_success.png -------------------------------------------------------------------------------- /simple/src/main/res/drawable-night-xxhdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/drawable-night-xxhdpi/ic_warning.png -------------------------------------------------------------------------------- /layer-design-material/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /simple/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/simple/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-notification-ktx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-overlay/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-visualeffectview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_del.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_del.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_del.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_del.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_caps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_caps.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_enter.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_space.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_caps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_caps.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_enter.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_space.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_caps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_caps.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_del.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_del.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_enter.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_space.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_caps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_caps.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_del.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_del.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_enter.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_space.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_arrow_down.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_caps_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-hdpi/layer_keyboard_ic_caps_lock.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_arrow_down.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_caps_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-mdpi/layer_keyboard_ic_caps_lock.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_arrow_down.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_caps_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xhdpi/layer_keyboard_ic_caps_lock.png -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_caps_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_caps_lock.png -------------------------------------------------------------------------------- /layer-dialog/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core") 9 | } 10 | -------------------------------------------------------------------------------- /layer-guide/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core") 9 | } 10 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goweii/Layer/HEAD/layer-keyboard/src/main/res/drawable-xxhdpi/layer_keyboard_ic_arrow_down.png -------------------------------------------------------------------------------- /layer-overlay/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core") 9 | } 10 | -------------------------------------------------------------------------------- /layer-popup/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-dialog") 9 | } 10 | -------------------------------------------------------------------------------- /layer-toast/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core") 9 | } 10 | -------------------------------------------------------------------------------- /layer-keyboard/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-dialog") 9 | } 10 | -------------------------------------------------------------------------------- /layer-notification/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core") 9 | } 10 | -------------------------------------------------------------------------------- /simple/src/main/java/per/goweii/layer/simple/App.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.simple 2 | 3 | import android.app.Application 4 | 5 | class App : Application() { 6 | override fun onCreate() { 7 | super.onCreate() 8 | } 9 | } -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8dp 4 | 6dp 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable/shape_divider_h.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable/popup_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-startup/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | implementation project(":layer-core") 9 | compileOnly "androidx.startup:startup-runtime:$androidx_startup_version" 10 | } 11 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable/shape_send_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable/shape_input_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-core-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core") 9 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 10 | compileOnly "androidx.core:core-ktx:1.6.0" 11 | } -------------------------------------------------------------------------------- /layer-design-material/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @color/layer_design_res_color_surface 4 | 5 | #14000000 6 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @color/layer_design_res_color_surface 4 | 5 | #14ffffff 6 | -------------------------------------------------------------------------------- /layer-core/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/drawable/layer_design_cupertino_divider_h.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/drawable/layer_design_cupertino_divider_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/drawable/layer_design_material_dialog_actions_gap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable/layer_keyboard_ic_caps_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/drawable/layer_design_material_dialog_btn_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-dialog-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core-ktx") 9 | api project(":layer-dialog") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-guide-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core-ktx") 9 | api project(":layer-guide") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable/layer_keyboard_btn_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-popup-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-dialog-ktx") 9 | api project(":layer-popup") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-toast-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core-ktx") 9 | api project(":layer-toast") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-design-material/src/main/res/drawable/layer_design_material_dialog_btn_bg_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-overlay-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core-ktx") 9 | api project(":layer-overlay") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-keyboard-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-dialog-ktx") 9 | api project(":layer-keyboard") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable/layer_keyboard_btn_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable/layer_keyboard_btn_bg_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /layer-notification-ktx/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "../library.gradle" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-core-ktx") 9 | api project(":layer-notification") 10 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 11 | compileOnly "androidx.core:core-ktx:$androidx_core_ktx_version" 12 | } -------------------------------------------------------------------------------- /layer-core-ktx/src/main/java/per/goweii/layer/core/ktx/FrameLayer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.ktx 2 | 3 | import per.goweii.layer.core.FrameLayer 4 | 5 | fun T.level(level: Int) = this.apply { 6 | this.setLevel(level) 7 | } 8 | 9 | fun T.cancelableOnClickKeyBack(enable: Boolean) = this.apply { 10 | this.setCancelableOnClickKeyBack(enable) 11 | } -------------------------------------------------------------------------------- /layer-design-material/src/main/res/drawable/layer_design_material_dialog_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/drawable-v21/layer_design_material_dialog_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /layer-visualeffectview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api "com.github.goweii.VisualEffect:visualeffect-core:$visual_effect_version" 9 | api "com.github.goweii.VisualEffect:visualeffect-blur:$visual_effect_version" 10 | api "com.github.goweii.VisualEffect:visualeffect-view:$visual_effect_version" 11 | } 12 | -------------------------------------------------------------------------------- /maven-upload.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "maven" 2 | 3 | group layer_group 4 | version layer_version 5 | 6 | uploadArchives { 7 | repositories { 8 | mavenDeployer { 9 | snapshotRepository(url: uri("/Users/cuizhen/StudioProjects/maven-repository/snapshots")) 10 | repository(url: uri("/Users/cuizhen/StudioProjects/maven-repository/releases")) 11 | pom.packaging = "aar" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #B3FFFFFF 4 | #B3FFFFFF 5 | #D9FFFFFF 6 | #14000000 7 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #B31E1E1E 4 | #B31E1E1E 5 | #F2333333 6 | #14000000 7 | -------------------------------------------------------------------------------- /simple/release/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "per.goweii.layer.simple", 8 | "variantName": "processReleaseResources", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "versionCode": 1, 14 | "versionName": "1.0.0", 15 | "outputFile": "per.goweii.layer.simple.apk" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/listener/DefaultOnShowListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.listener; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import per.goweii.layer.core.Layer; 6 | 7 | public class DefaultOnShowListener implements Layer.OnShowListener { 8 | @Override 9 | public void onPreShow(@NonNull Layer layer) { 10 | } 11 | 12 | @Override 13 | public void onPostShow(@NonNull Layer layer) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/listener/DefaultOnDismissListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.listener; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import per.goweii.layer.core.Layer; 6 | 7 | public class DefaultOnDismissListener implements Layer.OnDismissListener { 8 | @Override 9 | public void onPreDismiss(@NonNull Layer layer) { 10 | } 11 | 12 | @Override 13 | public void onPostDismiss(@NonNull Layer layer) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /simple/src/main/res/drawable/shape_dialog_fullscreen_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/listener/DefaultOnVisibleChangedListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.listener; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import per.goweii.layer.core.Layer; 6 | 7 | public class DefaultOnVisibleChangedListener implements Layer.OnVisibleChangedListener { 8 | @Override 9 | public void onShow(@NonNull Layer layer) { 10 | } 11 | 12 | @Override 13 | public void onDismiss(@NonNull Layer layer) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /layer-design-material/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-dialog") 9 | api project(":layer-popup") 10 | api project(":layer-notification") 11 | api project(":layer-guide") 12 | api project(":layer-overlay") 13 | api project(":layer-toast") 14 | api project(":layer-keyboard") 15 | api project(":layer-design-res") 16 | compileOnly "androidx.cardview:cardview:$cardview_version" 17 | } 18 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFFFF 4 | #FFF7F7F7 5 | #FFF5F5F5 6 | #FFF5F5F5 7 | #1A000000 8 | #FF232323 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-anydpi/layer_keyboard_ic_space.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF333333 4 | #FF222222 5 | #FF111111 6 | #FF111111 7 | #CC000000 8 | #E6FFFFFF 9 | #E6000000 10 | -------------------------------------------------------------------------------- /layer-dialog/src/main/java/per/goweii/layer/dialog/DefaultDialogOnSwipeListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.dialog; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | public class DefaultDialogOnSwipeListener implements DialogLayer.OnSwipeListener { 6 | @Override 7 | public void onStart(@NonNull DialogLayer layer) { 8 | } 9 | 10 | @Override 11 | public void onSwiping(@NonNull DialogLayer layer, int direction, float fraction) { 12 | } 13 | 14 | @Override 15 | public void onEnd(@NonNull DialogLayer layer, int direction) { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /layer-design-cupertino/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../library.gradle" 3 | 4 | android { 5 | } 6 | 7 | dependencies { 8 | api project(":layer-dialog") 9 | api project(":layer-popup") 10 | api project(":layer-notification") 11 | api project(":layer-guide") 12 | api project(":layer-overlay") 13 | api project(":layer-toast") 14 | api project(":layer-keyboard") 15 | api project(":layer-design-res") 16 | api project(":layer-visualeffectview") 17 | api "com.github.goweii:ShadowLayout:$shadowlayout_version" 18 | } 19 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/drawable/layer_design_material_toast_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/guide_i_know.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /layer-dialog/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/drawable/layer_design_cupertino_alert_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/drawable/layer_design_cupertino_toast_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /layer-notification/src/main/java/per/goweii/layer/notification/DefaultNotificationOnSwipeListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.notification; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | public class DefaultNotificationOnSwipeListener implements NotificationLayer.OnSwipeListener { 6 | @Override 7 | public void onStart(@NonNull NotificationLayer layer) { 8 | } 9 | 10 | @Override 11 | public void onSwiping(@NonNull NotificationLayer layer, int direction, float fraction) { 12 | } 13 | 14 | @Override 15 | public void onEnd(@NonNull NotificationLayer layer, int direction) { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-anydpi/layer_keyboard_ic_caps.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-anydpi/layer_keyboard_ic_arrow_down.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/layout/layer_design_cupertino_alert_action.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-anydpi/layer_keyboard_ic_enter.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /simple/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #526BFA 4 | #2949FB 5 | #1F36B6 6 | #F62343 7 | #B3000000 8 | #FFFFFF 9 | #FFFFFF 10 | #08000000 11 | #26000000 12 | #33000000 13 | #661F36B6 14 | 15 | -------------------------------------------------------------------------------- /simple/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #657BF8 4 | #3E5BFB 5 | #2E44BC 6 | #F83A57 7 | #B3ffffff 8 | #CC000000 9 | #333333 10 | #08FFFFFF 11 | #33000000 12 | #99000000 13 | #662E44BC 14 | 15 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-anydpi/layer_keyboard_ic_caps_lock.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /simple/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Layer 3 | 关闭 4 | 确定 5 | 取消 6 | 我知道了 7 | 菜单项 8 | 给个Star 9 | 这么好用的框架,动动手指给个Star吧! 10 | 你有一条新短消息 11 | 点击查看详情 12 | 这也太秀了~ 13 | 实现一个引导层就是这么简单! 14 | 发送 15 | 16 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/anim/NullAnimatorCreator.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.anim; 2 | 3 | import android.animation.Animator; 4 | import android.view.View; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | import per.goweii.layer.core.Layer; 10 | 11 | /** 12 | * @author CuiZhen 13 | */ 14 | public class NullAnimatorCreator implements Layer.AnimatorCreator { 15 | @Nullable 16 | @Override 17 | public Animator createInAnimator(@NonNull View target) { 18 | return null; 19 | } 20 | 21 | @Nullable 22 | @Override 23 | public Animator createOutAnimator(@NonNull View target) { 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /layer-design-material/src/main/java/per/goweii/layer/design/material/MaterialPopupLayer.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.design.material; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.View; 6 | 7 | import androidx.annotation.NonNull; 8 | 9 | import per.goweii.layer.popup.PopupLayer; 10 | 11 | public class MaterialPopupLayer extends PopupLayer { 12 | public MaterialPopupLayer(@NonNull Context context) { 13 | super(context); 14 | } 15 | 16 | public MaterialPopupLayer(@NonNull Activity activity) { 17 | super(activity); 18 | } 19 | 20 | public MaterialPopupLayer(@NonNull View targetView) { 21 | super(targetView); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':layer-visualeffectview' 2 | include ":simple" 3 | 4 | include ":layer-core" 5 | include ":layer-core-ktx" 6 | 7 | include ":layer-startup" 8 | 9 | include ":layer-dialog" 10 | include ":layer-dialog-ktx" 11 | include ":layer-popup" 12 | include ":layer-popup-ktx" 13 | include ":layer-notification" 14 | include ":layer-notification-ktx" 15 | include ":layer-guide" 16 | include ":layer-guide-ktx" 17 | include ":layer-overlay" 18 | include ":layer-overlay-ktx" 19 | include ":layer-toast" 20 | include ":layer-toast-ktx" 21 | include ":layer-keyboard" 22 | include ":layer-keyboard-ktx" 23 | 24 | include ":layer-design-res" 25 | include ":layer-design-cupertino" 26 | include ":layer-design-material" 27 | -------------------------------------------------------------------------------- /layer-design-res/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF222222 4 | #99000000 5 | #BFFFFFFF 6 | #80FFFFFF 7 | #59FFFFFF 8 | #33FFFFFF 9 | 10 | #FA444444 11 | #BFFFFFFF 12 | -------------------------------------------------------------------------------- /layer-startup/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /layer-core/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/java/per/goweii/layer/keyboard/BindingActionListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.keyboard; 2 | 3 | import android.widget.TextView; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | public abstract class BindingActionListener implements KeyboardLayer.OnActionListener { 8 | @Override 9 | public boolean onAction(@NonNull KeyboardLayer layer, @NonNull KeyAction action) { 10 | final TextView textView = layer.getViewHolder().getAttachedTextView(); 11 | if (textView == null) return false; 12 | return onBind(layer, textView, action); 13 | } 14 | 15 | protected abstract boolean onBind( 16 | @NonNull KeyboardLayer layer, 17 | @NonNull TextView view, 18 | @NonNull KeyAction action 19 | ); 20 | } -------------------------------------------------------------------------------- /layer-design-res/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFFFF 4 | #FFFFFFFF 5 | #1A000000 6 | #BF000000 7 | #80000000 8 | #59000000 9 | #33000000 10 | 11 | #FAEEEEEE 12 | #BF000000 13 | -------------------------------------------------------------------------------- /layer-startup/src/main/java/per/goweii/layer/startup/LayerInitializer.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.startup; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.startup.Initializer; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | import per.goweii.layer.core.Layers; 13 | 14 | public class LayerInitializer implements Initializer { 15 | @NonNull 16 | @Override 17 | public Layers create(@NonNull Context context) { 18 | return Layers.init((Application) context.getApplicationContext()); 19 | } 20 | 21 | @NonNull 22 | @Override 23 | public List>> dependencies() { 24 | return Collections.emptyList(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /library.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.library" 2 | apply from: "../maven-upload.gradle" 3 | 4 | android { 5 | compileSdkVersion android_compile_sdk_version 6 | buildToolsVersion android_build_tools_version 7 | defaultConfig { 8 | minSdkVersion android_min_sdk_version 9 | targetSdkVersion android_target_sdk_version 10 | } 11 | buildTypes { 12 | release { 13 | minifyEnabled false 14 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 15 | } 16 | } 17 | compileOptions { 18 | sourceCompatibility JavaVersion.VERSION_1_7 19 | targetCompatibility JavaVersion.VERSION_1_7 20 | } 21 | } 22 | 23 | dependencies { 24 | compileOnly "androidx.appcompat:appcompat:$androidx_appcompat_version" 25 | } 26 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/overlay.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | android.useAndroidX=true 15 | android.enableJetifier=true 16 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: https://goweii.github.io/resource/payment_code/all_qrcode.jpg 14 | -------------------------------------------------------------------------------- /simple/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 attach 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 | -------------------------------------------------------------------------------- /simple/src/main/java/per/goweii/layer/simple/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.simple 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.view.View 6 | import androidx.appcompat.app.AppCompatActivity 7 | 8 | class MainActivity : AppCompatActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.activity_main) 12 | } 13 | 14 | fun onBtnLayers(view: View) { 15 | startActivity(Intent(this@MainActivity, LayersSimpleActivity::class.java)) 16 | } 17 | 18 | fun onBtnMaterial(view: View) { 19 | startActivity(Intent(this@MainActivity, MaterialSimpleActivity::class.java)) 20 | } 21 | 22 | fun onBtnCupertino(view: View) { 23 | startActivity(Intent(this@MainActivity, CupertinoSimpleActivity::class.java)) 24 | } 25 | } -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/listener/DefaultAnimatorListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.listener; 2 | 3 | import android.animation.Animator; 4 | 5 | public class DefaultAnimatorListener implements Animator.AnimatorListener { 6 | private boolean beenCanceled = false; 7 | 8 | @Override 9 | public void onAnimationStart(Animator animation) { 10 | beenCanceled = false; 11 | } 12 | 13 | @Override 14 | public void onAnimationEnd(Animator animation) { 15 | if (!beenCanceled) { 16 | onAnimationEndNotCanceled(animation); 17 | } 18 | } 19 | 20 | @Override 21 | public void onAnimationCancel(Animator animation) { 22 | beenCanceled = true; 23 | } 24 | 25 | @Override 26 | public void onAnimationRepeat(Animator animation) { 27 | } 28 | 29 | public void onAnimationEndNotCanceled(Animator animation) { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/drawable-anydpi/layer_keyboard_ic_del.xml: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/java/per/goweii/layer/keyboard/KeyboardVibratorEffect.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.keyboard; 2 | 3 | import android.content.Context; 4 | import android.os.VibrationEffect; 5 | import android.os.Vibrator; 6 | 7 | public class KeyboardVibratorEffect { 8 | private final Context mContext; 9 | private final Vibrator mVibrator; 10 | 11 | public KeyboardVibratorEffect(Context context) { 12 | this.mContext = context; 13 | this.mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 14 | } 15 | 16 | public void release() { 17 | mVibrator.cancel(); 18 | } 19 | 20 | public void performClick() { 21 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { 22 | VibrationEffect effect = VibrationEffect.createOneShot(1, 1); 23 | mVibrator.vibrate(effect); 24 | } else { 25 | mVibrator.vibrate(1); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 300dp 4 | 300dp 5 | 6 | 20dp 7 | 8 | 24dp 9 | 16dp 10 | 8dp 11 | 4dp 12 | 13 | 4dp 14 | 12dp 15 | 16 | 17sp 17 | 15sp 18 | 15sp 19 | 44dp 20 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/layout/layer_design_material_dialog_action.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /layer-guide-ktx/src/main/java/per/goweii/layer/guide/ktx/GuideLayer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.guide.ktx 2 | 3 | import android.view.View 4 | import androidx.annotation.ColorInt 5 | import androidx.annotation.ColorRes 6 | import androidx.annotation.IdRes 7 | import per.goweii.layer.guide.GuideLayer 8 | 9 | fun T.backgroundColorInt(@ColorInt colorInt: Int) = this.apply { 10 | this.setBackgroundColorInt(colorInt) 11 | } 12 | 13 | fun T.backgroundColorRes(@ColorRes colorRes: Int) = this.apply { 14 | this.setBackgroundColorRes(colorRes) 15 | } 16 | 17 | fun T.mapping(mapping: GuideLayer.Mapping) = this.apply { 18 | this.addMapping(mapping) 19 | } 20 | 21 | fun T.mapping(init: GuideLayer.Mapping.() -> Unit) = this.apply { 22 | this.addMapping(GuideLayer.Mapping().apply { init() }) 23 | } 24 | 25 | fun GuideLayer.Mapping.onClick( 26 | @IdRes viewId: Int, 27 | onClickListener: GuideLayer.(view: View) -> Unit 28 | ) = this.apply { 29 | this.addOnClickListener({ layer, v -> 30 | layer as GuideLayer 31 | layer.onClickListener(v) 32 | }, viewId) 33 | } -------------------------------------------------------------------------------- /simple/src/main/res/layout/guide_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | 26 | -------------------------------------------------------------------------------- /layer-design-res/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 48dp 4 | 32dp 5 | 24dp 6 | 16dp 7 | 8dp 8 | 9 | 0.5dp 10 | 11 | 8dp 12 | 12dp 13 | 14 | 24dp 15 | 16 | 48dp 17 | 18 | 18sp 19 | 16sp 20 | 16sp 21 | 14sp 22 | 14sp 23 | 12sp 24 | 10sp 25 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/java/per/goweii/layer/keyboard/KeyboardSoundEffect.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.keyboard; 2 | 3 | import android.content.Context; 4 | import android.media.AudioManager; 5 | import android.media.SoundPool; 6 | 7 | import androidx.annotation.NonNull; 8 | 9 | public class KeyboardSoundEffect { 10 | private static final int SOUND_CLICK = R.raw.layer_keyboard_click; 11 | 12 | private final Context mContext; 13 | private final SoundPool mSoundPool; 14 | 15 | private int mIdClick = 0; 16 | 17 | public KeyboardSoundEffect(@NonNull Context context) { 18 | mContext = context.getApplicationContext(); 19 | mSoundPool = new SoundPool(5, AudioManager.STREAM_SYSTEM, 0); 20 | load(); 21 | } 22 | 23 | public void release() { 24 | unload(); 25 | mSoundPool.release(); 26 | } 27 | 28 | public void performClick() { 29 | play(mIdClick); 30 | } 31 | 32 | private void load() { 33 | mIdClick = mSoundPool.load(mContext, SOUND_CLICK, 1); 34 | } 35 | 36 | private void unload() { 37 | if (mIdClick != 0) mSoundPool.unload(mIdClick); 38 | } 39 | 40 | private int play(int id) { 41 | if (id == 0) return 0; 42 | return mSoundPool.play(id, 0.5F, 0.5F, 0, 0, 1F); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /layer-toast-ktx/src/main/java/per/goweii/layer/toast/ktx/ToastLayer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.toast.ktx 2 | 3 | import android.view.View 4 | import androidx.annotation.LayoutRes 5 | import per.goweii.layer.toast.ToastLayer 6 | 7 | fun T.contentView(contentView: View) = this.apply { 8 | this.setContentView(contentView) 9 | } 10 | 11 | fun T.contentView(@LayoutRes contentViewId: Int) = this.apply { 12 | this.setContentView(contentViewId) 13 | } 14 | 15 | fun T.removeOthers(removeOthers: Boolean) = this.apply { 16 | this.setRemoveOthers(removeOthers) 17 | } 18 | 19 | fun T.duration(duration: Long) = this.apply { 20 | this.setDuration(duration) 21 | } 22 | 23 | fun T.gravity(gravity: Int) = this.apply { 24 | this.setGravity(gravity) 25 | } 26 | 27 | fun T.marginLeft(margin: Int?) = this.apply { 28 | this.setMarginLeft(margin) 29 | } 30 | 31 | fun T.marginTop(margin: Int?) = this.apply { 32 | this.setMarginTop(margin) 33 | } 34 | 35 | fun T.marginRight(margin: Int?) = this.apply { 36 | this.setMarginRight(margin) 37 | } 38 | 39 | fun T.marginBottom(margin: Int?) = this.apply { 40 | this.setMarginBottom(margin) 41 | } 42 | 43 | fun T.alpha(alpha: Float) = this.apply { 44 | this.setAlpha(alpha) 45 | } 46 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/dialog_fullscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/Layers.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import per.goweii.layer.core.utils.Utils; 9 | 10 | /** 11 | * 保存 Application 实例。 12 | * 维护 activity 队列,用于弹出全局的浮层。 13 | */ 14 | public final class Layers { 15 | private static Layers sLayers = null; 16 | 17 | private final Application mApplication; 18 | private final ActivityHolder mActivityHolder; 19 | 20 | private Layers(@NonNull Application application) { 21 | mApplication = application; 22 | mActivityHolder = new ActivityHolder(application); 23 | } 24 | 25 | public static Layers init(@NonNull Application application) { 26 | if (sLayers == null) { 27 | sLayers = new Layers(application); 28 | } 29 | return sLayers; 30 | } 31 | 32 | @NonNull 33 | public static Layers getInstance() { 34 | return Utils.requireNonNull(sLayers, "需要先在Application中初始化"); 35 | } 36 | 37 | @NonNull 38 | public static ActivityHolder getActivityHolder() { 39 | return getInstance().mActivityHolder; 40 | } 41 | 42 | @NonNull 43 | public static Application getApplication() { 44 | return getInstance().mApplication; 45 | } 46 | 47 | @NonNull 48 | public static Activity requireCurrentActivity() { 49 | return getActivityHolder().requireCurrentActivity(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/activity_material_simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 18 | 19 | 24 | 25 | 30 | 31 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /simple/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 28 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20dp 4 | 10dp 5 | 6dp 6 | 2dp 7 | 8 | 20dp 9 | 10 | 44dp 11 | 12 | 14dp 13 | 14 | 17sp 15 | 16sp 16 | 13sp 17 | 17sp 18 | 19 | 270dp 20 | 20dp 21 | 8dp 22 | 23 | 270dp 24 | 25 | 12dp 26 | 4dp 27 | 28 | 12dp 29 | 3dp 30 | 24dp 31 | 12dp 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Android template 3 | # Built application files 4 | app/release/ 5 | *.ap_ 6 | *.aab 7 | 8 | # Files for the ART/Dalvik VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # Generated files 15 | bin/ 16 | gen/ 17 | out/ 18 | 19 | # Gradle files 20 | .gradle/ 21 | build/ 22 | 23 | # Local configuration file (sdk path, etc) 24 | local.properties 25 | 26 | # Proguard folder generated by Eclipse 27 | proguard/ 28 | 29 | # Log Files 30 | *.log 31 | 32 | # Android Studio Navigation editor temp files 33 | .navigation/ 34 | 35 | # Android Studio captures folder 36 | captures/ 37 | 38 | # IntelliJ 39 | *.iml 40 | .idea/ 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | 61 | # Google Services (e.g. APIs or Firebase) 62 | # google-services.json 63 | 64 | # Freeline 65 | freeline.py 66 | freeline/ 67 | freeline_project_description.json 68 | 69 | # fastlane 70 | fastlane/report.xml 71 | fastlane/Preview.html 72 | fastlane/screenshots 73 | fastlane/test_output 74 | fastlane/readme.md 75 | 76 | # Version control 77 | vcs.xml 78 | 79 | # lint 80 | lint/intermediates/ 81 | lint/generated/ 82 | lint/outputs/ 83 | lint/tmp/ 84 | # lint/reports/ 85 | 86 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/widget/LayerContainer.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.FocusFinder; 6 | import android.view.View; 7 | import android.widget.FrameLayout; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | public class LayerContainer extends FrameLayout { 13 | private boolean mForceFocusInside = false; 14 | 15 | public LayerContainer(@NonNull Context context) { 16 | this(context, null); 17 | } 18 | 19 | public LayerContainer(@NonNull Context context, @Nullable AttributeSet attrs) { 20 | this(context, attrs, 0); 21 | } 22 | 23 | public LayerContainer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 24 | super(context, attrs, defStyleAttr); 25 | setFocusable(true); 26 | } 27 | 28 | public void setForceFocusInside(boolean forceFocusInside) { 29 | mForceFocusInside = forceFocusInside; 30 | if (forceFocusInside) { 31 | if (!hasFocus()) { 32 | requestFocus(); 33 | } 34 | } 35 | } 36 | 37 | @Override 38 | public View focusSearch(View focused, int direction) { 39 | if (!mForceFocusInside) { 40 | return super.focusSearch(focused, direction); 41 | } 42 | FocusFinder focusFinder = FocusFinder.getInstance(); 43 | View nextFocus = focusFinder.findNextFocus(this, focused, direction); 44 | if (nextFocus != null) { 45 | return nextFocus; 46 | } 47 | if (hasFocus()) { 48 | return focused; 49 | } 50 | if (!isFocusable()) { 51 | return focused; 52 | } 53 | return this; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/toast.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 24 | 25 | 32 | 33 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/layout/layer_keyboard.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 23 | 24 | 30 | 31 | 37 | 38 | 44 | 45 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/dialog_input.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 35 | 36 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/java/per/goweii/layer/keyboard/DefaultBindingActionListener.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.keyboard; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.text.Editable; 5 | import android.text.TextUtils; 6 | import android.widget.TextView; 7 | 8 | import androidx.annotation.NonNull; 9 | 10 | public class DefaultBindingActionListener extends BindingActionListener { 11 | @Override 12 | protected boolean onBind(@NonNull KeyboardLayer layer, @NonNull TextView view, @NonNull KeyAction action) { 13 | if (action.getCode() == KeyCodes.KEYCODE_ENTER) { 14 | return onEnter(layer, view, action); 15 | } 16 | if (action.getCode() == KeyCodes.KEYCODE_DEL) { 17 | return onDelete(layer, view, action); 18 | } 19 | if (action.hasInput()) { 20 | return onInput(layer, view, action); 21 | } 22 | return false; 23 | } 24 | 25 | protected boolean onEnter(@NonNull KeyboardLayer layer, @NonNull TextView view, @NonNull KeyAction action) { 26 | view.clearFocus(); 27 | layer.dismiss(); 28 | return true; 29 | } 30 | 31 | protected boolean onDelete(@NonNull KeyboardLayer layer, @NonNull TextView view, @NonNull KeyAction action) { 32 | CharSequence text = view.getText(); 33 | if (text.length() <= 0) { 34 | return false; 35 | } 36 | if (text instanceof Editable) { 37 | Editable editable = (Editable) text; 38 | editable.delete(text.length() - 1, text.length()); 39 | } else { 40 | view.setText(text.subSequence(0, text.length() - 1)); 41 | } 42 | return true; 43 | } 44 | 45 | @SuppressLint("SetTextI18n") 46 | protected boolean onInput(@NonNull KeyboardLayer layer, @NonNull TextView view, @NonNull KeyAction action) { 47 | if (TextUtils.isEmpty(action.getText())) { 48 | return false; 49 | } 50 | view.setText(view.getText() + action.getText()); 51 | return true; 52 | } 53 | } -------------------------------------------------------------------------------- /layer-visualeffectview/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/java/per/goweii/layer/keyboard/KeyAction.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.keyboard; 2 | 3 | import androidx.annotation.IdRes; 4 | import androidx.annotation.NonNull; 5 | import androidx.annotation.Nullable; 6 | 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | public class KeyAction { 11 | @IdRes 12 | private int mCode; 13 | @Nullable 14 | private String mText; 15 | 16 | public KeyAction(@IdRes int code, @Nullable String text) { 17 | this.mCode = code; 18 | this.mText = text; 19 | } 20 | 21 | public boolean hasInput() { 22 | return KeyCodes.hasInput(mCode); 23 | } 24 | 25 | public boolean isLetter() { 26 | return KeyCodes.isLetter(mCode); 27 | } 28 | 29 | public boolean isNumber() { 30 | return KeyCodes.isNumber(mCode); 31 | } 32 | 33 | public boolean isSymbol() { 34 | return KeyCodes.isSymbol(mCode); 35 | } 36 | 37 | public void reset() { 38 | this.mCode = 0; 39 | this.mText = null; 40 | } 41 | 42 | public void recycle() { 43 | recycle(this); 44 | } 45 | 46 | @NonNull 47 | public KeyAction copy() { 48 | return obtain(mCode, mText); 49 | } 50 | 51 | @IdRes 52 | public int getCode() { 53 | return mCode; 54 | } 55 | 56 | @Nullable 57 | public String getText() { 58 | return mText; 59 | } 60 | 61 | private void setCode(@IdRes int code) { 62 | mCode = code; 63 | } 64 | 65 | private void setText(@Nullable String text) { 66 | mText = text; 67 | } 68 | 69 | private static final List sPool = new LinkedList<>(); 70 | 71 | public static KeyAction obtain(@IdRes int code, @Nullable String text) { 72 | if (sPool.isEmpty()) { 73 | return new KeyAction(code, text); 74 | } 75 | KeyAction action = sPool.remove(0); 76 | action.setCode(code); 77 | action.setText(text); 78 | return action; 79 | } 80 | 81 | public static void recycle(@NonNull KeyAction action) { 82 | action.reset(); 83 | sPool.add(action); 84 | } 85 | } -------------------------------------------------------------------------------- /simple/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "kotlin-android" 3 | 4 | android { 5 | compileSdkVersion android_compile_sdk_version 6 | buildToolsVersion android_build_tools_version 7 | defaultConfig { 8 | applicationId android_application_id 9 | minSdkVersion android_min_sdk_version 10 | targetSdkVersion android_target_sdk_version 11 | versionCode android_version_code 12 | versionName android_version_name 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 19 | } 20 | } 21 | compileOptions { 22 | sourceCompatibility JavaVersion.VERSION_1_8 23 | targetCompatibility JavaVersion.VERSION_1_8 24 | } 25 | applicationVariants.all { variant -> 26 | variant.outputs.each { output -> 27 | output.outputFileName = "${applicationId}.apk" 28 | } 29 | } 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(include: ["*.jar"], dir: "libs") 34 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 35 | implementation "androidx.core:core-ktx:$androidx_core_ktx_version" 36 | implementation "androidx.appcompat:appcompat:1.3.1" 37 | implementation "androidx.cardview:cardview:1.0.0" 38 | implementation "androidx.startup:startup-runtime:1.1.0" 39 | implementation "com.github.goweii:ActionBarEx:3.3.0" 40 | implementation project(":layer-startup") 41 | implementation project(":layer-dialog-ktx") 42 | implementation project(":layer-popup-ktx") 43 | implementation project(":layer-notification-ktx") 44 | implementation project(":layer-guide-ktx") 45 | implementation project(":layer-overlay-ktx") 46 | implementation project(":layer-toast-ktx") 47 | implementation project(":layer-keyboard-ktx") 48 | implementation project(":layer-visualeffectview") 49 | implementation project(":layer-design-cupertino") 50 | implementation project(":layer-design-material") 51 | } 52 | -------------------------------------------------------------------------------- /layer-dialog/src/main/java/per/goweii/layer/dialog/DialogLayerActivity.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.dialog; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | 11 | import java.lang.ref.WeakReference; 12 | 13 | import per.goweii.layer.core.Layer; 14 | import per.goweii.layer.core.utils.Utils; 15 | 16 | public class DialogLayerActivity extends Activity implements Layer.OnVisibleChangedListener { 17 | 18 | @Nullable 19 | private static WeakReference sOnLayerCreatedCallback = null; 20 | 21 | static void start(@NonNull Context context, @NonNull OnLayerCreatedCallback callback) { 22 | sOnLayerCreatedCallback = new WeakReference<>(callback); 23 | Intent intent = new Intent(context, DialogLayerActivity.class); 24 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 25 | context.startActivity(intent); 26 | } 27 | 28 | @Override 29 | protected void onCreate(@Nullable Bundle savedInstanceState) { 30 | overridePendingTransition(0, 0); 31 | super.onCreate(savedInstanceState); 32 | Utils.transparent(this); 33 | DialogLayer dialogLayer = new DialogLayer(this); 34 | dialogLayer.addOnVisibleChangeListener(this); 35 | if (sOnLayerCreatedCallback != null) { 36 | OnLayerCreatedCallback callback = sOnLayerCreatedCallback.get(); 37 | if (callback != null) { 38 | callback.onLayerCreated(dialogLayer); 39 | } 40 | sOnLayerCreatedCallback.clear(); 41 | sOnLayerCreatedCallback = null; 42 | } 43 | } 44 | 45 | @Override 46 | public void onShow(@NonNull Layer layer) { 47 | } 48 | 49 | @Override 50 | public void onDismiss(@NonNull Layer layer) { 51 | finish(); 52 | overridePendingTransition(0, 0); 53 | } 54 | 55 | public interface OnLayerCreatedCallback { 56 | /** 57 | * 浮层已创建,可在这里进行浮层的初始化和数据绑定 58 | */ 59 | void onLayerCreated(@NonNull DialogLayer dialogLayer); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /simple/src/main/java/per/goweii/layer/simple/MaterialSimpleActivity.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.simple 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.appcompat.app.AppCompatActivity 6 | import per.goweii.layer.core.anim.DelayedZoomAnimatorCreator 7 | import per.goweii.layer.design.material.MaterialDialogLayer 8 | import per.goweii.layer.design.material.MaterialNotificationLayer 9 | import per.goweii.layer.design.material.MaterialPopupLayer 10 | import per.goweii.layer.design.material.MaterialToastLayer 11 | import per.goweii.layer.dialog.ktx.contentAnimator 12 | import per.goweii.layer.dialog.ktx.contentView 13 | 14 | class MaterialSimpleActivity : AppCompatActivity() { 15 | override fun onCreate(savedInstanceState: Bundle?) { 16 | super.onCreate(savedInstanceState) 17 | setContentView(R.layout.activity_material_simple) 18 | } 19 | 20 | fun onBtnDialogClick(view: View) { 21 | MaterialDialogLayer(this) 22 | .setTitle(R.string.dialog_title) 23 | .setDesc(R.string.dialog_msg) 24 | .addAction(R.string.i_know) { layer, _ -> layer.dismiss() } 25 | .addAction(R.string.send) { layer, _ -> layer.dismiss() } 26 | .addAction(R.string.close) { layer, _ -> layer.dismiss() } 27 | .show() 28 | } 29 | 30 | fun onBtnPopupClick(view: View) { 31 | MaterialPopupLayer(view) 32 | .contentView(R.layout.popup_meun) 33 | .contentAnimator(DelayedZoomAnimatorCreator().setCenterPercentX(0.5F)) 34 | .show() 35 | } 36 | 37 | fun onBtnToastClick(view: View) { 38 | MaterialToastLayer(this) 39 | .setIcon(R.drawable.ic_success) 40 | .setMessage(R.string.toast_msg) 41 | .show() 42 | } 43 | 44 | fun onBtnNotificationClick(view: View) { 45 | MaterialNotificationLayer(this) 46 | .setIcon(R.drawable.ic_notification) 47 | .setLabel(R.string.app_name) 48 | .setTitle(R.string.notification_title) 49 | .setDesc(R.string.notification_desc) 50 | .setTimePattern("yyyy-MM-dd") 51 | .setOnNotificationClickListener { layer, _ -> layer.dismiss() } 52 | .show() 53 | } 54 | } -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/layout/layer_design_cupertino_toast.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 25 | 26 | 34 | 35 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /layer-design-material/src/main/res/layout/layer_design_material_toast.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 25 | 26 | 36 | 37 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/utils/ScrollCompat.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.utils; 2 | 3 | import android.view.View; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.core.view.ScrollingView; 7 | 8 | public class ScrollCompat { 9 | 10 | public static boolean canScrollUp(@NonNull View view) { 11 | return ScrollCompat.canScrollVertically(view, -1); 12 | } 13 | 14 | public static boolean canScrollDown(@NonNull View view) { 15 | return ScrollCompat.canScrollVertically(view, 1); 16 | } 17 | 18 | public static boolean canScrollLeft(@NonNull View view) { 19 | return ScrollCompat.canScrollHorizontally(view, -1); 20 | } 21 | 22 | public static boolean canScrollRight(@NonNull View view) { 23 | return ScrollCompat.canScrollHorizontally(view, 1); 24 | } 25 | 26 | public static boolean canScrollHorizontally(@NonNull View v, int direction) { 27 | if (v instanceof ScrollingView) { 28 | return canScrollingViewScrollHorizontally((ScrollingView) v, direction); 29 | } else { 30 | return v.canScrollHorizontally(direction); 31 | } 32 | } 33 | 34 | public static boolean canScrollVertically(@NonNull View v, int direction) { 35 | if (v instanceof ScrollingView) { 36 | return canScrollingViewScrollVertically((ScrollingView) v, direction); 37 | } else { 38 | return v.canScrollVertically(direction); 39 | } 40 | } 41 | 42 | private static boolean canScrollingViewScrollHorizontally(@NonNull ScrollingView view, int direction) { 43 | final int offset = view.computeHorizontalScrollOffset(); 44 | final int range = view.computeHorizontalScrollRange() - view.computeHorizontalScrollExtent(); 45 | if (range == 0) return false; 46 | if (direction < 0) { 47 | return offset > 0; 48 | } else { 49 | return offset < range - 1; 50 | } 51 | } 52 | 53 | private static boolean canScrollingViewScrollVertically(@NonNull ScrollingView view, int direction) { 54 | final int offset = view.computeVerticalScrollOffset(); 55 | final int range = view.computeVerticalScrollRange() - view.computeVerticalScrollExtent(); 56 | if (range == 0) return false; 57 | if (direction < 0) { 58 | return offset > 0; 59 | } else { 60 | return offset < range - 1; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/activity_cupertino_simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 20 | 21 | 26 | 27 | 32 | 33 | 38 | 39 | 44 | 45 | 50 | 51 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /simple/src/main/java/per/goweii/layer/simple/CupertinoSimpleActivity.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.simple 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.appcompat.app.AppCompatActivity 6 | import per.goweii.actionbarex.common.ActionBarCommon 7 | import per.goweii.layer.core.ktx.onBindData 8 | import per.goweii.layer.design.cupertino.* 9 | import per.goweii.layer.dialog.ktx.contentView 10 | 11 | class CupertinoSimpleActivity : AppCompatActivity() { 12 | override fun onCreate(savedInstanceState: Bundle?) { 13 | super.onCreate(savedInstanceState) 14 | setContentView(R.layout.activity_cupertino_simple) 15 | } 16 | 17 | fun onBtnDialogClick(view: View) { 18 | CupertinoAlertLayer(this) 19 | .setTitle(R.string.dialog_title) 20 | .setDesc(R.string.dialog_msg) 21 | .addAction(R.string.i_know) { layer, _ -> 22 | layer.dismiss() 23 | } 24 | .addAction(R.string.send) { layer, _ -> 25 | layer.dismiss() 26 | } 27 | .addAction(R.string.close) { layer, _ -> 28 | layer.dismiss() 29 | } 30 | .show() 31 | } 32 | 33 | fun onBtnPopoverClick(view: View) { 34 | CupertinoPopoverLayer(view) 35 | .contentView(R.layout.popup_meun) 36 | .setUseDefaultConfig() 37 | .setSolidColor(resources.getColor(R.color.colorSurface)) 38 | .show() 39 | } 40 | 41 | fun onBtnModalityClick(view: View) { 42 | CupertinoModalityLayer(this) 43 | .contentView(R.layout.dialog_fullscreen) 44 | .onBindData { 45 | val actionBar = requireViewById(R.id.dialog_actionbar) 46 | actionBar.leftTextView.setOnClickListener { dismiss() } 47 | actionBar.rightTextView.setOnClickListener { dismiss() } 48 | } 49 | .show() 50 | } 51 | 52 | fun onBtnToastClick(view: View) { 53 | CupertinoToastLayer(this) 54 | .setIcon(R.drawable.ic_success_big) 55 | .setMessage(R.string.toast_msg) 56 | .show() 57 | } 58 | 59 | fun onBtnNotificationClick(view: View) { 60 | CupertinoNotificationLayer(this) 61 | .setIcon(R.drawable.ic_notification) 62 | .setLabel(R.string.app_name) 63 | .setTitle(R.string.notification_title) 64 | .setDesc(R.string.notification_desc) 65 | .setTimePattern("yyyy-MM-dd") 66 | .setOnNotificationClickListener { layer, _ -> layer.dismiss() } 67 | .show() 68 | } 69 | } -------------------------------------------------------------------------------- /simple/src/main/res/layout/layout_list_20.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 14 | 15 | 18 | 19 | 22 | 23 | 26 | 27 | 30 | 31 | 34 | 35 | 38 | 39 | 42 | 43 | 46 | 47 | 50 | 51 | 54 | 55 | 58 | 59 | 62 | 63 | 66 | 67 | 70 | 71 | 74 | 75 | 78 | 79 | 82 | 83 | 86 | 87 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 27 | 28 | 39 | 40 | 51 | 52 | -------------------------------------------------------------------------------- /layer-dialog/src/main/java/per/goweii/layer/dialog/ContainerLayout.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.dialog; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.util.AttributeSet; 6 | import android.view.GestureDetector; 7 | import android.view.MotionEvent; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | import per.goweii.layer.core.widget.LayerContainer; 13 | 14 | public class ContainerLayout extends LayerContainer { 15 | private final GestureDetector mGestureDetector; 16 | 17 | private boolean mHandleTouchEvent = false; 18 | 19 | private OnTouchedListener mOnTouchedListener = null; 20 | private OnTappedListener mOnTappedListener = null; 21 | 22 | public ContainerLayout(@NonNull Context context) { 23 | this(context, null); 24 | } 25 | 26 | public ContainerLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 27 | this(context, attrs, 0); 28 | } 29 | 30 | public ContainerLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 31 | super(context, attrs, defStyleAttr); 32 | mGestureDetector = new GestureDetector(context, new OnGestureListener()); 33 | } 34 | 35 | @SuppressLint("ClickableViewAccessibility") 36 | @Override 37 | public boolean onTouchEvent(MotionEvent ev) { 38 | return mGestureDetector.onTouchEvent(ev); 39 | } 40 | 41 | public void setHandleTouchEvent(boolean handleTouchEvent) { 42 | this.mHandleTouchEvent = handleTouchEvent; 43 | } 44 | 45 | public void setOnTouchedListener(@Nullable OnTouchedListener onTouchedListener) { 46 | this.mOnTouchedListener = onTouchedListener; 47 | } 48 | 49 | public void setOnTappedListener(@Nullable OnTappedListener onTappedListener) { 50 | this.mOnTappedListener = onTappedListener; 51 | } 52 | 53 | private class OnGestureListener extends GestureDetector.SimpleOnGestureListener { 54 | @Override 55 | public boolean onDown(MotionEvent e) { 56 | if (mOnTouchedListener != null) { 57 | mOnTouchedListener.onTouched(); 58 | } 59 | return mHandleTouchEvent; 60 | } 61 | 62 | @Override 63 | public boolean onSingleTapUp(MotionEvent e) { 64 | if (mOnTappedListener != null) { 65 | mOnTappedListener.onTapped(); 66 | } 67 | return true; 68 | } 69 | } 70 | 71 | public interface OnTouchedListener { 72 | void onTouched(); 73 | } 74 | 75 | public interface OnTappedListener { 76 | void onTapped(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /layer-popup-ktx/src/main/java/per/goweii/layer/popup/ktx/PopupLayer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.popup.ktx 2 | 3 | import android.view.View 4 | import per.goweii.layer.popup.PopupLayer 5 | import per.goweii.layer.popup.PopupLayer.Align 6 | 7 | fun T.updateLocationInterceptor(interceptor: PopupLayer.UpdateLocationInterceptor) = 8 | this.apply { 9 | this.setUpdateLocationInterceptor(interceptor) 10 | } 11 | 12 | fun T.onViewTreeScrollChanged(onScrollChanged: T.() -> Unit) = this.apply { 13 | this.setOnViewTreeScrollChangedListener { this.onScrollChanged() } 14 | } 15 | 16 | fun T.scrollChangedToDismiss(enable: Boolean) = this.apply { 17 | this.setScrollChangedToDismiss(enable) 18 | } 19 | 20 | fun T.targetView(target: View) = this.apply { 21 | this.setTargetView(target) 22 | } 23 | 24 | fun T.contentClip(enable: Boolean) = this.apply { 25 | this.setContentClip(enable) 26 | } 27 | 28 | fun T.backgroundAlign(enable: Boolean) = this.apply { 29 | this.setBackgroundAlign(enable) 30 | } 31 | 32 | fun T.backgroundOffset(enable: Boolean) = this.apply { 33 | this.setBackgroundOffset(enable) 34 | } 35 | 36 | fun T.backgroundResize(enable: Boolean) = this.apply { 37 | this.setBackgroundResize(enable) 38 | } 39 | 40 | fun T.align( 41 | direction: Align.Direction, 42 | horizontal: Align.Horizontal, 43 | vertical: Align.Vertical, 44 | inside: Boolean 45 | ) = this.apply { 46 | this.setAlign(direction, horizontal, vertical, inside) 47 | } 48 | 49 | fun T.direction(direction: Align.Direction) = this.apply { 50 | this.setDirection(direction) 51 | } 52 | 53 | fun T.horizontal(horizontal: Align.Horizontal) = this.apply { 54 | this.setHorizontal(horizontal) 55 | } 56 | 57 | fun T.vertical(vertical: Align.Vertical) = this.apply { 58 | this.setVertical(vertical) 59 | } 60 | 61 | fun T.inside(inside: Boolean) = this.apply { 62 | this.setInside(inside) 63 | } 64 | 65 | fun T.offsetX(offsetX: Float, unit: Int) = this.apply { 66 | this.setOffsetX(offsetX, unit) 67 | } 68 | 69 | fun T.offsetXdp(offsetX: Float) = this.apply { 70 | this.setOffsetXdp(offsetX) 71 | } 72 | 73 | fun T.offsetXpx(offsetX: Float) = this.apply { 74 | this.setOffsetXpx(offsetX) 75 | } 76 | 77 | fun T.offsetY(offsetY: Float, unit: Int) = this.apply { 78 | this.setOffsetY(offsetY, unit) 79 | } 80 | 81 | fun T.offsetYdp(offsetY: Float) = this.apply { 82 | this.setOffsetYdp(offsetY) 83 | } 84 | 85 | fun T.offsetYpx(offsetY: Float) = this.apply { 86 | this.setOffsetYpx(offsetY) 87 | } -------------------------------------------------------------------------------- /layer-visualeffectview/src/main/java/per/goweii/layer/visualeffectview/BackdropIgnoreView.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.visualeffectview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.util.AttributeSet; 6 | import android.widget.FrameLayout; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | 11 | import java.lang.ref.WeakReference; 12 | import java.util.Iterator; 13 | import java.util.LinkedList; 14 | import java.util.List; 15 | 16 | public class BackdropIgnoreView extends FrameLayout { 17 | private final List> mBackdropBlurViews = new LinkedList<>(); 18 | 19 | public BackdropIgnoreView(@NonNull Context context) { 20 | super(context); 21 | } 22 | 23 | public BackdropIgnoreView(@NonNull Context context, @Nullable AttributeSet attrs) { 24 | super(context, attrs); 25 | } 26 | 27 | public BackdropIgnoreView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 28 | super(context, attrs, defStyleAttr); 29 | } 30 | 31 | public void clearBackdropBlurViews() { 32 | mBackdropBlurViews.clear(); 33 | } 34 | 35 | public boolean containBackdropBlurView(@Nullable BackdropBlurView backdropBlurView) { 36 | Iterator> iterator = mBackdropBlurViews.iterator(); 37 | boolean contain = false; 38 | while (iterator.hasNext()) { 39 | WeakReference reference = iterator.next(); 40 | if (reference.get() == null) { 41 | iterator.remove(); 42 | } else { 43 | if (reference.get() == backdropBlurView) { 44 | contain = true; 45 | } 46 | } 47 | } 48 | return contain; 49 | } 50 | 51 | public void addBackdropBlurView(@Nullable BackdropBlurView backdropBlurView) { 52 | if (containBackdropBlurView(backdropBlurView)) { 53 | return; 54 | } 55 | if (backdropBlurView != null) { 56 | mBackdropBlurViews.add(new WeakReference<>(backdropBlurView)); 57 | } 58 | } 59 | 60 | @Override 61 | public void draw(Canvas canvas) { 62 | boolean hasRendering = false; 63 | Iterator> iterator = mBackdropBlurViews.iterator(); 64 | while (iterator.hasNext()) { 65 | WeakReference reference = iterator.next(); 66 | if (reference.get() == null) { 67 | iterator.remove(); 68 | } else { 69 | if (!hasRendering && reference.get().isRendering()) { 70 | hasRendering = true; 71 | } 72 | } 73 | } 74 | if (!hasRendering) { 75 | super.draw(canvas); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/activity_layers_simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 16 | 17 | 22 | 23 | 28 | 29 | 34 | 35 | 40 | 41 | 46 | 47 | 52 | 53 | 58 | 59 | 64 | 65 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/layout/layer_design_cupertino_alert.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 27 | 28 | 41 | 42 | 47 | 48 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/widget/MaxSizeFrameLayout.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.widget; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | import android.widget.FrameLayout; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | import per.goweii.layer.core.R; 13 | 14 | public class MaxSizeFrameLayout extends FrameLayout { 15 | 16 | private int mMaxWidth = -1; 17 | private int mMaxHeight = -1; 18 | 19 | private OnDispatchTouchListener mOnDispatchTouchListener = null; 20 | 21 | public MaxSizeFrameLayout(@NonNull Context context) { 22 | this(context, null); 23 | } 24 | 25 | public MaxSizeFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 26 | this(context, attrs, 0); 27 | } 28 | 29 | public MaxSizeFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 30 | super(context, attrs, defStyleAttr); 31 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MaxSizeFrameLayout); 32 | mMaxWidth = (int) array.getDimension(R.styleable.MaxSizeFrameLayout_android_maxWidth, mMaxWidth); 33 | mMaxHeight = (int) array.getDimension(R.styleable.MaxSizeFrameLayout_android_maxHeight, mMaxHeight); 34 | array.recycle(); 35 | } 36 | 37 | public void setMaxWidth(int maxWidth) { 38 | this.mMaxWidth = maxWidth; 39 | requestLayout(); 40 | } 41 | 42 | public void setMaxHeight(int maxHeight) { 43 | this.mMaxHeight = maxHeight; 44 | requestLayout(); 45 | } 46 | 47 | @Override 48 | public boolean dispatchTouchEvent(MotionEvent e) { 49 | if (mOnDispatchTouchListener != null) { 50 | mOnDispatchTouchListener.onDispatch(e); 51 | } 52 | return super.dispatchTouchEvent(e); 53 | } 54 | 55 | @Override 56 | public boolean onInterceptTouchEvent(MotionEvent e) { 57 | return super.onInterceptTouchEvent(e); 58 | } 59 | 60 | @Override 61 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 62 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 63 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 64 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 65 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 66 | int newWidthSize = widthSize; 67 | int newHeightSize = heightSize; 68 | if (mMaxWidth >= 0) { 69 | newWidthSize = Math.min(mMaxWidth, widthSize); 70 | } 71 | if (mMaxHeight >= 0) { 72 | newHeightSize = Math.min(mMaxHeight, heightSize); 73 | } 74 | int newWidthSpec = MeasureSpec.makeMeasureSpec(newWidthSize, widthMode); 75 | int newHeightSpec = MeasureSpec.makeMeasureSpec(newHeightSize, heightMode); 76 | super.onMeasure(newWidthSpec, newHeightSpec); 77 | } 78 | 79 | public void setOnDispatchTouchListener(@Nullable OnDispatchTouchListener onDispatchTouchListener) { 80 | this.mOnDispatchTouchListener = onDispatchTouchListener; 81 | } 82 | 83 | public interface OnDispatchTouchListener { 84 | void onDispatch(MotionEvent e); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | Android稳定高效的浮层创建管理框架。 4 | 5 | [GitHub主页](https://github.com/goweii/Layer) 6 | 7 | [Wiki](https://github.com/goweii/Layer/wiki) 8 | 9 | 可实现Dialog,PopupWindow,引导层,悬浮按钮,通知,吐司,安全键盘等效果。 10 | 11 | 已实现几种常用效果 12 | - DialogLayer:AlertDialog/BottomSheetDialog 13 | - 占用区域不会超过当前Activity避免导航栏遮挡 14 | - 支持自定义大小和显示位置 15 | - 支持自定义数据绑定 16 | - 支持自定义进出场动画 17 | - 支持自定义背景颜色/图片/高斯模糊 18 | - 支持在Activity的onCreate生命周期弹出 19 | - 支持从ApplicationContext中弹出 20 | - 支持拖拽关闭 21 | - 支持不拦截外部事件 22 | - PopupLayer:PopupWindow 23 | - 拥有Dialog效果特性 24 | - 支持跟随目标View移动 25 | - ToastLayer:吐司 26 | - 支持自定义图标和文字 27 | - 支持自定义显示时长 28 | - 支持自定义位置 29 | - 支持自定义背景资源和颜色 30 | - 支持自定义透明度 31 | - 支持自定义进出场动画 32 | - GuideLayer:引导层 33 | - 支持自定义遮罩颜色和圆角半径 34 | - OverlayLayer:悬浮按钮 35 | - 支持自定义吸附边 36 | - 支持自定义正常和低姿态2中模式 37 | - 支持自定义低姿态显示效果 38 | - NotificationLayer:通知 39 | - 支持滑动关闭 40 | - KeyboardLayer:软键盘 41 | - 支持大小写字母/数字/常用符号 42 | 43 | # 截图 44 | 45 | 截图效果较差,建议[下载Demo](https://raw.githubusercontent.com/goweii/Layer/master/simple/release/per.goweii.layer.simple.apk)体验最新功能 46 | 47 | | ![qQF8OK.gif](https://s1.ax1x.com/2022/03/22/qQF8OK.gif) | ![qQF1Qx.gif](https://s1.ax1x.com/2022/03/22/qQF1Qx.gif) | ![qQF3y6.gif](https://s1.ax1x.com/2022/03/22/qQF3y6.gif) | 48 | | --- | --- | --- | 49 | 50 | # 如何集成 51 | 52 | - 添加仓库 53 | 54 | ```groovy 55 | // build.gradle(Project:) 56 | allprojects { 57 | repositories { 58 | maven { url 'https://jitpack.io' } 59 | } 60 | } 61 | ``` 62 | 63 | - 添加依赖 64 | 65 | ![](https://img.shields.io/github/v/release/goweii/Layer) 66 | 67 | ```groovy 68 | // build.gradle(Module:) 69 | dependencies { 70 | def version = "1.0.0" 71 | 72 | // 完整引入 73 | implementation "com.github.goweii:Layer:$version" 74 | 75 | // 按需引入 76 | 77 | // 核心功能 78 | // implementation "com.github.goweii.Layer:layer-core:$version" 79 | // 核心功能Kotlin扩展库 80 | // implementation "com.github.goweii.Layer:layer-ktx:$version" 81 | // 自动初始化 82 | // implementation "com.github.goweii.Layer:layer-startup:$version" 83 | 84 | // 各个浮层效果(xxx为module名) 85 | // implementation "com.github.goweii.Layer:layer-xxx:$version" 86 | // implementation "com.github.goweii.Layer:layer-xxx-ktx:$version" 87 | } 88 | ``` 89 | 90 | # 如何使用 91 | 92 | 具体使用可参考simple 93 | 94 | - [LayersSimpleActivity](https://raw.githubusercontent.com/goweii/Layer/master/simple/src/main/java/per/goweii/layer/simple/LayersSimpleActivity.kt) 95 | - [MaterialSimpleActivity](https://raw.githubusercontent.com/goweii/Layer/master/simple/src/main/java/per/goweii/layer/simple/MaterialSimpleActivity.kt) 96 | - [CupertinoSimpleActivity](https://raw.githubusercontent.com/goweii/Layer/master/simple/src/main/java/per/goweii/layer/simple/CupertinoSimpleActivity.kt) 97 | 98 | # 更新说明 99 | 100 | [点击查看](https://github.com/goweii/Layer/releases) 101 | 102 | # 如果你觉得还不错,就请我喝杯咖啡吧~ 103 | 104 | | 微信 | 支付宝 | QQ | 105 | | :---: | :---: | :---: | 106 | | ![wx_qrcode](https://gitee.com/goweii/WanAndroidServer/raw/master/about/wx_qrcode.png) | ![zfb_qrcode](https://gitee.com/goweii/WanAndroidServer/raw/master/about/zfb_qrcode.png) | ![qq_qrcode](https://gitee.com/goweii/WanAndroidServer/raw/master/about/qq_qrcode.png) | 107 | 108 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/popup_meun.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 24 | 25 | 26 | 27 | 31 | 32 | 40 | 41 | 42 | 43 | 47 | 48 | 56 | 57 | 58 | 59 | 63 | 64 | 72 | 73 | 74 | 75 | 79 | 80 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /layer-notification-ktx/src/main/java/per/goweii/layer/notification/ktx/NotificationLayer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.notification.ktx 2 | 3 | import android.view.View 4 | import androidx.annotation.FloatRange 5 | import androidx.annotation.LayoutRes 6 | import per.goweii.layer.core.widget.SwipeLayout 7 | import per.goweii.layer.notification.DefaultNotificationOnSwipeListener 8 | import per.goweii.layer.notification.NotificationLayer 9 | import per.goweii.layer.notification.NotificationLayer.SwipeTransformer 10 | 11 | fun T.contentView(contentView: View) = this.apply { 12 | this.setContentView(contentView) 13 | } 14 | 15 | fun T.contentView(@LayoutRes contentViewId: Int) = this.apply { 16 | this.setContentView(contentViewId) 17 | } 18 | 19 | fun T.maxWidth(maxWidth: Int) = this.apply { 20 | this.setMaxWidth(maxWidth) 21 | } 22 | 23 | fun T.maxHeight(maxHeight: Int) = this.apply { 24 | this.setMaxHeight(maxHeight) 25 | } 26 | 27 | fun T.removeOthers(removeOthers: Boolean) = this.apply { 28 | this.setRemoveOthers(removeOthers) 29 | } 30 | 31 | fun T.swipeDirection(@SwipeLayout.Direction direction: Int) = this.apply { 32 | this.setSwipeDirection(direction) 33 | } 34 | 35 | fun T.swipeTransformer(swipeTransformer: SwipeTransformer) = this.apply { 36 | this.setSwipeTransformer(swipeTransformer) 37 | } 38 | 39 | fun T.duration(duration: Long) = this.apply { 40 | this.setDuration(duration) 41 | } 42 | 43 | fun T.onNotificationClick(onClick: T.(view: View) -> Unit) = 44 | this.apply { 45 | this.setOnNotificationClickListener { _, view -> this.onClick(view) } 46 | } 47 | 48 | fun T.onNotificationLongClick(onLongClick: T.(view: View) -> Boolean) = 49 | this.apply { 50 | this.setOnNotificationLongClickListener { _, view -> this.onLongClick(view) } 51 | } 52 | 53 | fun T.autoDismiss(autoDismiss: Boolean) = this.apply { 54 | this.setAutoDismiss(autoDismiss) 55 | } 56 | 57 | fun T.onSwipeStart(onStart: T.() -> Unit) = this.apply { 58 | this.addOnSwipeListener(object : DefaultNotificationOnSwipeListener() { 59 | override fun onStart(layer: NotificationLayer) { 60 | this@apply.onStart() 61 | } 62 | }) 63 | } 64 | 65 | fun T.onSwiping(onSwiping: T.(direction: Int, fraction: Float) -> Unit) = 66 | this.apply { 67 | this.addOnSwipeListener(object : DefaultNotificationOnSwipeListener() { 68 | override fun onSwiping( 69 | layer: NotificationLayer, 70 | @SwipeLayout.Direction direction: Int, 71 | @FloatRange(from = 0.0, to = 1.0) fraction: Float 72 | ) { 73 | this@apply.onSwiping(direction, fraction) 74 | } 75 | }) 76 | } 77 | 78 | fun T.onSwipeEnd(onEnd: T.(direction: Int) -> Unit) = this.apply { 79 | this.addOnSwipeListener(object : DefaultNotificationOnSwipeListener() { 80 | override fun onEnd(layer: NotificationLayer, @SwipeLayout.Direction direction: Int) { 81 | this@apply.onEnd(direction) 82 | } 83 | }) 84 | } -------------------------------------------------------------------------------- /layer-guide/src/main/java/per/goweii/layer/guide/HoleView.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.guide; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.Rect; 9 | import android.graphics.RectF; 10 | import android.graphics.Region; 11 | import android.os.Build; 12 | import android.util.AttributeSet; 13 | import android.view.View; 14 | 15 | import androidx.annotation.ColorInt; 16 | import androidx.annotation.NonNull; 17 | import androidx.annotation.Nullable; 18 | import androidx.core.graphics.ColorUtils; 19 | 20 | import per.goweii.layer.core.utils.Utils; 21 | 22 | public class HoleView extends View { 23 | private final Paint mPaint; 24 | private final Path mTempPath = new Path(); 25 | private final Path mHolePath = new Path(); 26 | @ColorInt 27 | private int mOuterColor = ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.5)); 28 | 29 | public HoleView(Context context) { 30 | this(context, null); 31 | } 32 | 33 | public HoleView(Context context, @Nullable AttributeSet attrs) { 34 | this(context, attrs, 0); 35 | } 36 | 37 | public HoleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 38 | super(context, attrs, defStyleAttr); 39 | mPaint = new Paint(); 40 | mPaint.setAntiAlias(true); 41 | } 42 | 43 | public void setOuterColor(@ColorInt int colorInt) { 44 | mOuterColor = colorInt; 45 | } 46 | 47 | public void clear() { 48 | mTempPath.reset(); 49 | mTempPath.rewind(); 50 | } 51 | 52 | public void addCircle(float centerX, float centerY, float radius) { 53 | mTempPath.addCircle(centerX, centerY, radius, Path.Direction.CW); 54 | } 55 | 56 | public void addRect(float left, float top, float right, float bottom, float radii) { 57 | addRect(new RectF(left, top, right, bottom), radii); 58 | } 59 | 60 | public void addRect(@NonNull Rect rect, float radii) { 61 | addRect(new RectF(rect), radii); 62 | } 63 | 64 | public void addRect(@NonNull RectF rectF, float radii) { 65 | radii = Utils.floatRange(radii, 0F, Math.min(rectF.width(), rectF.height()) / 2F); 66 | mTempPath.addRoundRect( 67 | rectF, 68 | new float[]{radii, radii, radii, radii, radii, radii, radii, radii}, 69 | Path.Direction.CW 70 | ); 71 | } 72 | 73 | public void addPath(@NonNull Path path) { 74 | mTempPath.addPath(path); 75 | invalidate(); 76 | } 77 | 78 | @Override 79 | protected void onDraw(Canvas canvas) { 80 | super.onDraw(canvas); 81 | canvas.save(); 82 | mPaint.setColor(mOuterColor); 83 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 84 | mHolePath.reset(); 85 | mHolePath.rewind(); 86 | mHolePath.addRect(0F, 0F, getWidth(), getHeight(), Path.Direction.CW); 87 | mHolePath.op(mHolePath, mTempPath, Path.Op.DIFFERENCE); 88 | canvas.drawPath(mHolePath, mPaint); 89 | } else { 90 | canvas.clipPath(mTempPath, Region.Op.DIFFERENCE); 91 | canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); 92 | } 93 | canvas.restore(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /layer-overlay-ktx/src/main/java/per/goweii/layer/overlay/ktx/OverlayLayer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.overlay.ktx 2 | 3 | import android.view.View 4 | import androidx.annotation.FloatRange 5 | import androidx.annotation.LayoutRes 6 | import per.goweii.layer.overlay.OverlayLayer 7 | 8 | fun T.overlayView(@LayoutRes layoutId: Int) = this.apply { 9 | this.setOverlayView(layoutId) 10 | } 11 | 12 | fun T.overlayView(floatView: View) = this.apply { 13 | this.setOverlayView(floatView) 14 | } 15 | 16 | fun T.defPercentX(p: Float) = this.apply { 17 | this.setDefPercentX(p) 18 | } 19 | 20 | fun T.defPercentY(p: Float) = this.apply { 21 | this.setDefPercentY(p) 22 | } 23 | 24 | fun T.defAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) = this.apply { 25 | this.setDefAlpha(alpha) 26 | } 27 | 28 | fun T.defScale(scale: Float) = this.apply { 29 | this.setDefScale(scale) 30 | } 31 | 32 | fun T.normalAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) = this.apply { 33 | this.setNormalAlpha(alpha) 34 | } 35 | 36 | fun T.normalScale(scale: Float) = this.apply { 37 | this.setNormalScale(scale) 38 | } 39 | 40 | fun T.lowProfileAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) = 41 | this.apply { 42 | this.setLowProfileAlpha(alpha) 43 | } 44 | 45 | fun T.lowProfileScale(scale: Float) = this.apply { 46 | this.setLowProfileScale(scale) 47 | } 48 | 49 | fun T.lowProfileIndent(@FloatRange(from = 0.0, to = 1.0) indent: Float) = 50 | this.apply { 51 | this.setLowProfileIndent(indent) 52 | } 53 | 54 | fun T.lowProfileDelay(delay: Long) = this.apply { 55 | this.setLowProfileDelay(delay) 56 | } 57 | 58 | fun T.snapEdge(edge: Int) = this.apply { 59 | this.setSnapEdge(edge) 60 | } 61 | 62 | fun T.pivotX(pivot: Float) = this.apply { 63 | this.setPivotX(pivot) 64 | } 65 | 66 | fun T.pivotY(pivot: Float) = this.apply { 67 | this.setPivotY(pivot) 68 | } 69 | 70 | fun T.outside(outside: Boolean) = this.apply { 71 | this.setOutside(outside) 72 | } 73 | 74 | fun T.marginLeft(margin: Int?) = this.apply { 75 | this.setMarginLeft(margin) 76 | } 77 | 78 | fun T.marginTop(margin: Int?) = this.apply { 79 | this.setMarginTop(margin) 80 | } 81 | 82 | fun T.marginRight(margin: Int?) = this.apply { 83 | this.setMarginRight(margin) 84 | } 85 | 86 | fun T.marginBottom(margin: Int?) = this.apply { 87 | this.setMarginBottom(margin) 88 | } 89 | 90 | fun T.paddingLeft(padding: Int) = this.apply { 91 | this.setPaddingLeft(padding) 92 | } 93 | 94 | fun T.paddingTop(padding: Int) = this.apply { 95 | this.setPaddingTop(padding) 96 | } 97 | 98 | fun T.paddingRight(padding: Int) = this.apply { 99 | this.setPaddingRight(padding) 100 | } 101 | 102 | fun T.paddingBottom(padding: Int) = this.apply { 103 | this.setPaddingBottom(padding) 104 | } 105 | 106 | fun T.onOverlayClick(onClick: T.(view: View) -> Unit) = this.apply { 107 | this.addOnOverlayClickListener { _, view -> this.onClick(view) } 108 | } 109 | 110 | fun T.onOverlayLongClick(onLongClick: T.(view: View) -> Boolean) = this.apply { 111 | this.setOnOverlayLongClickListener { _, view -> this.onLongClick(view) } 112 | } -------------------------------------------------------------------------------- /layer-design-material/src/main/res/layout/layer_design_material_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 24 | 25 | 36 | 37 | 49 | 50 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /simple/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 22 | 23 | 33 | 34 | 40 | 41 | 47 | 48 | 53 | 54 | 59 | 60 | 76 | 77 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/anim/CircularRevealAnimatorCreator.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.anim; 2 | 3 | import android.animation.Animator; 4 | import android.animation.TimeInterpolator; 5 | import android.os.Build; 6 | import android.view.View; 7 | import android.view.ViewAnimationUtils; 8 | import android.view.animation.AccelerateInterpolator; 9 | import android.view.animation.DecelerateInterpolator; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.annotation.Nullable; 13 | import androidx.annotation.RequiresApi; 14 | 15 | import per.goweii.layer.core.Layer; 16 | 17 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP) 18 | public class CircularRevealAnimatorCreator implements Layer.AnimatorCreator { 19 | private boolean mUsePercentX = true; 20 | private boolean mUsePercentY = true; 21 | private float mCenterPercentX = 0.5F; 22 | private float mCenterPercentY = 0.5F; 23 | private int mCenterX = 0; 24 | private int mCenterY = 0; 25 | private TimeInterpolator mInTimeInterpolator = null; 26 | private TimeInterpolator mOutTimeInterpolator = null; 27 | 28 | public CircularRevealAnimatorCreator setCenterPercentX(float centerPercentX) { 29 | mUsePercentX = true; 30 | mCenterPercentX = centerPercentX; 31 | return this; 32 | } 33 | 34 | public CircularRevealAnimatorCreator setCenterPercentY(float centerPercentY) { 35 | mUsePercentY = true; 36 | mCenterPercentY = centerPercentY; 37 | return this; 38 | } 39 | 40 | public CircularRevealAnimatorCreator setCenterX(int centerX) { 41 | mUsePercentX = false; 42 | mCenterX = centerX; 43 | return this; 44 | } 45 | 46 | public CircularRevealAnimatorCreator setCenterY(int centerY) { 47 | mUsePercentY = false; 48 | mCenterY = centerY; 49 | return this; 50 | } 51 | 52 | public void setInTimeInterpolator(TimeInterpolator inTimeInterpolator) { 53 | mInTimeInterpolator = inTimeInterpolator; 54 | } 55 | 56 | public void setOutTimeInterpolator(TimeInterpolator outTimeInterpolator) { 57 | mOutTimeInterpolator = outTimeInterpolator; 58 | } 59 | 60 | @Nullable 61 | @Override 62 | public Animator createInAnimator(@NonNull View target) { 63 | int x = target.getWidth(); 64 | int y = target.getHeight(); 65 | int centerX = mUsePercentX ? (int) (mCenterPercentX * x) : mCenterX; 66 | int centerY = mUsePercentY ? (int) (mCenterPercentY * y) : mCenterY; 67 | int r = (int) Math.sqrt(Math.pow(Math.max(centerX, x - centerX), 2) + Math.pow(Math.max(centerY, y - centerY), 2)); 68 | Animator animator = ViewAnimationUtils.createCircularReveal(target, centerX, centerY, 0, r); 69 | if (mInTimeInterpolator != null) { 70 | animator.setInterpolator(mInTimeInterpolator); 71 | } else { 72 | animator.setInterpolator(new DecelerateInterpolator()); 73 | } 74 | return animator; 75 | } 76 | 77 | @Nullable 78 | @Override 79 | public Animator createOutAnimator(@NonNull View target) { 80 | int x = target.getWidth(); 81 | int y = target.getHeight(); 82 | int centerX = mUsePercentX ? (int) (mCenterPercentX * x) : mCenterX; 83 | int centerY = mUsePercentY ? (int) (mCenterPercentY * y) : mCenterY; 84 | int r = (int) Math.sqrt(Math.pow(Math.max(centerX, x - centerX), 2) + Math.pow(Math.max(centerY, y - centerY), 2)); 85 | Animator animator = ViewAnimationUtils.createCircularReveal(target, centerX, centerY, r, 0); 86 | if (mOutTimeInterpolator != null) { 87 | animator.setInterpolator(mOutTimeInterpolator); 88 | } else { 89 | animator.setInterpolator(new AccelerateInterpolator()); 90 | } 91 | return animator; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /simple/src/main/res/layout/dialog_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 18 | 19 | 31 | 32 | 43 | 44 | 49 | 50 | 57 | 58 | 65 | 66 | 67 | 68 | 74 | 75 | 82 | 83 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /layer-keyboard/src/main/java/per/goweii/layer/keyboard/KeyboardGesture.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.keyboard; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.view.GestureDetector; 5 | import android.view.MotionEvent; 6 | import android.view.View; 7 | 8 | import androidx.annotation.NonNull; 9 | 10 | public class KeyboardGesture { 11 | private final KeyboardLayer mLayer; 12 | private final View mView; 13 | private final boolean mRepeatable; 14 | private final Runnable mOnKeyAction; 15 | private final KeyboardGestureListener mGestureListener; 16 | 17 | public KeyboardGesture( 18 | @NonNull KeyboardLayer layer, 19 | @NonNull View view, 20 | boolean repeatable, 21 | @NonNull Runnable action 22 | ) { 23 | this.mLayer = layer; 24 | this.mView = view; 25 | this.mRepeatable = repeatable; 26 | this.mOnKeyAction = action; 27 | this.mGestureListener = new KeyboardGestureListener(); 28 | final GestureDetector gestureDetector = new GestureDetector(view.getContext(), mGestureListener); 29 | mView.setOnTouchListener(new View.OnTouchListener() { 30 | @SuppressLint("ClickableViewAccessibility") 31 | @Override 32 | public boolean onTouch(View v, MotionEvent event) { 33 | gestureDetector.onTouchEvent(event); 34 | switch (event.getAction()) { 35 | case MotionEvent.ACTION_UP: 36 | mGestureListener.onUp(event); 37 | case MotionEvent.ACTION_CANCEL: 38 | mGestureListener.onCancel(event); 39 | break; 40 | } 41 | return true; 42 | } 43 | }); 44 | } 45 | 46 | private class KeyboardGestureListener implements GestureDetector.OnGestureListener { 47 | private final Runnable mRepeatRunnable = new Runnable() { 48 | @Override 49 | public void run() { 50 | if (mRepeatable && mRepeating) { 51 | mOnKeyAction.run(); 52 | mLayer.performFeedback(); 53 | mView.postDelayed(mRepeatRunnable, 50); 54 | } 55 | } 56 | }; 57 | 58 | private boolean mRepeating = false; 59 | 60 | @Override 61 | public boolean onDown(MotionEvent e) { 62 | mRepeating = false; 63 | mView.removeCallbacks(mRepeatRunnable); 64 | mView.setPressed(true); 65 | return true; 66 | } 67 | 68 | public void onUp(MotionEvent e) { 69 | mRepeating = false; 70 | mView.removeCallbacks(mRepeatRunnable); 71 | mView.setPressed(false); 72 | } 73 | 74 | public void onCancel(MotionEvent e) { 75 | mRepeating = false; 76 | mView.removeCallbacks(mRepeatRunnable); 77 | mView.setPressed(false); 78 | } 79 | 80 | @Override 81 | public void onShowPress(MotionEvent e) { 82 | } 83 | 84 | @Override 85 | public boolean onSingleTapUp(MotionEvent e) { 86 | mOnKeyAction.run(); 87 | mLayer.performFeedback(); 88 | return true; 89 | } 90 | 91 | @Override 92 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 93 | mRepeating = false; 94 | mView.removeCallbacks(mRepeatRunnable); 95 | return false; 96 | } 97 | 98 | @Override 99 | public void onLongPress(MotionEvent e) { 100 | if (mRepeatable) { 101 | mRepeating = true; 102 | mView.post(mRepeatRunnable); 103 | } 104 | } 105 | 106 | @Override 107 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 108 | return false; 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/ActivityHolder.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | import android.text.TextUtils; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | 11 | import java.lang.ref.WeakReference; 12 | import java.util.LinkedList; 13 | import java.util.List; 14 | 15 | import per.goweii.layer.core.utils.Utils; 16 | 17 | public final class ActivityHolder { 18 | private final List> mActivityStack = new LinkedList<>(); 19 | 20 | public ActivityHolder(@NonNull Application application) { 21 | application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksImpl()); 22 | } 23 | 24 | @NonNull 25 | public Activity requireActivity(@NonNull Class clazz) { 26 | Activity activity = getActivity(clazz); 27 | Utils.requireNonNull(activity, "请确保有已启动的Activity实例:" + clazz.getName()); 28 | return activity; 29 | } 30 | 31 | @Nullable 32 | public Activity getActivity(@NonNull Class clazz) { 33 | final List> stack = mActivityStack; 34 | if (stack.isEmpty()) return null; 35 | final int size = stack.size(); 36 | Activity find = null; 37 | for (int i = size - 1; i >= 0; i--) { 38 | WeakReference ref = stack.get(i); 39 | final Activity activity = ref.get(); 40 | if (activity == null) { 41 | ref.clear(); 42 | stack.remove(i); 43 | } else { 44 | if (find == null) { 45 | if (TextUtils.equals(clazz.getName(), activity.getClass().getName())) { 46 | find = activity; 47 | } 48 | } 49 | } 50 | } 51 | return find; 52 | } 53 | 54 | @NonNull 55 | public Activity requireCurrentActivity() { 56 | Activity activity = getCurrentActivity(); 57 | Utils.requireNonNull(activity, "请确保有已启动的Activity实例"); 58 | return activity; 59 | } 60 | 61 | @Nullable 62 | public Activity getCurrentActivity() { 63 | final List> stack = mActivityStack; 64 | if (stack.isEmpty()) return null; 65 | final int size = stack.size(); 66 | for (int i = size - 1; i >= 0; i--) { 67 | WeakReference ref = stack.get(i); 68 | if (ref.get() == null) { 69 | ref.clear(); 70 | stack.remove(i); 71 | } 72 | } 73 | if (stack.isEmpty()) return null; 74 | return stack.get(stack.size() - 1).get(); 75 | } 76 | 77 | private class ActivityLifecycleCallbacksImpl implements Application.ActivityLifecycleCallbacks { 78 | @Override 79 | public void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) { 80 | mActivityStack.add(new WeakReference<>(activity)); 81 | } 82 | 83 | @Override 84 | public void onActivityStarted(@NonNull Activity activity) { 85 | } 86 | 87 | @Override 88 | public void onActivityResumed(@NonNull Activity activity) { 89 | } 90 | 91 | @Override 92 | public void onActivityPaused(@NonNull Activity activity) { 93 | } 94 | 95 | @Override 96 | public void onActivityStopped(@NonNull Activity activity) { 97 | } 98 | 99 | @Override 100 | public void onActivityDestroyed(@NonNull Activity activity) { 101 | final int size = mActivityStack.size(); 102 | for (int i = size - 1; i >= 0; i--) { 103 | WeakReference ref = mActivityStack.get(i); 104 | if (ref.get() == null || ref.get() == activity) { 105 | ref.clear(); 106 | mActivityStack.remove(i); 107 | } 108 | } 109 | } 110 | 111 | @Override 112 | public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /layer-visualeffectview/src/main/java/per/goweii/layer/visualeffectview/BackdropBlurView.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.visualeffectview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Path; 6 | import android.graphics.RectF; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | import androidx.annotation.NonNull; 11 | 12 | import java.util.Arrays; 13 | 14 | import per.goweii.visualeffect.blur.BlurEffect; 15 | import per.goweii.visualeffect.blur.RSBlurEffect; 16 | import per.goweii.visualeffect.view.BackdropVisualEffectFrameLayout; 17 | import per.goweii.visualeffect.view.OutlineBuilder; 18 | 19 | public class BackdropBlurView extends BackdropVisualEffectFrameLayout { 20 | private final RoundedOutlineBuilder mOutlineBuilder = new RoundedOutlineBuilder(); 21 | 22 | private float mCornerRadius = 0F; 23 | private float mBlurRadius = 8F; 24 | private float mBlurPercent = 0F; 25 | 26 | public BackdropBlurView(Context context) { 27 | this(context, null); 28 | } 29 | 30 | public BackdropBlurView(Context context, AttributeSet attrs) { 31 | this(context, attrs, 0); 32 | } 33 | 34 | public BackdropBlurView(Context context, AttributeSet attrs, int defStyleAttr) { 35 | super(context, attrs, defStyleAttr); 36 | setShowDebugInfo(false); 37 | } 38 | 39 | @Override 40 | public void draw(@NonNull Canvas canvas) { 41 | float simple = getSimpleSize(); 42 | float radius; 43 | if (mBlurPercent > 0) { 44 | radius = Math.min(getWidth(), getHeight()) * mBlurPercent; 45 | mBlurPercent = 0F; 46 | } else { 47 | radius = mBlurRadius; 48 | } 49 | if (radius > 25) { 50 | simple = simple * (radius / 25); 51 | radius = 25; 52 | } else if (radius < 0) { 53 | radius = 0; 54 | } 55 | if (mBlurRadius != radius) { 56 | mBlurRadius = radius; 57 | } 58 | if (getSimpleSize() != simple) { 59 | setSimpleSize(simple); 60 | } 61 | if (radius == 0) { 62 | if (getVisualEffect() != null) { 63 | setVisualEffect(null); 64 | } 65 | } else { 66 | if (!(getVisualEffect() instanceof BlurEffect) || ((BlurEffect) getVisualEffect()).getRadius() != radius) { 67 | setVisualEffect(new RSBlurEffect(getContext(), radius)); 68 | } 69 | } 70 | super.draw(canvas); 71 | } 72 | 73 | public void setCornerRadius(float cornerRadius) { 74 | if (mCornerRadius != cornerRadius) { 75 | mCornerRadius = cornerRadius; 76 | if (mCornerRadius == 0) { 77 | if (getOutlineBuilder() != null) { 78 | setOutlineBuilder(null); 79 | } 80 | } else { 81 | if (getOutlineBuilder() == null) { 82 | setOutlineBuilder(mOutlineBuilder); 83 | } else { 84 | mOutlineBuilder.invalidateOutline(); 85 | } 86 | } 87 | } 88 | } 89 | 90 | public void setBlurPercent(float blurPercent) { 91 | if (mBlurPercent != blurPercent) { 92 | mBlurPercent = blurPercent; 93 | invalidate(); 94 | } 95 | } 96 | 97 | public void setBlurRadius(float blurRadius) { 98 | if (mBlurRadius != blurRadius) { 99 | mBlurRadius = blurRadius; 100 | invalidate(); 101 | } 102 | } 103 | 104 | private class RoundedOutlineBuilder extends OutlineBuilder { 105 | private final RectF rect = new RectF(); 106 | private final float[] radii = new float[8]; 107 | 108 | @Override 109 | public void buildOutline(@NonNull View view, @NonNull Path path) { 110 | float minSide = Math.min(view.getWidth(), view.getHeight()); 111 | float r = Math.min(mCornerRadius, minSide / 2F); 112 | Arrays.fill(radii, r); 113 | rect.set(0, 0, view.getWidth(), view.getHeight()); 114 | path.addRoundRect(rect, radii, Path.Direction.CW); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /layer-core-ktx/src/main/java/per/goweii/layer/core/ktx/Layer.kt: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.ktx 2 | 3 | import android.animation.Animator 4 | import android.view.View 5 | import androidx.annotation.IdRes 6 | import per.goweii.layer.core.Layer 7 | import per.goweii.layer.core.listener.DefaultOnDismissListener 8 | import per.goweii.layer.core.listener.DefaultOnShowListener 9 | import per.goweii.layer.core.listener.DefaultOnVisibleChangedListener 10 | 11 | fun T.onClick(@IdRes viewId: Int, onClickListener: T.(view: View) -> Unit) = 12 | this.apply { 13 | this.addOnClickListener({ _, v -> this.onClickListener(v) }, viewId) 14 | } 15 | 16 | fun T.onClickToDismiss( 17 | @IdRes viewId: Int, 18 | onClickListener: (T.(view: View) -> Unit)? = null 19 | ) = this.apply { 20 | onClickListener?.let { 21 | this.addOnClickToDismissListener({ _, v -> this.it(v) }, viewId) 22 | } ?: addOnClickToDismissListener(null, viewId) 23 | } 24 | 25 | fun T.onLongClick(@IdRes viewId: Int, onLongClickListener: T.(view: View) -> Boolean) = 26 | this.apply { 27 | this.addOnLongClickListener({ _, v -> this.onLongClickListener(v) }, viewId) 28 | } 29 | 30 | fun T.onLongClickToDismiss( 31 | @IdRes viewId: Int, 32 | onLongClickListener: (T.(view: View) -> Boolean)? = null 33 | ) = this.apply { 34 | onLongClickListener?.let { 35 | this.addOnLongClickToDismissListener({ _, v -> this.it(v) }, viewId) 36 | } ?: addOnLongClickToDismissListener(null, viewId) 37 | } 38 | 39 | fun T.onBindData(dataBinder: T.() -> Unit) = this.apply { 40 | this.addOnBindDataListener { this.dataBinder() } 41 | } 42 | 43 | fun T.onInitialize(onInitialize: T.() -> Unit) = this.apply { 44 | this.addOnInitializeListener { this.onInitialize() } 45 | } 46 | 47 | fun T.onShow(onShow: T.() -> Unit) = this.apply { 48 | this.addOnVisibleChangeListener(object : DefaultOnVisibleChangedListener() { 49 | override fun onShow(layer: Layer) { 50 | onShow.invoke(this@apply) 51 | } 52 | }) 53 | } 54 | 55 | fun T.onDismiss(onDismiss: T.() -> Unit) = this.apply { 56 | this.addOnVisibleChangeListener(object : DefaultOnVisibleChangedListener() { 57 | override fun onDismiss(layer: Layer) { 58 | onDismiss.invoke(this@apply) 59 | } 60 | }) 61 | } 62 | 63 | fun T.onPreShow(onPreShow: T.() -> Unit) = this.apply { 64 | this.addOnShowListener(object : DefaultOnShowListener() { 65 | override fun onPreShow(layer: Layer) { 66 | this@apply.onPreShow() 67 | } 68 | }) 69 | } 70 | 71 | fun T.onPostShow(onPostShow: T.() -> Unit) = this.apply { 72 | this.addOnShowListener(object : DefaultOnShowListener() { 73 | override fun onPostShow(layer: Layer) { 74 | this@apply.onPostShow() 75 | } 76 | }) 77 | } 78 | 79 | fun T.onPreDismiss(onPreDismiss: T.() -> Unit) = this.apply { 80 | this.addOnDismissListener(object : DefaultOnDismissListener() { 81 | override fun onPreDismiss(layer: Layer) { 82 | this@apply.onPreDismiss() 83 | } 84 | }) 85 | } 86 | 87 | fun T.onPostDismiss(onPostDismiss: T.() -> Unit) = this.apply { 88 | this.addOnDismissListener(object : DefaultOnDismissListener() { 89 | override fun onPostDismiss(layer: Layer) { 90 | this@apply.onPostDismiss() 91 | } 92 | }) 93 | } 94 | 95 | fun T.animator( 96 | onIn: T.(target: View) -> R, 97 | onOut: T.(target: View) -> R 98 | ) = this.apply { 99 | this.setAnimator(object : Layer.AnimatorCreator { 100 | override fun createInAnimator(target: View): Animator? { 101 | return onIn.invoke(this@apply, target) 102 | } 103 | 104 | override fun createOutAnimator(target: View): Animator? { 105 | return onOut.invoke(this@apply, target) 106 | } 107 | }) 108 | } 109 | 110 | fun T.animator(creator: Layer.AnimatorCreator) = this.apply { 111 | this.setAnimator(creator) 112 | } 113 | 114 | fun T.interceptKeyEvent(enable: Boolean) = this.apply { 115 | this.isInterceptKeyEvent = enable 116 | } 117 | 118 | fun T.cancelableOnClickKeyBack(enable: Boolean) = this.apply { 119 | this.isCancelableOnKeyBack = enable 120 | } -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/anim/AnimStyle.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.anim; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorSet; 5 | import android.view.View; 6 | import android.view.animation.AccelerateInterpolator; 7 | import android.view.animation.DecelerateInterpolator; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | import per.goweii.layer.core.Layer; 13 | 14 | public enum AnimStyle implements Layer.AnimatorCreator { 15 | NONE, 16 | ALPHA, 17 | ZOOM, 18 | ZOOM_ALPHA, 19 | BOTTOM, 20 | BOTTOM_ALPHA, 21 | TOP, 22 | TOP_ALPHA, 23 | LEFT, 24 | LEFT_ALPHA, 25 | RIGHT, 26 | RIGHT_ALPHA, 27 | BOTTOM_ZOOM_ALPHA, 28 | ; 29 | 30 | @Nullable 31 | public Animator createInAnimator(@NonNull View target) { 32 | switch (this) { 33 | default: 34 | case NONE: 35 | return null; 36 | case ALPHA: 37 | return AnimatorHelper.createAlphaInAnim(target); 38 | case ZOOM: 39 | return AnimatorHelper.createZoomInAnim(target); 40 | case ZOOM_ALPHA: 41 | return AnimatorHelper.createZoomAlphaInAnim(target); 42 | case BOTTOM: 43 | return AnimatorHelper.createBottomInAnim(target); 44 | case BOTTOM_ALPHA: 45 | return AnimatorHelper.createBottomAlphaInAnim(target); 46 | case TOP: 47 | return AnimatorHelper.createTopInAnim(target); 48 | case TOP_ALPHA: 49 | return AnimatorHelper.createTopAlphaInAnim(target); 50 | case LEFT: 51 | return AnimatorHelper.createLeftInAnim(target); 52 | case LEFT_ALPHA: 53 | return AnimatorHelper.createLeftAlphaInAnim(target); 54 | case RIGHT: 55 | return AnimatorHelper.createRightInAnim(target); 56 | case RIGHT_ALPHA: 57 | return AnimatorHelper.createRightAlphaInAnim(target); 58 | case BOTTOM_ZOOM_ALPHA: 59 | AnimatorSet set = new AnimatorSet(); 60 | Animator a1 = AnimatorHelper.createBottomAlphaInAnim(target, 0.3F); 61 | a1.setInterpolator(new DecelerateInterpolator(2.5f)); 62 | Animator a2 = AnimatorHelper.createZoomAlphaInAnim(target, 0.9F); 63 | a2.setInterpolator(new DecelerateInterpolator(1.5f)); 64 | set.playTogether(a1, a2); 65 | return set; 66 | } 67 | } 68 | 69 | @Nullable 70 | public Animator createOutAnimator(@NonNull View target) { 71 | switch (this) { 72 | default: 73 | case NONE: 74 | return null; 75 | case ALPHA: 76 | return AnimatorHelper.createAlphaOutAnim(target); 77 | case ZOOM: 78 | return AnimatorHelper.createZoomOutAnim(target); 79 | case ZOOM_ALPHA: 80 | return AnimatorHelper.createZoomAlphaOutAnim(target); 81 | case BOTTOM: 82 | return AnimatorHelper.createBottomOutAnim(target); 83 | case BOTTOM_ALPHA: 84 | return AnimatorHelper.createBottomAlphaOutAnim(target); 85 | case TOP: 86 | return AnimatorHelper.createTopOutAnim(target); 87 | case TOP_ALPHA: 88 | return AnimatorHelper.createTopAlphaOutAnim(target); 89 | case LEFT: 90 | return AnimatorHelper.createLeftOutAnim(target); 91 | case LEFT_ALPHA: 92 | return AnimatorHelper.createLeftAlphaOutAnim(target); 93 | case RIGHT: 94 | return AnimatorHelper.createRightOutAnim(target); 95 | case RIGHT_ALPHA: 96 | return AnimatorHelper.createRightAlphaOutAnim(target); 97 | case BOTTOM_ZOOM_ALPHA: 98 | AnimatorSet set = new AnimatorSet(); 99 | Animator a1 = AnimatorHelper.createBottomAlphaOutAnim(target, 0.3F); 100 | a1.setInterpolator(new AccelerateInterpolator(2.5f)); 101 | Animator a2 = AnimatorHelper.createZoomAlphaOutAnim(target, 0.9F); 102 | a2.setInterpolator(new AccelerateInterpolator(1.5f)); 103 | set.playTogether(a1, a2); 104 | return set; 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /simple/src/main/res/layout/bottom_sheet.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 24 | 25 | 29 | 30 | 35 | 36 | 40 | 41 | 44 | 45 | 48 | 49 | 52 | 53 | 56 | 57 | 60 | 61 | 64 | 65 | 68 | 69 | 72 | 73 | 76 | 77 | 80 | 81 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 95 | 96 | 101 | 102 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /layer-design-cupertino/src/main/res/layout/layer_design_cupertino_notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 24 | 25 | 37 | 38 | 51 | 52 | 64 | 65 | 66 | 67 | 80 | 81 | 92 | 93 | -------------------------------------------------------------------------------- /layer-core/src/main/java/per/goweii/layer/core/listener/WindowCallbackDelegate.java: -------------------------------------------------------------------------------- 1 | package per.goweii.layer.core.listener; 2 | 3 | import android.os.Build; 4 | import android.view.ActionMode; 5 | import android.view.KeyEvent; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | import android.view.MotionEvent; 9 | import android.view.SearchEvent; 10 | import android.view.View; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | import android.view.accessibility.AccessibilityEvent; 14 | 15 | import androidx.annotation.NonNull; 16 | import androidx.annotation.Nullable; 17 | import androidx.annotation.RequiresApi; 18 | 19 | public class WindowCallbackDelegate implements Window.Callback { 20 | private final Window.Callback mOldCallback; 21 | 22 | public WindowCallbackDelegate(@NonNull Window.Callback callback) { 23 | mOldCallback = callback; 24 | } 25 | 26 | @Override 27 | public boolean dispatchKeyEvent(KeyEvent event) { 28 | return mOldCallback.dispatchKeyEvent(event); 29 | } 30 | 31 | @Override 32 | public boolean dispatchKeyShortcutEvent(KeyEvent event) { 33 | return mOldCallback.dispatchKeyShortcutEvent(event); 34 | } 35 | 36 | @Override 37 | public boolean dispatchTouchEvent(MotionEvent event) { 38 | return mOldCallback.dispatchTouchEvent(event); 39 | } 40 | 41 | @Override 42 | public boolean dispatchTrackballEvent(MotionEvent event) { 43 | return mOldCallback.dispatchTrackballEvent(event); 44 | } 45 | 46 | @Override 47 | public boolean dispatchGenericMotionEvent(MotionEvent event) { 48 | return mOldCallback.dispatchGenericMotionEvent(event); 49 | } 50 | 51 | @Override 52 | public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 53 | return mOldCallback.dispatchPopulateAccessibilityEvent(event); 54 | } 55 | 56 | @Nullable 57 | @Override 58 | public View onCreatePanelView(int featureId) { 59 | return mOldCallback.onCreatePanelView(featureId); 60 | } 61 | 62 | @Override 63 | public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) { 64 | return mOldCallback.onCreatePanelMenu(featureId, menu); 65 | } 66 | 67 | @Override 68 | public boolean onPreparePanel(int featureId, @Nullable View view, @NonNull Menu menu) { 69 | return mOldCallback.onPreparePanel(featureId, view, menu); 70 | } 71 | 72 | @Override 73 | public boolean onMenuOpened(int featureId, @NonNull Menu menu) { 74 | return mOldCallback.onMenuOpened(featureId, menu); 75 | } 76 | 77 | @Override 78 | public boolean onMenuItemSelected(int featureId, @NonNull MenuItem item) { 79 | return mOldCallback.onMenuItemSelected(featureId, item); 80 | } 81 | 82 | @Override 83 | public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) { 84 | mOldCallback.onWindowAttributesChanged(attrs); 85 | } 86 | 87 | @Override 88 | public void onContentChanged() { 89 | mOldCallback.onContentChanged(); 90 | } 91 | 92 | @Override 93 | public void onWindowFocusChanged(boolean hasFocus) { 94 | mOldCallback.onWindowFocusChanged(hasFocus); 95 | } 96 | 97 | @Override 98 | public void onAttachedToWindow() { 99 | mOldCallback.onAttachedToWindow(); 100 | } 101 | 102 | @Override 103 | public void onDetachedFromWindow() { 104 | mOldCallback.onDetachedFromWindow(); 105 | } 106 | 107 | @Override 108 | public void onPanelClosed(int featureId, @NonNull Menu menu) { 109 | mOldCallback.onPanelClosed(featureId, menu); 110 | } 111 | 112 | @Override 113 | public boolean onSearchRequested() { 114 | return mOldCallback.onSearchRequested(); 115 | } 116 | 117 | @RequiresApi(api = Build.VERSION_CODES.M) 118 | @Override 119 | public boolean onSearchRequested(SearchEvent searchEvent) { 120 | return mOldCallback.onSearchRequested(searchEvent); 121 | } 122 | 123 | @Nullable 124 | @Override 125 | public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) { 126 | return mOldCallback.onWindowStartingActionMode(callback); 127 | } 128 | 129 | @RequiresApi(api = Build.VERSION_CODES.M) 130 | @Nullable 131 | @Override 132 | public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) { 133 | return mOldCallback.onWindowStartingActionMode(callback, type); 134 | } 135 | 136 | @Override 137 | public void onActionModeStarted(ActionMode mode) { 138 | mOldCallback.onActionModeStarted(mode); 139 | } 140 | 141 | @Override 142 | public void onActionModeFinished(ActionMode mode) { 143 | mOldCallback.onActionModeFinished(mode); 144 | } 145 | } 146 | --------------------------------------------------------------------------------