├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── Bug_report.md
│ └── Feature_request.md
├── pull_request_template.md
└── workflows
│ └── android.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── README_OLD.md
├── RELEASE_NOTES.md
├── art
├── basic.png
├── basic_list.png
├── basic_with_buttons.png
├── bottomsheet_customview.png
├── bottomsheet_peekheight.gif
├── checkbox_prompt.png
├── color_chooser.png
├── color_chooser_sub.png
├── custom_argb.png
├── custom_view.png
├── customtheme.png
├── datepicker.png
├── datetimepicker.png
├── file_chooser.png
├── file_emptytext.png
├── file_folder_creation.png
├── icon.png
├── input.png
├── input_max_length.png
├── lightanddarkthemes.png
├── multi_choice_list.png
├── showcase4.png
├── single_choice_list.png
├── stacked_buttons.png
└── timepicker.png
├── bottomsheets
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ └── bottomsheets
│ │ ├── BottomSheet.kt
│ │ ├── BottomSheets.kt
│ │ ├── GridIconDialogAdapter.kt
│ │ ├── GridItem.kt
│ │ ├── HeightMatchesWidthImageView.kt
│ │ └── Util.kt
│ ├── res-public
│ └── values
│ │ └── integers.xml
│ └── res
│ ├── layout
│ ├── md_dialog_base_bottomsheet.xml
│ ├── md_dialog_base_no_buttons.xml
│ └── md_griditem.xml
│ ├── values-land
│ └── integers.xml
│ ├── values-large-land
│ └── integers.xml
│ ├── values-large
│ └── integers.xml
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── integers.xml
│ └── styles.xml
├── build.gradle
├── color
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ └── color
│ │ ├── ColorGridAdapter.kt
│ │ ├── ColorPagerAdapter.kt
│ │ ├── ColorPalette.kt
│ │ ├── CustomPageViewSet.kt
│ │ ├── DialogColorChooserExt.kt
│ │ ├── utils
│ │ ├── ColorExt.kt
│ │ └── ViewExt.kt
│ │ └── view
│ │ ├── ColorCircleView.kt
│ │ ├── ObservableEditText.kt
│ │ ├── ObservableSeekBar.kt
│ │ ├── PreviewFrameView.kt
│ │ ├── SeekBarGroupLayout.kt
│ │ └── WrapContentViewPager.kt
│ ├── res-public
│ └── values
│ │ └── public.xml
│ └── res
│ ├── drawable-nodpi
│ ├── transparent_rect.png
│ └── transparentgrid.png
│ ├── drawable
│ ├── icon_back_black.xml
│ ├── icon_back_white.xml
│ ├── icon_checkmark_black.xml
│ ├── icon_checkmark_white.xml
│ ├── icon_custom_black.xml
│ ├── icon_custom_white.xml
│ └── transparent_rect_repeat.xml
│ ├── layout-land
│ ├── md_color_chooser_base_argb.xml
│ └── md_color_chooser_base_pager.xml
│ ├── layout
│ ├── md_color_chooser_base_argb.xml
│ ├── md_color_chooser_base_grid.xml
│ ├── md_color_chooser_base_pager.xml
│ ├── md_color_chooser_preview_frame.xml
│ ├── md_color_grid_item.xml
│ └── md_color_grid_item_go_up.xml
│ ├── values-land
│ ├── dimens.xml
│ └── integers.xml
│ ├── values-large-land
│ └── integers.xml
│ ├── values-large
│ └── integers.xml
│ └── values
│ ├── dimens.xml
│ ├── integers.xml
│ └── styles.xml
├── core
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ ├── DialogBehavior.kt
│ │ ├── LayoutMode.kt
│ │ ├── MaterialDialog.kt
│ │ ├── Theme.kt
│ │ ├── WhichButton.kt
│ │ ├── actions
│ │ └── DialogActionExt.kt
│ │ ├── callbacks
│ │ └── DialogCallbackExt.kt
│ │ ├── checkbox
│ │ └── DialogCheckboxExt.kt
│ │ ├── customview
│ │ └── DialogCustomViewExt.kt
│ │ ├── internal
│ │ ├── button
│ │ │ ├── DialogActionButton.kt
│ │ │ └── DialogActionButtonLayout.kt
│ │ ├── list
│ │ │ ├── AdapterPayload.kt
│ │ │ ├── DialogAdapter.kt
│ │ │ ├── DialogRecyclerView.kt
│ │ │ ├── MultiChoiceDialogAdapter.kt
│ │ │ ├── PlainListDialogAdapter.kt
│ │ │ └── SingleChoiceDialogAdapter.kt
│ │ ├── main
│ │ │ ├── BaseSubLayout.kt
│ │ │ ├── DialogLayout.kt
│ │ │ ├── DialogScrollView.kt
│ │ │ └── DialogTitleLayout.kt
│ │ ├── message
│ │ │ ├── CustomUrlSpan.kt
│ │ │ ├── DialogContentLayout.kt
│ │ │ └── LinkTransformationMethod.kt
│ │ └── rtl
│ │ │ └── RtlTextView.kt
│ │ ├── list
│ │ ├── DialogListExt.kt
│ │ ├── DialogMultiChoiceExt.kt
│ │ ├── DialogSingleChoiceExt.kt
│ │ └── ListCallbacks.kt
│ │ ├── message
│ │ └── DialogMessageSettings.kt
│ │ └── utils
│ │ ├── Arrays.kt
│ │ ├── Colors.kt
│ │ ├── Dialogs.kt
│ │ ├── Dimens.kt
│ │ ├── Fonts.kt
│ │ ├── IntArrays.kt
│ │ ├── MDUtil.kt
│ │ └── Views.kt
│ ├── res-public
│ └── values
│ │ └── public.xml
│ └── res
│ ├── anim
│ ├── decelerate_cubic.xml
│ ├── popup_enter.xml
│ └── popup_exit.xml
│ ├── color
│ └── md_list_item_textcolor.xml
│ ├── drawable-v21
│ ├── md_btn_selector.xml
│ ├── md_btn_selector_dark.xml
│ ├── md_btn_shape.xml
│ ├── md_item_selector.xml
│ ├── md_item_selector_dark.xml
│ └── md_item_shape.xml
│ ├── drawable
│ ├── md_btn_selected.xml
│ ├── md_btn_selected_dark.xml
│ ├── md_btn_selector.xml
│ ├── md_btn_selector_dark.xml
│ ├── md_item_selected.xml
│ ├── md_item_selected_dark.xml
│ ├── md_item_selector.xml
│ ├── md_item_selector_dark.xml
│ ├── md_nav_back.xml
│ └── md_transparent.xml
│ ├── layout
│ ├── md_dialog_base.xml
│ ├── md_dialog_stub_buttons.xml
│ ├── md_dialog_stub_message.xml
│ ├── md_dialog_stub_recyclerview.xml
│ ├── md_dialog_stub_scrollview.xml
│ ├── md_dialog_stub_title.xml
│ ├── md_listitem.xml
│ ├── md_listitem_multichoice.xml
│ └── md_listitem_singlechoice.xml
│ ├── values-sw600dp
│ └── dimens.xml
│ ├── values-sw720dp-land
│ └── dimens.xml
│ ├── values-sw720dp
│ └── dimens.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ └── styles.xml
├── datetime
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ └── datetime
│ │ ├── DatePickerExt.kt
│ │ ├── DateTimePickerExt.kt
│ │ ├── TimePickerExt.kt
│ │ ├── internal
│ │ ├── DateTimePickerAdapter.kt
│ │ ├── TimeChangeListener.kt
│ │ └── WrapContentViewPager.kt
│ │ └── utils
│ │ ├── DateTimeExt.kt
│ │ └── ViewExt.kt
│ ├── res-public
│ └── values
│ │ └── public.xml
│ └── res
│ ├── layout
│ ├── md_datetime_picker_date.xml
│ ├── md_datetime_picker_pager.xml
│ └── md_datetime_picker_time.xml
│ └── values
│ └── dimens.xml
├── dependencies.gradle
├── documentation
├── BOTTOMSHEETS.md
├── COLOR.md
├── CORE.md
├── DATETIME.md
├── FILES.md
├── INPUT.md
└── LIFECYCLE.md
├── files
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ └── files
│ │ ├── DialogFileChooserExt.kt
│ │ ├── DialogFolderChooserExt.kt
│ │ ├── FileChooserAdapter.kt
│ │ └── util
│ │ ├── ContextExt.kt
│ │ ├── FilesUtilExt.kt
│ │ └── ViewExt.kt
│ ├── res-public
│ └── values
│ │ └── public.xml
│ └── res
│ ├── drawable
│ ├── icon_file_dark.xml
│ ├── icon_file_light.xml
│ ├── icon_folder_dark.xml
│ ├── icon_folder_light.xml
│ ├── icon_new_folder_dark.xml
│ ├── icon_new_folder_light.xml
│ ├── icon_return_dark.xml
│ └── icon_return_light.xml
│ ├── layout
│ ├── md_file_chooser_base.xml
│ └── md_file_chooser_item.xml
│ └── values
│ ├── dimens.xml
│ └── strings.xml
├── gradle.properties
├── gradle
├── android_application_config.gradle
├── android_common_config.gradle
├── android_library_config.gradle
├── android_publish_mavencentral.gradle
├── spotless_plugin_config.gradle
├── versions_plugin_config.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── input
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── afollestad
│ │ └── materialdialogs
│ │ └── input
│ │ ├── DialogInputExt.kt
│ │ └── InputUtilExt.kt
│ ├── res-public
│ └── values
│ │ └── public.xml
│ └── res
│ ├── layout
│ └── md_dialog_stub_input.xml
│ └── values
│ └── dimens.xml
├── lifecycle
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── afollestad
│ └── materialdialogs
│ └── lifecycle
│ ├── DialogLifecycleObserver.kt
│ └── LifecycleExt.kt
├── sample
├── .gitignore
├── build.gradle
├── ic_web.png
├── sample.apk
└── src
│ ├── debug
│ └── java
│ │ └── com
│ │ └── afollestad
│ │ └── materialdialogssample
│ │ └── SampleApp.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── afollestad
│ │ │ └── materialdialogssample
│ │ │ ├── Debouncer.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── Utils.kt
│ └── res
│ │ ├── drawable
│ │ └── ic_icon_android.xml
│ │ ├── font
│ │ ├── raleway_bold.ttf
│ │ ├── raleway_medium.ttf
│ │ └── raleway_semibold.ttf
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── custom_view.xml
│ │ └── custom_view_webview.xml
│ │ ├── menu
│ │ └── main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── values-v21
│ │ └── styles_parent.xml
│ │ └── values
│ │ ├── arrays.xml
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ ├── styles.xml
│ │ └── styles_parent.xml
│ └── release
│ └── java
│ └── com
│ └── afollestad
│ └── materialdialogssample
│ └── SampleApp.kt
├── settings.gradle
└── spotless.license.kt
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.kt]
2 | indent_size = 2
3 | continuation_indent_size=4
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Something is crashing or not working as intended
4 | labels: bug
5 |
6 | ---
7 |
8 | *Please consider making a Pull Request if you are capable of doing so. Note that versions before 2.0.0 are no longer supported.*
9 |
10 | **Library Version:**
11 |
12 | 2.x.x
13 |
14 | **Affected Device(s):**
15 |
16 | Google Pixel 3 XL with Android 9.0
17 |
18 | **Describe the Bug:**
19 |
20 | A clear description of what is the bug is.
21 |
22 | **To Reproduce:**
23 | 1.
24 | 2.
25 | 3.
26 |
27 | **Expected Behavior:**
28 |
29 | A clear description of what you expected to happen.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | labels: improvement
5 |
6 | ---
7 |
8 | *Please consider making a Pull Request if you are capable of doing so. Note that versions before 2.0.0 are no longer supported.*
9 |
10 | **What module does this apply to?**
11 |
12 | Core? Input? Files? Color?
13 |
14 | **Description what you'd like to happen:**
15 |
16 | A clear description if the feature or behavior you'd like implemented.
17 |
18 | **Describe alternatives you've considered:**
19 |
20 | A clear description of any alternative solutions you've considered.
21 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ### Guidelines
2 |
3 | 1. You must run the `spotlessApply` task before commiting, either through Android Studio or with `./gradlew spotlessApply`.
4 | 2. A PR should be focused and contained. If you are changing multiple unrelated things, they should be in separate PRs.
5 | 3. A PR should fix a bug or solve a problem - something that only you would use is not necessarily something that should be published.
6 | 4. Give your PR a detailed title and description - look over your code one last time before actually creating the PR. Give it a self-review.
7 |
8 | **If you do not follow the guidelines, your PR will be rejected.**
9 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v1
12 | - name: set up JDK 1.8
13 | uses: actions/setup-java@v1
14 | with:
15 | java-version: 1.8
16 | - name: Build with Gradle
17 | run: ./gradlew build check
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io
2 |
3 | ### Android ###
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Log Files
26 | *.log
27 |
28 |
29 | ### Intellij ###
30 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
31 |
32 | *.iml
33 |
34 | ## Directory-based project format:
35 | .idea/
36 | # if you remove the above rule, at least ignore the following:
37 |
38 | # User-specific stuff:
39 | # .idea/workspace.xml
40 | # .idea/tasks.xml
41 | # .idea/dictionaries
42 |
43 | # Sensitive or high-churn files:
44 | # .idea/dataSources.ids
45 | # .idea/dataSources.xml
46 | # .idea/sqlDataSources.xml
47 | # .idea/dynamic.xml
48 | # .idea/uiDesigner.xml
49 |
50 | # Gradle:
51 | # .idea/gradle.xml
52 | # .idea/libraries
53 |
54 | # Mongo Explorer plugin:
55 | # .idea/mongoSettings.xml
56 |
57 | ## File-based project format:
58 | *.ipr
59 | *.iws
60 |
61 | ## Plugin-specific files:
62 |
63 | # IntelliJ
64 | out/
65 |
66 | # mpeltonen/sbt-idea plugin
67 | .idea_modules/
68 |
69 | # JIRA plugin
70 | atlassian-ide-plugin.xml
71 |
72 | # Crashlytics plugin (for Android Studio and IntelliJ)
73 | com_crashlytics_export_strings.xml
74 |
75 | # Ignore Gradle GUI config
76 | gradle-app.setting
77 |
78 | # Mobile Tools for Java (J2ME)
79 | .mtj.tmp/
80 |
81 | # Package Files #
82 | *.war
83 | *.ear
84 |
85 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
86 | hs_err_pid*
87 |
88 | *.DS_Store
89 |
90 | *.jks
--------------------------------------------------------------------------------
/RELEASE_NOTES.md:
--------------------------------------------------------------------------------
1 | 3.3.0
2 |
3 | * Added `md_line_spacing_body` global theme attribute, which sets a global default for message line
4 | spacing. See #1903.
5 | * Added some assertions and sanity checks to avoid choice list adapter out of bounds crashes.
6 | See #1906.
7 | * Corner radius should not apply to the bottom of bottom sheet dialogs. See #1941.
8 | * Fix dialog titles being cut off with custom fonts. See #1936.
9 | * If `noVerticalPadding` is set with `customView(...)``, padding is not applied to the bottom of
10 | the content `ScrollView` if `scrollable` is enabled. Resolves #1834.
11 | * Input dialog styling is not enforced by the dialog. The global default for `TextInputLayout`
12 | (`textInputStyle`) is used instead. See #1857.
--------------------------------------------------------------------------------
/art/basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/basic.png
--------------------------------------------------------------------------------
/art/basic_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/basic_list.png
--------------------------------------------------------------------------------
/art/basic_with_buttons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/basic_with_buttons.png
--------------------------------------------------------------------------------
/art/bottomsheet_customview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/bottomsheet_customview.png
--------------------------------------------------------------------------------
/art/bottomsheet_peekheight.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/bottomsheet_peekheight.gif
--------------------------------------------------------------------------------
/art/checkbox_prompt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/checkbox_prompt.png
--------------------------------------------------------------------------------
/art/color_chooser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/color_chooser.png
--------------------------------------------------------------------------------
/art/color_chooser_sub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/color_chooser_sub.png
--------------------------------------------------------------------------------
/art/custom_argb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/custom_argb.png
--------------------------------------------------------------------------------
/art/custom_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/custom_view.png
--------------------------------------------------------------------------------
/art/customtheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/customtheme.png
--------------------------------------------------------------------------------
/art/datepicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/datepicker.png
--------------------------------------------------------------------------------
/art/datetimepicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/datetimepicker.png
--------------------------------------------------------------------------------
/art/file_chooser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/file_chooser.png
--------------------------------------------------------------------------------
/art/file_emptytext.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/file_emptytext.png
--------------------------------------------------------------------------------
/art/file_folder_creation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/file_folder_creation.png
--------------------------------------------------------------------------------
/art/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/icon.png
--------------------------------------------------------------------------------
/art/input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/input.png
--------------------------------------------------------------------------------
/art/input_max_length.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/input_max_length.png
--------------------------------------------------------------------------------
/art/lightanddarkthemes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/lightanddarkthemes.png
--------------------------------------------------------------------------------
/art/multi_choice_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/multi_choice_list.png
--------------------------------------------------------------------------------
/art/showcase4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/showcase4.png
--------------------------------------------------------------------------------
/art/single_choice_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/single_choice_list.png
--------------------------------------------------------------------------------
/art/stacked_buttons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/stacked_buttons.png
--------------------------------------------------------------------------------
/art/timepicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/art/timepicker.png
--------------------------------------------------------------------------------
/bottomsheets/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/bottomsheets/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "bottomsheets"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api project(':core')
8 |
9 | implementation deps.kotlin.stdlib8
10 | implementation deps.google_material
11 | }
12 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/java/com/afollestad/materialdialogs/bottomsheets/GridItem.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.bottomsheets
17 |
18 | import android.widget.ImageView
19 | import android.widget.TextView
20 | import androidx.annotation.DrawableRes
21 |
22 | /** @author Aidan Follestad (@afollestad) */
23 | interface GridItem {
24 | val title: String
25 | fun populateIcon(imageView: ImageView)
26 | fun configureTitle(textView: TextView) {
27 | textView.text = title
28 | }
29 | }
30 |
31 | /** @author Aidan Follestad (@afollestad) */
32 | data class BasicGridItem(
33 | @DrawableRes val iconRes: Int,
34 | override val title: String
35 | ) : GridItem {
36 | override fun populateIcon(imageView: ImageView) {
37 | imageView.setImageResource(iconRes)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/java/com/afollestad/materialdialogs/bottomsheets/HeightMatchesWidthImageView.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.bottomsheets
17 |
18 | import android.content.Context
19 | import android.util.AttributeSet
20 | import androidx.annotation.RestrictTo
21 | import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
22 | import androidx.appcompat.widget.AppCompatImageView
23 |
24 | /**
25 | * @author Aidan Follestad (@afollestad)
26 | * @hide
27 | */
28 | @RestrictTo(LIBRARY_GROUP)
29 | class HeightMatchesWidthImageView(
30 | context: Context,
31 | attrs: AttributeSet?
32 | ) : AppCompatImageView(context, attrs) {
33 |
34 | override fun onMeasure(
35 | widthMeasureSpec: Int,
36 | heightMeasureSpec: Int
37 | ) = super.onMeasure(widthMeasureSpec, widthMeasureSpec)
38 | }
39 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res-public/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/layout/md_dialog_base_bottomsheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/layout/md_dialog_base_no_buttons.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/layout/md_griditem.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
19 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/values-land/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 6
4 |
5 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/values-large-land/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8
4 |
5 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/values-large/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 6
4 |
5 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4
4 |
5 |
--------------------------------------------------------------------------------
/bottomsheets/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
21 |
22 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply from: rootProject.file("gradle/versions_plugin_config.gradle")
2 |
3 | buildscript {
4 | apply from: rootProject.file("dependencies.gradle")
5 |
6 | repositories {
7 | google()
8 | jcenter()
9 | }
10 |
11 | dependencies {
12 | classpath deps.gradle_plugins.android
13 | classpath deps.gradle_plugins.kotlin
14 | classpath deps.gradle_plugins.spotless
15 | classpath deps.gradle_plugins.versions
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | }
24 | }
25 |
26 | subprojects {
27 | tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
28 | kotlinOptions {
29 | freeCompilerArgs += ['-module-name', project.path.replace(':', '')]
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/color/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/color/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "color"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api project(':core')
8 |
9 | implementation deps.kotlin.stdlib8
10 | implementation deps.afollestad.dots_indicator
11 | }
12 |
--------------------------------------------------------------------------------
/color/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/ColorPagerAdapter.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.color
17 |
18 | import android.view.View
19 | import android.view.ViewGroup
20 | import androidx.viewpager.widget.PagerAdapter
21 |
22 | internal class ColorPagerAdapter : PagerAdapter() {
23 |
24 | override fun instantiateItem(
25 | collection: ViewGroup,
26 | position: Int
27 | ): Any {
28 | var resId = 0
29 | when (position) {
30 | 0 -> resId = R.id.colorPresetGrid
31 | 1 -> resId = R.id.colorArgbPage
32 | }
33 | return collection.findViewById(resId)
34 | }
35 |
36 | override fun getCount() = 2
37 |
38 | override fun isViewFromObject(
39 | arg0: View,
40 | arg1: Any
41 | ) = arg0 === arg1 as View
42 |
43 | override fun destroyItem(
44 | container: ViewGroup,
45 | position: Int,
46 | arg1: Any
47 | ) = Unit
48 | }
49 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/utils/ColorExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.color.utils
17 |
18 | import android.graphics.Color
19 |
20 | internal fun Int.hexValue(includeAlpha: Boolean) = if (this == 0) {
21 | if (includeAlpha) "00000000" else "000000"
22 | } else {
23 | if (includeAlpha) {
24 | val result = Integer.toHexString(this)
25 | if (result.length == 6) {
26 | "00$result"
27 | } else {
28 | result
29 | }
30 | } else {
31 | String.format("%06X", 0xFFFFFF and this)
32 | }
33 | }
34 |
35 | internal fun String.toColor(): Int? {
36 | return try {
37 | Color.parseColor("#$this")
38 | } catch (_: Exception) {
39 | null
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/utils/ViewExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.color.utils
17 |
18 | import android.view.View
19 | import android.view.View.GONE
20 | import android.view.View.INVISIBLE
21 | import android.view.View.VISIBLE
22 | import android.view.ViewGroup.MarginLayoutParams
23 | import android.widget.RelativeLayout
24 | import androidx.annotation.IdRes
25 | import androidx.viewpager.widget.ViewPager
26 |
27 | internal fun T.setVisibleOrGone(visible: Boolean) {
28 | visibility = if (visible) VISIBLE else GONE
29 | }
30 |
31 | internal fun ViewPager.onPageSelected(selection: (Int) -> Unit) {
32 | addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
33 | override fun onPageSelected(position: Int) = selection(position)
34 |
35 | override fun onPageScrollStateChanged(state: Int) = Unit
36 |
37 | override fun onPageScrolled(
38 | position: Int,
39 | positionOffset: Float,
40 | positionOffsetPixels: Int
41 | ) = Unit
42 | })
43 | }
44 |
45 | internal fun View.changeHeight(height: Int) {
46 | if (height == 0) {
47 | visibility = INVISIBLE
48 | }
49 | val lp = layoutParams as MarginLayoutParams
50 | lp.height = height
51 | layoutParams = lp
52 | }
53 |
54 | internal fun View.below(@IdRes id: Int) {
55 | val lp = layoutParams as RelativeLayout.LayoutParams
56 | lp.addRule(RelativeLayout.BELOW, id)
57 | layoutParams = lp
58 | }
59 |
60 | internal fun View.clearTopMargin() {
61 | val lp = this.layoutParams as MarginLayoutParams
62 | lp.topMargin = 0
63 | layoutParams = lp
64 | parent.requestLayout()
65 | }
66 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/view/ColorCircleView.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.color.view
17 |
18 | import android.content.Context
19 | import android.graphics.Canvas
20 | import android.graphics.Color
21 | import android.graphics.Color.TRANSPARENT
22 | import android.graphics.Paint
23 | import android.graphics.Paint.Style.FILL
24 | import android.graphics.Paint.Style.STROKE
25 | import android.graphics.drawable.Drawable
26 | import android.util.AttributeSet
27 | import android.view.View
28 | import androidx.annotation.ColorInt
29 | import androidx.core.content.ContextCompat.getDrawable
30 | import com.afollestad.materialdialogs.color.R.dimen
31 | import com.afollestad.materialdialogs.color.R.drawable
32 | import com.afollestad.materialdialogs.utils.MDUtil.dimenPx
33 |
34 | /** @author Aidan Follestad (afollestad) */
35 | internal class ColorCircleView(
36 | context: Context,
37 | attrs: AttributeSet? = null
38 | ) : View(context, attrs) {
39 |
40 | private val strokePaint = Paint()
41 | private val fillPaint = Paint()
42 |
43 | private val borderWidth = dimenPx(
44 | dimen.color_circle_view_border
45 | )
46 |
47 | private var transparentGrid: Drawable? = null
48 |
49 | init {
50 | setWillNotDraw(false)
51 | strokePaint.style = STROKE
52 | strokePaint.isAntiAlias = true
53 | strokePaint.color = Color.BLACK
54 | strokePaint.strokeWidth = borderWidth.toFloat()
55 | fillPaint.style = FILL
56 | fillPaint.isAntiAlias = true
57 | fillPaint.color = Color.DKGRAY
58 | }
59 |
60 | @ColorInt var color: Int = Color.BLACK
61 | set(value) {
62 | field = value
63 | fillPaint.color = value
64 | invalidate()
65 | }
66 | @ColorInt var border: Int = Color.DKGRAY
67 | set(value) {
68 | field = value
69 | strokePaint.color = value
70 | invalidate()
71 | }
72 |
73 | override fun onMeasure(
74 | widthMeasureSpec: Int,
75 | heightMeasureSpec: Int
76 | ) = super.onMeasure(widthMeasureSpec, widthMeasureSpec)
77 |
78 | override fun onDraw(canvas: Canvas) {
79 | super.onDraw(canvas)
80 | if (color == TRANSPARENT) {
81 | if (transparentGrid == null) {
82 | transparentGrid = getDrawable(context,
83 | drawable.transparentgrid
84 | )
85 | }
86 | transparentGrid?.setBounds(0, 0, measuredWidth, measuredHeight)
87 | transparentGrid?.draw(canvas)
88 | } else {
89 | canvas.drawCircle(
90 | measuredWidth / 2f,
91 | measuredHeight / 2f,
92 | (measuredWidth / 2f) - borderWidth,
93 | fillPaint
94 | )
95 | }
96 | canvas.drawCircle(
97 | measuredWidth / 2f,
98 | measuredHeight / 2f,
99 | (measuredWidth / 2f) - borderWidth,
100 | strokePaint
101 | )
102 | }
103 |
104 | override fun onDetachedFromWindow() {
105 | super.onDetachedFromWindow()
106 | transparentGrid = null
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/view/ObservableEditText.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("MemberVisibilityCanBePrivate", "unused")
17 |
18 | package com.afollestad.materialdialogs.color.view
19 |
20 | import android.content.Context
21 | import android.text.Editable
22 | import android.text.TextWatcher
23 | import android.util.AttributeSet
24 | import androidx.annotation.StringRes
25 | import androidx.appcompat.widget.AppCompatEditText
26 |
27 | typealias TextListener = ((String) -> Unit)?
28 |
29 | /** @author Aidan Follestad (@afollestad) */
30 | class ObservableEditText(
31 | context: Context,
32 | attrs: AttributeSet? = null
33 | ) : AppCompatEditText(context, attrs) {
34 |
35 | private var listener: TextListener = null
36 | private var paused: Boolean = false
37 |
38 | val textOrEmpty: String
39 | get() = text?.toString()?.trim() ?: ""
40 | val textLength: Int get() = textOrEmpty.length
41 |
42 | override fun onAttachedToWindow() {
43 | super.onAttachedToWindow()
44 | addTextChangedListener(watcher)
45 | }
46 |
47 | override fun onDetachedFromWindow() {
48 | super.onDetachedFromWindow()
49 | removeTextChangedListener(watcher)
50 | }
51 |
52 | fun observe(listener: TextListener) {
53 | this.listener = listener
54 | }
55 |
56 | fun updateText(text: CharSequence) {
57 | paused = true
58 | setText(text)
59 | }
60 |
61 | fun updateText(@StringRes res: Int) {
62 | paused = true
63 | setText(res)
64 | }
65 |
66 | private val watcher = object : TextWatcher {
67 | override fun beforeTextChanged(
68 | s: CharSequence?,
69 | start: Int,
70 | count: Int,
71 | after: Int
72 | ) = Unit
73 |
74 | override fun onTextChanged(
75 | s: CharSequence,
76 | start: Int,
77 | before: Int,
78 | count: Int
79 | ) {
80 | if (!paused) {
81 | listener?.invoke(s.toString())
82 | }
83 | }
84 |
85 | override fun afterTextChanged(s: Editable?) {
86 | paused = false
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/view/ObservableSeekBar.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.color.view
17 |
18 | import android.content.Context
19 | import android.os.Build
20 | import android.util.AttributeSet
21 | import android.widget.SeekBar
22 | import androidx.appcompat.widget.AppCompatSeekBar
23 |
24 | typealias ProgressListener = ((Int) -> Unit)?
25 |
26 | /** @author Aidan Follestad (@afollestad) */
27 | class ObservableSeekBar(
28 | context: Context,
29 | attrs: AttributeSet? = null
30 | ) : AppCompatSeekBar(context, attrs) {
31 |
32 | private var listener: ProgressListener = null
33 | private var paused: Boolean = false
34 | private var onlyFromUser: Boolean = false
35 |
36 | override fun onAttachedToWindow() {
37 | super.onAttachedToWindow()
38 | setOnSeekBarChangeListener(watcher)
39 | }
40 |
41 | override fun onDetachedFromWindow() {
42 | setOnSeekBarChangeListener(null)
43 | super.onDetachedFromWindow()
44 | }
45 |
46 | fun observe(
47 | onlyFromUser: Boolean = true,
48 | listener: ProgressListener
49 | ) {
50 | this.onlyFromUser = onlyFromUser
51 | this.listener = listener
52 | }
53 |
54 | fun updateProgress(
55 | progress: Int,
56 | animate: Boolean = false
57 | ) {
58 | paused = true
59 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
60 | setProgress(progress, animate)
61 | } else {
62 | setProgress(progress)
63 | }
64 | }
65 |
66 | private val watcher = object : OnSeekBarChangeListener {
67 | override fun onProgressChanged(
68 | seekBar: SeekBar,
69 | progress: Int,
70 | fromUser: Boolean
71 | ) {
72 | if (!onlyFromUser || fromUser) {
73 | listener?.invoke(progress)
74 | }
75 | paused = false
76 | }
77 |
78 | override fun onStartTrackingTouch(seekBar: SeekBar?) = Unit
79 |
80 | override fun onStopTrackingTouch(seekBar: SeekBar?) = Unit
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/color/src/main/java/com/afollestad/materialdialogs/color/view/WrapContentViewPager.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.color.view
17 |
18 | import android.content.Context
19 | import android.util.AttributeSet
20 | import android.view.View
21 | import android.view.View.MeasureSpec.EXACTLY
22 | import android.view.View.MeasureSpec.UNSPECIFIED
23 | import android.view.View.MeasureSpec.makeMeasureSpec
24 | import androidx.viewpager.widget.ViewPager
25 | import com.afollestad.materialdialogs.utils.MDUtil.ifNotZero
26 |
27 | internal class WrapContentViewPager(
28 | context: Context,
29 | attrs: AttributeSet? = null
30 | ) : ViewPager(context, attrs) {
31 |
32 | override fun onMeasure(
33 | widthMeasureSpec: Int,
34 | heightMeasureSpec: Int
35 | ) {
36 | var newHeightSpec = heightMeasureSpec
37 |
38 | var maxChildHeight = 0
39 | forEachChild { child ->
40 | child.measure(
41 | widthMeasureSpec,
42 | makeMeasureSpec(0, UNSPECIFIED)
43 | )
44 |
45 | val h = child.measuredHeight
46 | if (h > maxChildHeight) {
47 | maxChildHeight = h
48 | }
49 | }
50 |
51 | val maxAllowedHeightFromParent = MeasureSpec.getSize(heightMeasureSpec)
52 | if (maxChildHeight > maxAllowedHeightFromParent) {
53 | maxChildHeight = maxAllowedHeightFromParent
54 | }
55 | maxChildHeight.ifNotZero {
56 | newHeightSpec = makeMeasureSpec(it, EXACTLY)
57 | }
58 |
59 | super.onMeasure(widthMeasureSpec, newHeightSpec)
60 | }
61 |
62 | private fun forEachChild(each: (View) -> Unit) {
63 | for (i in 0 until childCount) {
64 | val child = getChildAt(i)
65 | each(child)
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/color/src/main/res-public/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable-nodpi/transparent_rect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/color/src/main/res/drawable-nodpi/transparent_rect.png
--------------------------------------------------------------------------------
/color/src/main/res/drawable-nodpi/transparentgrid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/color/src/main/res/drawable-nodpi/transparentgrid.png
--------------------------------------------------------------------------------
/color/src/main/res/drawable/icon_back_black.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable/icon_back_white.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable/icon_checkmark_black.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable/icon_checkmark_white.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable/icon_custom_black.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable/icon_custom_white.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/color/src/main/res/drawable/transparent_rect_repeat.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/color/src/main/res/layout-land/md_color_chooser_base_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/color/src/main/res/layout/md_color_chooser_base_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
--------------------------------------------------------------------------------
/color/src/main/res/layout/md_color_chooser_base_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/color/src/main/res/layout/md_color_chooser_preview_frame.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
25 |
26 |
33 |
34 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/color/src/main/res/layout/md_color_grid_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/color/src/main/res/layout/md_color_grid_item_go_up.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/color/src/main/res/values-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4dp
5 | 12dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/color/src/main/res/values-land/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 5
4 |
5 |
--------------------------------------------------------------------------------
/color/src/main/res/values-large-land/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 7
4 |
5 |
--------------------------------------------------------------------------------
/color/src/main/res/values-large/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 6
4 |
5 |
--------------------------------------------------------------------------------
/color/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1dp
4 |
5 | 8dp
6 | 16dp
7 | 12dp
8 |
9 | 24dp
10 | 8dp
11 |
12 | 72dp
13 | 120dp
14 | 8dp
15 | 8dp
16 |
17 | 18sp
18 | 20dp
19 | 8dp
20 |
21 | 36dp
22 |
23 |
24 |
--------------------------------------------------------------------------------
/color/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4
4 |
5 |
--------------------------------------------------------------------------------
/color/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
15 |
16 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/core/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/core/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "core"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api deps.androidx.core
8 | api deps.androidx.recycler_view
9 | compileOnly deps.androidx.annotations
10 |
11 | implementation deps.kotlin.stdlib8
12 | }
13 |
--------------------------------------------------------------------------------
/core/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/LayoutMode.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs
17 |
18 | /** @author Aidan Follestad (afollestad) */
19 | enum class LayoutMode {
20 | /** The layout height fills in the screen. */
21 | MATCH_PARENT,
22 | /**
23 | * The layout height wraps its children, maxing out at the screen height in which case the
24 | * children should be inside of a ScrollView.
25 | */
26 | WRAP_CONTENT
27 | }
28 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/Theme.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs
17 |
18 | import android.R.attr
19 | import android.content.Context
20 | import androidx.annotation.CheckResult
21 | import androidx.annotation.StyleRes
22 | import com.afollestad.materialdialogs.utils.MDUtil.isColorDark
23 | import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
24 |
25 | @StyleRes @CheckResult
26 | internal fun inferTheme(
27 | context: Context,
28 | dialogBehavior: DialogBehavior
29 | ): Int {
30 | val isThemeDark = !inferThemeIsLight(context)
31 | return dialogBehavior.getThemeRes(isThemeDark)
32 | }
33 |
34 | @CheckResult internal fun inferThemeIsLight(context: Context): Boolean {
35 | return resolveColor(context = context, attr = attr.textColorPrimary).isColorDark()
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/WhichButton.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs
17 |
18 | import com.afollestad.materialdialogs.internal.button.DialogActionButtonLayout.Companion.INDEX_NEGATIVE
19 | import com.afollestad.materialdialogs.internal.button.DialogActionButtonLayout.Companion.INDEX_NEUTRAL
20 | import com.afollestad.materialdialogs.internal.button.DialogActionButtonLayout.Companion.INDEX_POSITIVE
21 |
22 | enum class WhichButton(val index: Int) {
23 | POSITIVE(INDEX_POSITIVE),
24 | NEGATIVE(INDEX_NEGATIVE),
25 | NEUTRAL(INDEX_NEUTRAL);
26 |
27 | companion object {
28 | fun fromIndex(index: Int) = when (index) {
29 | INDEX_POSITIVE -> POSITIVE
30 | INDEX_NEGATIVE -> NEGATIVE
31 | INDEX_NEUTRAL -> NEUTRAL
32 | else -> throw IndexOutOfBoundsException("$index is not an action button index.")
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/actions/DialogActionExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.actions
17 |
18 | import com.afollestad.materialdialogs.MaterialDialog
19 | import com.afollestad.materialdialogs.WhichButton
20 | import com.afollestad.materialdialogs.internal.button.DialogActionButton
21 | import com.afollestad.materialdialogs.utils.isVisible
22 |
23 | /** Returns true if the dialog has visible action buttons. */
24 | fun MaterialDialog.hasActionButtons(): Boolean {
25 | return view.buttonsLayout?.visibleButtons?.isNotEmpty() ?: false
26 | }
27 |
28 | /** Returns true if the given button is visible in the dialog. */
29 | fun MaterialDialog.hasActionButton(which: WhichButton) = getActionButton(which).isVisible()
30 |
31 | /** Returns the underlying view for an action button in the dialog. */
32 | fun MaterialDialog.getActionButton(which: WhichButton): DialogActionButton {
33 | return view.buttonsLayout?.actionButtons?.get(which.index) ?: throw IllegalStateException(
34 | "The dialog does not have an attached buttons layout."
35 | )
36 | }
37 |
38 | /** Enables or disables an action button. */
39 | fun MaterialDialog.setActionButtonEnabled(
40 | which: WhichButton,
41 | enabled: Boolean
42 | ) {
43 | getActionButton(which).isEnabled = enabled
44 | }
45 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/callbacks/DialogCallbackExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.callbacks
17 |
18 | import com.afollestad.materialdialogs.DialogCallback
19 | import com.afollestad.materialdialogs.MaterialDialog
20 |
21 | /**
22 | * Adds a listener that's invoked right before the dialog is [MaterialDialog.show]'n. If this is called
23 | * multiple times, it appends additional callbacks, rather than overwriting.
24 | */
25 | fun MaterialDialog.onPreShow(callback: DialogCallback): MaterialDialog {
26 | this.preShowListeners.add(callback)
27 | return this
28 | }
29 |
30 | /**
31 | * Adds a listener that's invoked when the dialog is [MaterialDialog.show]'n. If this is called
32 | * multiple times, it appends additional callbacks, rather than overwriting.
33 | *
34 | * If the dialog is already showing, the callback be will be invoked immediately.
35 | */
36 | fun MaterialDialog.onShow(callback: DialogCallback): MaterialDialog {
37 | this.showListeners.add(callback)
38 | if (this.isShowing) {
39 | // Already showing, invoke now
40 | this.showListeners.invokeAll(this)
41 | }
42 | setOnShowListener { this.showListeners.invokeAll(this) }
43 | return this
44 | }
45 |
46 | /**
47 | * Adds a listener that's invoked when the dialog is [MaterialDialog.dismiss]'d. If this is called
48 | * multiple times, it appends additional callbacks, rather than overwriting.
49 | */
50 | fun MaterialDialog.onDismiss(callback: DialogCallback): MaterialDialog {
51 | this.dismissListeners.add(callback)
52 | setOnDismissListener { dismissListeners.invokeAll(this) }
53 | return this
54 | }
55 |
56 | /**
57 | * Adds a listener that's invoked when the dialog is [MaterialDialog.cancel]'d. If this is called
58 | * multiple times, it appends additional callbacks, rather than overwriting.
59 | */
60 | fun MaterialDialog.onCancel(callback: DialogCallback): MaterialDialog {
61 | this.cancelListeners.add(callback)
62 | setOnCancelListener { cancelListeners.invokeAll(this) }
63 | return this
64 | }
65 |
66 | internal fun MutableList.invokeAll(dialog: MaterialDialog) {
67 | for (callback in this) {
68 | callback.invoke(dialog)
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/checkbox/DialogCheckboxExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("unused")
17 |
18 | package com.afollestad.materialdialogs.checkbox
19 |
20 | import android.view.View
21 | import android.widget.CheckBox
22 | import androidx.annotation.CheckResult
23 | import androidx.annotation.StringRes
24 | import androidx.core.widget.CompoundButtonCompat
25 | import com.afollestad.materialdialogs.MaterialDialog
26 | import com.afollestad.materialdialogs.R
27 | import com.afollestad.materialdialogs.utils.MDUtil.assertOneSet
28 | import com.afollestad.materialdialogs.utils.MDUtil.createColorSelector
29 | import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
30 | import com.afollestad.materialdialogs.utils.MDUtil.resolveString
31 | import com.afollestad.materialdialogs.utils.resolveColors
32 |
33 | typealias BooleanCallback = ((Boolean) -> Unit)?
34 |
35 | @CheckResult fun MaterialDialog.getCheckBoxPrompt(): CheckBox {
36 | return view.buttonsLayout?.checkBoxPrompt ?: throw IllegalStateException(
37 | "The dialog does not have an attached buttons layout."
38 | )
39 | }
40 |
41 | @CheckResult fun MaterialDialog.isCheckPromptChecked() = getCheckBoxPrompt().isChecked
42 |
43 | /**
44 | * @param res The string resource to display for the checkbox label.
45 | * @param text The literal string to display for the checkbox label.
46 | * @param isCheckedDefault Whether or not the checkbox is initially checked.
47 | * @param onToggle A listener invoked when the checkbox is checked or unchecked.
48 | */
49 | fun MaterialDialog.checkBoxPrompt(
50 | @StringRes res: Int = 0,
51 | text: String? = null,
52 | isCheckedDefault: Boolean = false,
53 | onToggle: BooleanCallback
54 | ): MaterialDialog {
55 | assertOneSet("checkBoxPrompt", text, res)
56 | view.buttonsLayout?.checkBoxPrompt?.run {
57 | this.visibility = View.VISIBLE
58 | this.text = text ?: resolveString(this@checkBoxPrompt, res)
59 | this.isChecked = isCheckedDefault
60 | this.setOnCheckedChangeListener { _, checked ->
61 | onToggle?.invoke(checked)
62 | }
63 | maybeSetTextColor(windowContext, R.attr.md_color_content)
64 | bodyFont?.let(this::setTypeface)
65 |
66 | val widgetAttrs = intArrayOf(R.attr.md_color_widget, R.attr.md_color_widget_unchecked)
67 | resolveColors(attrs = widgetAttrs).let {
68 | CompoundButtonCompat.setButtonTintList(
69 | this,
70 | createColorSelector(windowContext, checked = it[0], unchecked = it[1])
71 | )
72 | }
73 | }
74 | return this
75 | }
76 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/customview/DialogCustomViewExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.customview
17 |
18 | import android.view.View
19 | import androidx.annotation.CheckResult
20 | import androidx.annotation.LayoutRes
21 | import com.afollestad.materialdialogs.MaterialDialog
22 | import com.afollestad.materialdialogs.utils.MDUtil.assertOneSet
23 | import com.afollestad.materialdialogs.utils.MDUtil.waitForWidth
24 |
25 | internal const val CUSTOM_VIEW_NO_VERTICAL_PADDING = "md.custom_view_no_vertical_padding"
26 |
27 | /**
28 | * Gets the custom view for the dialog, set by [customView].
29 | *
30 | * @throws IllegalStateException if there is no custom view set.
31 | */
32 | @CheckResult fun MaterialDialog.getCustomView(): View {
33 | return this.view.contentLayout.customView
34 | ?: error("You have not setup this dialog as a customView dialog.")
35 | }
36 |
37 | /**
38 | * Sets a custom view to display in the dialog, below the title and above the action buttons
39 | * (and checkbox prompt).
40 | *
41 | * @param viewRes The layout resource to inflate as the custom view.
42 | * @param view The view to insert as the custom view.
43 | * @param scrollable Whether or not the custom view is automatically wrapped in a ScrollView.
44 | * @param noVerticalPadding When set to true, vertical padding is not added around your content.
45 | * @param horizontalPadding When true, 24dp horizontal padding is applied to your custom view.
46 | * @param dialogWrapContent When true, the dialog will wrap the content width.
47 | */
48 | fun MaterialDialog.customView(
49 | @LayoutRes viewRes: Int? = null,
50 | view: View? = null,
51 | scrollable: Boolean = false,
52 | noVerticalPadding: Boolean = false,
53 | horizontalPadding: Boolean = false,
54 | dialogWrapContent: Boolean = false
55 | ): MaterialDialog {
56 | assertOneSet("customView", view, viewRes)
57 | config[CUSTOM_VIEW_NO_VERTICAL_PADDING] = noVerticalPadding
58 |
59 | if (dialogWrapContent) {
60 | // Postpone window measurement so custom view measures itself naturally.
61 | maxWidth(literal = 0)
62 | }
63 |
64 | this.view.contentLayout
65 | .addCustomView(
66 | res = viewRes,
67 | view = view,
68 | scrollable = scrollable,
69 | horizontalPadding = horizontalPadding,
70 | noVerticalPadding = noVerticalPadding
71 | )
72 | .also {
73 | if (dialogWrapContent) {
74 | it.waitForWidth {
75 | maxWidth(literal = measuredWidth)
76 | }
77 | }
78 | }
79 |
80 | return this
81 | }
82 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/list/AdapterPayload.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.internal.list
17 |
18 | /**
19 | * Used by the single and multi-choice list adapters to selectively bind list items. This
20 | * payload indicates that the notified list item should check its toggleable view.
21 | */
22 | internal object CheckPayload
23 |
24 | /**
25 | * Used by the single and multi-choice list adapters to selectively bind list items. This
26 | * payload indicates that the notified list item should uncheck its toggleable view.
27 | */
28 | internal object UncheckPayload
29 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/list/DialogAdapter.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.internal.list
17 |
18 | interface DialogAdapter {
19 | fun replaceItems(
20 | items: List,
21 | listener: SL? = null
22 | )
23 |
24 | fun disableItems(indices: IntArray)
25 |
26 | fun checkItems(indices: IntArray)
27 |
28 | fun uncheckItems(indices: IntArray)
29 |
30 | fun toggleItems(indices: IntArray)
31 |
32 | fun checkAllItems()
33 |
34 | fun uncheckAllItems()
35 |
36 | fun toggleAllChecked()
37 |
38 | fun isItemChecked(index: Int): Boolean
39 |
40 | fun getItemCount(): Int
41 |
42 | fun positiveButtonClicked()
43 | }
44 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/main/BaseSubLayout.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.internal.main
17 |
18 | import android.content.Context
19 | import android.graphics.Paint
20 | import android.graphics.Paint.Style.STROKE
21 | import android.util.AttributeSet
22 | import android.view.ViewGroup
23 | import androidx.annotation.RestrictTo
24 | import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
25 | import com.afollestad.materialdialogs.MaterialDialog
26 | import com.afollestad.materialdialogs.R
27 | import com.afollestad.materialdialogs.R.attr
28 | import com.afollestad.materialdialogs.utils.MDUtil.dimenPx
29 | import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
30 |
31 | @RestrictTo(LIBRARY_GROUP)
32 | abstract class BaseSubLayout internal constructor(
33 | context: Context,
34 | attrs: AttributeSet? = null
35 | ) : ViewGroup(context, attrs) {
36 |
37 | private val dividerPaint = Paint()
38 | protected val dividerHeight = dimenPx(R.dimen.md_divider_height)
39 | lateinit var dialog: MaterialDialog
40 |
41 | var drawDivider: Boolean = false
42 | set(value) {
43 | field = value
44 | invalidate()
45 | }
46 |
47 | init {
48 | @Suppress("LeakingThis")
49 | setWillNotDraw(false)
50 | dividerPaint.style = STROKE
51 | dividerPaint.strokeWidth = context.resources.getDimension(R.dimen.md_divider_height)
52 | dividerPaint.isAntiAlias = true
53 | }
54 |
55 | protected fun dividerPaint(): Paint {
56 | dividerPaint.color = getDividerColor()
57 | return dividerPaint
58 | }
59 |
60 | private fun getDividerColor(): Int {
61 | return resolveColor(dialog.context, attr = attr.md_divider_color)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/main/DialogScrollView.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.internal.main
17 |
18 | import android.content.Context
19 | import android.util.AttributeSet
20 | import android.widget.ScrollView
21 | import androidx.annotation.RestrictTo
22 | import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
23 | import com.afollestad.materialdialogs.utils.MDUtil.waitForWidth
24 |
25 | /**
26 | * A [ScrollView] which reports whether or not it's scrollable based on whether the content
27 | * is shorter than the ScrollView itself. Also reports back to an [DialogLayout] to invalidate
28 | * dividers.
29 | *
30 | * @author Aidan Follestad (afollestad)
31 | */
32 | @RestrictTo(LIBRARY_GROUP)
33 | class DialogScrollView(
34 | context: Context?,
35 | attrs: AttributeSet? = null
36 | ) : ScrollView(context, attrs) {
37 |
38 | var rootView: DialogLayout? = null
39 |
40 | private val isScrollable: Boolean
41 | get() = getChildAt(0).measuredHeight > height
42 |
43 | override fun onAttachedToWindow() {
44 | super.onAttachedToWindow()
45 | waitForWidth {
46 | invalidateDividers()
47 | invalidateOverScroll()
48 | }
49 | }
50 |
51 | override fun onScrollChanged(
52 | left: Int,
53 | top: Int,
54 | oldl: Int,
55 | oldt: Int
56 | ) {
57 | super.onScrollChanged(left, top, oldl, oldt)
58 | invalidateDividers()
59 | }
60 |
61 | fun invalidateDividers() {
62 | if (childCount == 0 || measuredHeight == 0 || !isScrollable) {
63 | rootView?.invalidateDividers(showTop = false, showBottom = false)
64 | return
65 | }
66 | val view = getChildAt(childCount - 1)
67 | val diff = view.bottom - (measuredHeight + scrollY)
68 | rootView?.invalidateDividers(
69 | scrollY > 0,
70 | diff > 0
71 | )
72 | }
73 |
74 | private fun invalidateOverScroll() {
75 | overScrollMode = if (childCount == 0 || measuredHeight == 0 || !isScrollable) {
76 | OVER_SCROLL_NEVER
77 | } else {
78 | OVER_SCROLL_IF_CONTENT_SCROLLS
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/message/CustomUrlSpan.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("unused")
17 |
18 | package com.afollestad.materialdialogs.internal.message
19 |
20 | import android.text.style.URLSpan
21 | import android.view.View
22 |
23 | /** @author Aidan Follestad (@afollestad) */
24 | class CustomUrlSpan(
25 | url: String,
26 | private val onLinkClick: (String) -> Unit
27 | ) : URLSpan(url) {
28 | override fun onClick(widget: View) = onLinkClick(url)
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/message/LinkTransformationMethod.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.internal.message
17 |
18 | import android.graphics.Rect
19 | import android.text.Spannable
20 | import android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
21 | import android.text.method.TransformationMethod
22 | import android.text.style.URLSpan
23 | import android.view.View
24 | import android.widget.TextView
25 |
26 | /** https://medium.com/@nullthemall/make-textview-open-links-in-customtabs-12fdcf4bb684 */
27 | internal class LinkTransformationMethod(
28 | private val onLinkClick: (link: String) -> Unit
29 | ) : TransformationMethod {
30 | override fun getTransformation(
31 | source: CharSequence,
32 | view: View
33 | ): CharSequence {
34 | if (view !is TextView) {
35 | return source
36 | } else if (view.text == null || view.text !is Spannable) {
37 | return source
38 | }
39 | val text = view.text as Spannable
40 | val spans = text.getSpans(0, view.length(), URLSpan::class.java)
41 | for (span in spans) {
42 | val start = text.getSpanStart(span)
43 | val end = text.getSpanEnd(span)
44 | val url = span.url
45 |
46 | text.removeSpan(span)
47 | text.setSpan(CustomUrlSpan(url, onLinkClick), start, end, SPAN_EXCLUSIVE_EXCLUSIVE)
48 | }
49 | return text
50 | }
51 |
52 | override fun onFocusChanged(
53 | view: View,
54 | sourceText: CharSequence,
55 | focused: Boolean,
56 | direction: Int,
57 | previouslyFocusedRect: Rect
58 | ) = Unit
59 | }
60 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/internal/rtl/RtlTextView.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.internal.rtl
17 |
18 | import android.content.Context
19 | import android.util.AttributeSet
20 | import androidx.appcompat.widget.AppCompatTextView
21 | import com.afollestad.materialdialogs.utils.setGravityStartCompat
22 |
23 | /**
24 | * With our custom layout-ing, using START/END gravity doesn't work so we manually
25 | * set text alignment for RTL/LTR.
26 | *
27 | * @author Aidan Follestad (afollestad)
28 | */
29 | class RtlTextView(
30 | context: Context,
31 | attrs: AttributeSet?
32 | ) : AppCompatTextView(context, attrs) {
33 | init {
34 | setGravityStartCompat()
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/list/ListCallbacks.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.list
17 |
18 | import com.afollestad.materialdialogs.MaterialDialog
19 |
20 | typealias ItemListener =
21 | ((dialog: MaterialDialog, index: Int, text: CharSequence) -> Unit)?
22 |
23 | typealias SingleChoiceListener =
24 | ((dialog: MaterialDialog, index: Int, text: CharSequence) -> Unit)?
25 |
26 | typealias MultiChoiceListener =
27 | ((dialog: MaterialDialog, indices: IntArray, items: List) -> Unit)?
28 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/message/DialogMessageSettings.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.message
17 |
18 | import android.text.Html
19 | import android.text.method.LinkMovementMethod
20 | import android.widget.TextView
21 | import androidx.annotation.StringRes
22 | import com.afollestad.materialdialogs.MaterialDialog
23 | import com.afollestad.materialdialogs.R
24 | import com.afollestad.materialdialogs.internal.message.LinkTransformationMethod
25 | import com.afollestad.materialdialogs.utils.MDUtil.resolveFloat
26 | import com.afollestad.materialdialogs.utils.MDUtil.resolveString
27 |
28 | /** @author Aidan Follestad (@afollestad) */
29 | class DialogMessageSettings internal constructor(
30 | private val dialog: MaterialDialog,
31 | @Suppress("MemberVisibilityCanBePrivate")
32 | val messageTextView: TextView
33 | ) {
34 | private var isHtml: Boolean = false
35 | private var didSetLineSpacing: Boolean = false
36 |
37 | fun lineSpacing(multiplier: Float): DialogMessageSettings {
38 | didSetLineSpacing = true
39 | messageTextView.setLineSpacing(0f, multiplier)
40 | return this
41 | }
42 |
43 | fun html(onLinkClick: ((link: String) -> Unit)? = null): DialogMessageSettings {
44 | isHtml = true
45 | if (onLinkClick != null) {
46 | messageTextView.transformationMethod = LinkTransformationMethod(onLinkClick)
47 | }
48 | messageTextView.movementMethod = LinkMovementMethod.getInstance()
49 | return this
50 | }
51 |
52 | internal fun setText(
53 | @StringRes res: Int?,
54 | text: CharSequence?
55 | ) {
56 | if (!didSetLineSpacing) {
57 | lineSpacing(
58 | resolveFloat(
59 | context = dialog.windowContext,
60 | attr = R.attr.md_line_spacing_body,
61 | defaultValue = 1.1f
62 | )
63 | )
64 | }
65 | messageTextView.text = text.maybeWrapHtml(isHtml)
66 | ?: resolveString(dialog, res, html = isHtml)
67 | }
68 |
69 | private fun CharSequence?.maybeWrapHtml(isHtml: Boolean): CharSequence? {
70 | if (this == null) return null
71 | @Suppress("DEPRECATION")
72 | return if (isHtml) Html.fromHtml(this.toString()) else this
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/utils/Arrays.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.utils
17 |
18 | internal inline fun List.pullIndices(indices: IntArray): List {
19 | return mutableListOf().apply {
20 | for (index in indices) {
21 | add(this@pullIndices[index])
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/utils/Colors.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.utils
17 |
18 | import android.graphics.Color
19 | import androidx.annotation.AttrRes
20 | import androidx.annotation.CheckResult
21 | import androidx.annotation.ColorInt
22 | import androidx.annotation.ColorRes
23 | import com.afollestad.materialdialogs.MaterialDialog
24 | import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
25 | import com.afollestad.materialdialogs.utils.MDUtil.resolveColors
26 |
27 | @ColorInt @CheckResult
28 | internal fun MaterialDialog.resolveColor(
29 | @ColorRes res: Int? = null,
30 | @AttrRes attr: Int? = null,
31 | fallback: (() -> Int)? = null
32 | ): Int = resolveColor(windowContext, res, attr, fallback)
33 |
34 | @CheckResult
35 | internal fun MaterialDialog.resolveColors(
36 | attrs: IntArray,
37 | fallback: ((forAttr: Int) -> Int)? = null
38 | ) = resolveColors(windowContext, attrs, fallback)
39 |
40 | @ColorInt @CheckResult
41 | internal fun Int.adjustAlpha(alpha: Float): Int {
42 | return Color.argb((255 * alpha).toInt(), Color.red(this), Color.green(this), Color.blue(this))
43 | }
44 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/utils/Dimens.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.utils
17 |
18 | import android.util.TypedValue
19 | import android.util.TypedValue.COMPLEX_UNIT_DIP
20 | import android.view.View
21 | import androidx.annotation.AttrRes
22 | import androidx.annotation.DimenRes
23 | import com.afollestad.materialdialogs.MaterialDialog
24 | import com.afollestad.materialdialogs.utils.MDUtil.assertOneSet
25 |
26 | internal fun MaterialDialog.dimen(
27 | @DimenRes res: Int? = null,
28 | @AttrRes attr: Int? = null,
29 | fallback: Float = 0f
30 | ): Float {
31 | assertOneSet("dimen", attr, res)
32 | if (res != null) {
33 | return windowContext.resources.getDimension(res)
34 | }
35 | requireNotNull(attr)
36 | val a = windowContext.theme.obtainStyledAttributes(intArrayOf(attr))
37 | try {
38 | return a.getDimension(0, fallback)
39 | } finally {
40 | a.recycle()
41 | }
42 | }
43 |
44 | internal fun View.dp(value: Int): Float {
45 | return TypedValue.applyDimension(COMPLEX_UNIT_DIP, value.toFloat(), resources.displayMetrics)
46 | }
47 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/utils/Fonts.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.utils
17 |
18 | import android.content.Context
19 | import android.graphics.Typeface
20 | import androidx.annotation.AttrRes
21 | import androidx.annotation.CheckResult
22 | import androidx.annotation.FontRes
23 | import androidx.core.content.res.ResourcesCompat
24 | import com.afollestad.materialdialogs.MaterialDialog
25 | import com.afollestad.materialdialogs.utils.MDUtil.assertOneSet
26 |
27 | @CheckResult internal fun MaterialDialog.font(
28 | @FontRes res: Int? = null,
29 | @AttrRes attr: Int? = null
30 | ): Typeface? {
31 | assertOneSet("font", attr, res)
32 | if (res != null) {
33 | return safeGetFont(windowContext, res)
34 | }
35 | requireNotNull(attr)
36 | val a = windowContext.theme.obtainStyledAttributes(intArrayOf(attr))
37 | try {
38 | val resId = a.getResourceId(0, 0)
39 | if (resId == 0) return null
40 | return safeGetFont(windowContext, resId)
41 | } finally {
42 | a.recycle()
43 | }
44 | }
45 |
46 | private fun safeGetFont(context: Context, @FontRes res: Int): Typeface? {
47 | return try {
48 | ResourcesCompat.getFont(context, res)
49 | } catch (e: Throwable) {
50 | e.printStackTrace()
51 | null
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/utils/IntArrays.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.utils
17 |
18 | internal fun IntArray.appendAll(values: Collection): IntArray {
19 | return toMutableList()
20 | .apply { addAll(values) }
21 | .toIntArray()
22 | }
23 |
24 | internal fun IntArray.removeAll(values: Collection): IntArray {
25 | return toMutableList().apply { removeAll { values.contains(it) } }
26 | .toIntArray()
27 | }
28 |
--------------------------------------------------------------------------------
/core/src/main/java/com/afollestad/materialdialogs/utils/Views.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.utils
17 |
18 | import android.os.Build.VERSION.SDK_INT
19 | import android.os.Build.VERSION_CODES.JELLY_BEAN_MR1
20 | import android.view.Gravity
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import android.view.ViewGroup
24 | import android.widget.Button
25 | import android.widget.TextView
26 | import androidx.annotation.LayoutRes
27 | import com.afollestad.materialdialogs.MaterialDialog
28 |
29 | @Suppress("UNCHECKED_CAST")
30 | internal fun MaterialDialog.inflate(
31 | @LayoutRes res: Int,
32 | root: ViewGroup? = null
33 | ) = LayoutInflater.from(windowContext).inflate(res, root, false) as T
34 |
35 | @Suppress("UNCHECKED_CAST")
36 | internal fun ViewGroup.inflate(
37 | @LayoutRes res: Int,
38 | root: ViewGroup? = this
39 | ) = LayoutInflater.from(context).inflate(res, root, false) as T
40 |
41 | internal fun T.isVisible(): Boolean {
42 | return if (this is Button) {
43 | this.visibility == View.VISIBLE && this.text.trim().isNotBlank()
44 | } else {
45 | this.visibility == View.VISIBLE
46 | }
47 | }
48 |
49 | internal fun T.isNotVisible(): Boolean = !isVisible()
50 |
51 | internal fun T.isRtl(): Boolean {
52 | return if (SDK_INT < JELLY_BEAN_MR1) false else resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
53 | }
54 |
55 | internal fun TextView.setGravityStartCompat() {
56 | if (SDK_INT >= JELLY_BEAN_MR1) {
57 | this.textAlignment = View.TEXT_ALIGNMENT_VIEW_START
58 | }
59 | this.gravity = Gravity.START or Gravity.CENTER_VERTICAL
60 | }
61 |
62 | internal fun TextView.setGravityEndCompat() {
63 | if (SDK_INT >= JELLY_BEAN_MR1) {
64 | this.textAlignment = View.TEXT_ALIGNMENT_VIEW_END
65 | }
66 | this.gravity = Gravity.END or Gravity.CENTER_VERTICAL
67 | }
68 |
--------------------------------------------------------------------------------
/core/src/main/res-public/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/core/src/main/res/anim/decelerate_cubic.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/core/src/main/res/anim/popup_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/core/src/main/res/anim/popup_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/core/src/main/res/color/md_list_item_textcolor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable-v21/md_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable-v21/md_btn_selector_dark.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable-v21/md_btn_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable-v21/md_item_selector.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 | -
9 |
10 |
-
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable-v21/md_item_selector_dark.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 | -
9 |
10 |
-
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable-v21/md_item_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_btn_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_btn_selected_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_btn_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_btn_selector_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_item_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_item_selected_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_item_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_item_selector_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_nav_back.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/core/src/main/res/drawable/md_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_dialog_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_dialog_stub_buttons.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
22 |
23 |
28 |
29 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_dialog_stub_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_dialog_stub_recyclerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_dialog_stub_scrollview.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_dialog_stub_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_listitem.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_listitem_multichoice.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/core/src/main/res/layout/md_listitem_singlechoice.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/core/src/main/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 446dp
5 |
6 |
7 |
--------------------------------------------------------------------------------
/core/src/main/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 564dp
5 |
6 |
7 |
--------------------------------------------------------------------------------
/core/src/main/res/values-sw720dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 496dp
5 |
6 |
--------------------------------------------------------------------------------
/core/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/core/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #33969696
5 | #40CBCBCB
6 |
7 | #E0E0E0
8 | #3B3C3F
9 |
10 | #818181
11 | #C2C2C2
12 |
13 |
14 |
--------------------------------------------------------------------------------
/core/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 356dp
5 | 4dp
6 | 52dp
7 | 32dp
8 |
9 | 20dp
10 | 24dp
11 | 16dp
12 | 24dp
13 |
14 | 52dp
15 | 7dp
16 | 8dp
17 | 8dp
18 | 4dp
19 | 12dp
20 | 4dp
21 |
22 | 64dp
23 | 2dp
24 | 14sp
25 |
26 | 48dp
27 |
28 | 20sp
29 | 16sp
30 |
31 | 16dp
32 | 42dp
33 |
34 | 12dp
35 | 8dp
36 | 16sp
37 | 48dp
38 | 6dp
39 | 24dp
40 | 0dp
41 |
42 | 16dp
43 | 4dp
44 | 1dp
45 |
46 |
47 |
--------------------------------------------------------------------------------
/datetime/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/datetime/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "datetime"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api project(':core')
8 | api deps.afollestad.date_picker
9 | compileOnly deps.androidx.annotations
10 |
11 | implementation deps.afollestad.dots_indicator
12 | implementation deps.kotlin.stdlib8
13 | }
14 |
--------------------------------------------------------------------------------
/datetime/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/DatePickerExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("unused")
17 |
18 | package com.afollestad.materialdialogs.datetime
19 |
20 | import android.R.string
21 | import androidx.annotation.CheckResult
22 | import com.afollestad.materialdialogs.MaterialDialog
23 | import com.afollestad.materialdialogs.WhichButton.POSITIVE
24 | import com.afollestad.materialdialogs.actions.setActionButtonEnabled
25 | import com.afollestad.materialdialogs.callbacks.onDismiss
26 | import com.afollestad.materialdialogs.customview.customView
27 | import com.afollestad.materialdialogs.datetime.internal.TimeChangeListener
28 | import com.afollestad.materialdialogs.datetime.utils.getDatePicker
29 | import com.afollestad.materialdialogs.datetime.utils.isFutureDate
30 | import com.afollestad.materialdialogs.utils.MDUtil.isLandscape
31 | import java.util.Calendar
32 |
33 | /**
34 | * Makes the dialog a date picker.
35 | */
36 | fun MaterialDialog.datePicker(
37 | minDate: Calendar? = null,
38 | maxDate: Calendar? = null,
39 | currentDate: Calendar? = null,
40 | requireFutureDate: Boolean = false,
41 | dateCallback: DateTimeCallback = null
42 | ): MaterialDialog {
43 | customView(
44 | R.layout.md_datetime_picker_date,
45 | noVerticalPadding = true,
46 | dialogWrapContent = windowContext.isLandscape()
47 | )
48 |
49 | check(minDate == null || currentDate == null || minDate.before(currentDate)) {
50 | "Your `minDate` must be less than `currentDate`."
51 | }
52 | check(maxDate == null || currentDate == null || maxDate.after(currentDate)) {
53 | "Your `maxDate` must be bigger than `currentDate`."
54 | }
55 |
56 | getDatePicker().apply {
57 | minDate?.let { setMinDate(it) }
58 | maxDate?.let { setMaxDate(it) }
59 | currentDate?.let { setDate(it) }
60 |
61 | addOnDateChanged { _, _ ->
62 | val isFutureDate = getDatePicker().isFutureDate()
63 | setActionButtonEnabled(
64 | POSITIVE,
65 | !requireFutureDate || isFutureDate
66 | )
67 | }
68 | }
69 |
70 | positiveButton(string.ok) {
71 | getDatePicker().getDate()?.let { datetime ->
72 | dateCallback?.invoke(it, datetime)
73 | }
74 | }
75 | negativeButton(string.cancel)
76 |
77 | if (requireFutureDate) {
78 | val changeListener = TimeChangeListener(windowContext, getDatePicker()) {
79 | val isFutureDate = it.isFutureDate()
80 | setActionButtonEnabled(
81 | POSITIVE,
82 | !requireFutureDate || isFutureDate
83 | )
84 | }
85 | onDismiss { changeListener.dispose() }
86 | }
87 |
88 | return this
89 | }
90 |
91 | /**
92 | * Gets the currently selected date from a date picker dialog.
93 | */
94 | @CheckResult fun MaterialDialog.selectedDate(): Calendar {
95 | return getDatePicker().getDate()!!
96 | }
97 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/TimePickerExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("unused")
17 |
18 | package com.afollestad.materialdialogs.datetime
19 |
20 | import androidx.annotation.CheckResult
21 | import com.afollestad.materialdialogs.MaterialDialog
22 | import com.afollestad.materialdialogs.WhichButton.POSITIVE
23 | import com.afollestad.materialdialogs.actions.setActionButtonEnabled
24 | import com.afollestad.materialdialogs.callbacks.onDismiss
25 | import com.afollestad.materialdialogs.customview.customView
26 | import com.afollestad.materialdialogs.datetime.internal.TimeChangeListener
27 | import com.afollestad.materialdialogs.datetime.utils.getTimePicker
28 | import com.afollestad.materialdialogs.datetime.utils.hour
29 | import com.afollestad.materialdialogs.datetime.utils.isFutureTime
30 | import com.afollestad.materialdialogs.datetime.utils.minute
31 | import com.afollestad.materialdialogs.datetime.utils.toCalendar
32 | import com.afollestad.materialdialogs.utils.MDUtil.isLandscape
33 | import java.util.Calendar
34 |
35 | /**
36 | * Makes the dialog a time picker.
37 | */
38 | fun MaterialDialog.timePicker(
39 | currentTime: Calendar? = null,
40 | requireFutureTime: Boolean = false,
41 | show24HoursView: Boolean = true,
42 | timeCallback: DateTimeCallback = null
43 | ): MaterialDialog {
44 | customView(
45 | R.layout.md_datetime_picker_time,
46 | noVerticalPadding = true,
47 | dialogWrapContent = windowContext.isLandscape()
48 | )
49 |
50 | with(getTimePicker()) {
51 | setIs24HourView(show24HoursView)
52 | if (currentTime != null) {
53 | hour(currentTime.get(Calendar.HOUR_OF_DAY))
54 | minute(currentTime.get(Calendar.MINUTE))
55 | }
56 | setOnTimeChangedListener { _, _, _ ->
57 | val isFutureTime = isFutureTime()
58 | setActionButtonEnabled(
59 | POSITIVE,
60 | !requireFutureTime || isFutureTime
61 | )
62 | }
63 | }
64 |
65 | positiveButton(android.R.string.ok) {
66 | timeCallback?.invoke(it, getTimePicker().toCalendar())
67 | }
68 | negativeButton(android.R.string.cancel)
69 |
70 | if (requireFutureTime) {
71 | val changeListener = TimeChangeListener(windowContext, getTimePicker()) {
72 | val isFutureTime = it.isFutureTime()
73 | setActionButtonEnabled(
74 | POSITIVE,
75 | !requireFutureTime || isFutureTime
76 | )
77 | }
78 | onDismiss { changeListener.dispose() }
79 | }
80 |
81 | return this
82 | }
83 |
84 | /**
85 | * Gets the currently selected time from a time picker dialog.
86 | */
87 | @CheckResult fun MaterialDialog.selectedTime(): Calendar {
88 | return getTimePicker().toCalendar()
89 | }
90 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/internal/DateTimePickerAdapter.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.datetime.internal
17 |
18 | import android.view.View
19 | import android.view.ViewGroup
20 | import androidx.viewpager.widget.PagerAdapter
21 | import com.afollestad.materialdialogs.datetime.R.id
22 |
23 | internal class DateTimePickerAdapter : PagerAdapter() {
24 |
25 | override fun instantiateItem(
26 | container: ViewGroup,
27 | position: Int
28 | ): Any {
29 | val resId = when (position) {
30 | 0 -> id.datetimeDatePicker
31 | 1 -> id.datetimeTimePicker
32 | else -> throw IllegalStateException("Unexpected position: $position")
33 | }
34 | return container.findViewById(resId)
35 | }
36 |
37 | override fun getCount(): Int = 2
38 |
39 | override fun isViewFromObject(
40 | view: View,
41 | `object`: Any
42 | ): Boolean = view === `object` as View
43 |
44 | override fun destroyItem(
45 | container: ViewGroup,
46 | position: Int,
47 | `object`: Any
48 | ) = Unit
49 | }
50 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/internal/TimeChangeListener.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.datetime.internal
17 |
18 | import android.content.BroadcastReceiver
19 | import android.content.Context
20 | import android.content.Intent
21 | import android.content.IntentFilter
22 | import java.util.Calendar
23 |
24 | /** @author Aidan Follestad (@afollestad) */
25 | internal class TimeChangeListener(
26 | private var context: Context?,
27 | private val argument: T?,
28 | private var onChange: ((arg: T) -> Unit)? = null
29 | ) {
30 | private var lastHour: Int = -1
31 | private var lastMinute: Int = -1
32 |
33 | private val receiver = object : BroadcastReceiver() {
34 | override fun onReceive(
35 | context: Context?,
36 | intent: Intent?
37 | ) {
38 | val now = Calendar.getInstance()
39 | val newHour = now.get(Calendar.HOUR_OF_DAY)
40 | val newMinute = now.get(Calendar.MINUTE)
41 |
42 | if (argument != null && (lastHour != newHour || lastMinute != newMinute)) {
43 | onChange?.invoke(argument)
44 | lastHour = newHour
45 | lastMinute = newMinute
46 | }
47 | }
48 | }
49 |
50 | init {
51 | requireNotNull(context)
52 | requireNotNull(argument)
53 | requireNotNull(onChange)
54 |
55 | val filter = IntentFilter().apply {
56 | addAction(Intent.ACTION_TIME_TICK)
57 | addAction(Intent.ACTION_TIMEZONE_CHANGED)
58 | addAction(Intent.ACTION_TIME_CHANGED)
59 | }
60 | context!!.registerReceiver(receiver, filter)
61 | }
62 |
63 | fun dispose() {
64 | context?.unregisterReceiver(receiver)
65 | context = null
66 | onChange = null
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/internal/WrapContentViewPager.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.datetime.internal
17 |
18 | import android.content.Context
19 | import android.util.AttributeSet
20 | import android.view.View
21 | import android.view.View.MeasureSpec.EXACTLY
22 | import android.view.View.MeasureSpec.UNSPECIFIED
23 | import androidx.viewpager.widget.ViewPager
24 | import com.afollestad.materialdialogs.utils.MDUtil.ifNotZero
25 |
26 | internal class WrapContentViewPager(
27 | context: Context,
28 | attrs: AttributeSet? = null
29 | ) : ViewPager(context, attrs) {
30 |
31 | override fun onMeasure(
32 | widthMeasureSpec: Int,
33 | heightMeasureSpec: Int
34 | ) {
35 | var newHeightSpec = heightMeasureSpec
36 |
37 | var maxChildHeight = 0
38 | forEachChild { child ->
39 | child.measure(
40 | widthMeasureSpec,
41 | MeasureSpec.makeMeasureSpec(0, UNSPECIFIED)
42 | )
43 |
44 | val h = child.measuredHeight
45 | if (h > maxChildHeight) {
46 | maxChildHeight = h
47 | }
48 | }
49 |
50 | val maxAllowedHeightFromParent = MeasureSpec.getSize(heightMeasureSpec)
51 | if (maxChildHeight > maxAllowedHeightFromParent) {
52 | maxChildHeight = maxAllowedHeightFromParent
53 | }
54 | maxChildHeight.ifNotZero {
55 | newHeightSpec = MeasureSpec.makeMeasureSpec(it, EXACTLY)
56 | }
57 |
58 | super.onMeasure(widthMeasureSpec, newHeightSpec)
59 | }
60 |
61 | private fun forEachChild(each: (View) -> Unit) {
62 | for (i in 0 until childCount) {
63 | val child = getChildAt(i)
64 | each(child)
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/utils/DateTimeExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.datetime.utils
17 |
18 | import android.widget.TimePicker
19 | import com.afollestad.date.DatePicker
20 | import java.util.Calendar
21 | import java.util.GregorianCalendar
22 |
23 | internal fun isFutureTime(
24 | datePicker: DatePicker,
25 | timePicker: TimePicker
26 | ): Boolean {
27 | val now = Calendar.getInstance()
28 | val dateTime = toCalendar(datePicker, timePicker)
29 | return dateTime.timeInMillis >= now.timeInMillis
30 | }
31 |
32 | internal fun TimePicker.isFutureTime(): Boolean {
33 | val now = Calendar.getInstance()
34 | return toCalendar().timeInMillis >= now.timeInMillis
35 | }
36 |
37 | internal fun DatePicker.isFutureDate(): Boolean {
38 | val now = Calendar.getInstance()
39 | return getDate()!!.timeInMillis >= now.timeInMillis
40 | }
41 |
42 | internal fun TimePicker.toCalendar(): Calendar {
43 | val now = Calendar.getInstance()
44 | return GregorianCalendar(
45 | now.get(Calendar.YEAR),
46 | now.get(Calendar.MONTH),
47 | now.get(Calendar.DAY_OF_MONTH),
48 | hour(),
49 | minute()
50 | )
51 | }
52 |
53 | internal fun toCalendar(
54 | datePicker: DatePicker,
55 | timePicker: TimePicker
56 | ): Calendar {
57 | return datePicker.getDate()!!.apply {
58 | set(Calendar.HOUR_OF_DAY, timePicker.hour())
59 | set(Calendar.MINUTE, timePicker.minute())
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/datetime/src/main/java/com/afollestad/materialdialogs/datetime/utils/ViewExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("DEPRECATION")
17 |
18 | package com.afollestad.materialdialogs.datetime.utils
19 |
20 | import android.os.Build
21 | import android.widget.TimePicker
22 | import androidx.viewpager.widget.ViewPager
23 | import com.afollestad.date.DatePicker
24 | import com.afollestad.materialdialogs.MaterialDialog
25 | import com.afollestad.materialdialogs.datetime.R
26 | import com.afollestad.viewpagerdots.DotsIndicator
27 |
28 | internal fun TimePicker.hour(): Int = if (isNougat()) hour else currentHour
29 |
30 | internal fun TimePicker.minute(): Int = if (isNougat()) minute else currentMinute
31 |
32 | internal fun TimePicker.hour(value: Int) {
33 | if (isNougat()) hour = value else currentHour = value
34 | }
35 |
36 | internal fun TimePicker.minute(value: Int) {
37 | if (isNougat()) minute = value else currentMinute = value
38 | }
39 |
40 | internal fun MaterialDialog.getDatePicker() = findViewById(R.id.datetimeDatePicker)
41 |
42 | internal fun MaterialDialog.getTimePicker() = findViewById(R.id.datetimeTimePicker)
43 |
44 | internal fun MaterialDialog.getPager() = findViewById(R.id.dateTimePickerPager)
45 |
46 | internal fun MaterialDialog.getPageIndicator() =
47 | findViewById(R.id.datetimePickerPagerDots)
48 |
49 | private fun isNougat() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
50 |
--------------------------------------------------------------------------------
/datetime/src/main/res-public/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/datetime/src/main/res/layout/md_datetime_picker_date.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/datetime/src/main/res/layout/md_datetime_picker_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/datetime/src/main/res/layout/md_datetime_picker_time.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/datetime/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 24dp
4 | 8dp
5 |
--------------------------------------------------------------------------------
/dependencies.gradle:
--------------------------------------------------------------------------------
1 | ext.versions = [
2 | min_sdk: 16,
3 | compile_sdk: 29,
4 | build_tools: "29.0.0",
5 | publish_version: "3.3.0",
6 | publish_version_code: 262
7 | ]
8 |
9 | ext.deps = [
10 | gradle_plugins: [
11 | android: "com.android.tools.build:gradle:4.1.2",
12 | kotlin: "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61",
13 | spotless: "com.diffplug.spotless:spotless-plugin-gradle:3.27.1",
14 | versions: "com.github.ben-manes:gradle-versions-plugin:0.27.0"
15 | ],
16 |
17 | androidx: [
18 | annotations: "androidx.annotation:annotation:1.1.0",
19 | core: "androidx.appcompat:appcompat:1.1.0",
20 | grid_layout: "androidx.gridlayout:gridlayout:1.0.0",
21 | lifecycle: [
22 | runtime: "androidx.lifecycle:lifecycle-runtime:2.2.0",
23 | compiler: "androidx.lifecycle:lifecycle-compiler:2.2.0"
24 | ],
25 | recycler_view: "androidx.recyclerview:recyclerview:1.1.0"
26 | ],
27 |
28 | google_material: "com.google.android.material:material:1.1.0",
29 |
30 | kotlin: [
31 | stdlib8: "org.jetbrains.kotlin:kotlin-stdlib-jdk8",
32 | coroutines: [
33 | android: "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
34 | ]
35 | ],
36 |
37 | afollestad: [
38 | assent: "com.afollestad:assent:2.3.1",
39 | dots_indicator: "com.afollestad:viewpagerdots:1.0.0",
40 | date_picker: "com.afollestad:date-picker:0.6.1"
41 | ],
42 |
43 | leak_canary: "com.squareup.leakcanary:leakcanary-android:2.2"
44 | ]
45 |
--------------------------------------------------------------------------------
/documentation/COLOR.md:
--------------------------------------------------------------------------------
1 | # Color
2 |
3 | # Table of Contents - Color
4 |
5 | 1. [Gradle Dependency](#gradle-dependency)
6 | 2. [Color Choosers](#color-choosers)
7 | 1. [Basics](#basics)
8 | 2. [Sub Colors](#sub-colors)
9 |
10 | ## Gradle Dependency
11 |
12 | [  ](https://repo1.maven.org/maven2/com/afollestad/material-dialogs/color)
13 |
14 | The `color` module contains extensions to the core module, such as a color chooser.
15 |
16 | ```gradle
17 | dependencies {
18 | ...
19 | implementation 'com.afollestad.material-dialogs:color:3.2.1'
20 | }
21 | ```
22 |
23 | ## Color Choosers
24 |
25 | ### Basics
26 |
27 | Color choosers show a simple grid of colors.
28 |
29 |
30 |
31 | ```kotlin
32 | val colors = intArrayOf(RED, GREEN, BLUE)
33 |
34 | MaterialDialog(this).show {
35 | title(R.string.colors)
36 | colorChooser(colors) { dialog, color ->
37 | // Use color integer
38 | }
39 | positiveButton(R.string.select)
40 | }
41 | ```
42 |
43 | You can specify an initial selection, which is just a color integer:
44 |
45 | ```kotlin
46 | val colors = intArrayOf(RED, GREEN, BLUE)
47 |
48 | MaterialDialog(this).show {
49 | title(R.string.colors)
50 | colorChooser(colors, initialSelection = BLUE) { dialog, color ->
51 | // Use color integer
52 | }
53 | positiveButton(R.string.select)
54 | }
55 | ```
56 |
57 | ### Sub Colors
58 |
59 | You can specify sub-colors, which are a level down from each top level color. The size of the top
60 | level array must match the size of the sub-colors array.
61 |
62 |
63 |
64 | ```kotlin
65 | val colors = intArrayOf(RED, GREEN, BLUE) // size = 3
66 |
67 | val subColors = listOf( // size = 3
68 | intArrayOf(LIGHT_RED, RED, DARK_RED, WHITE),
69 | intArrayOf(LIGHT_GREEN, GREEN, DARK_GREEN, GRAY),
70 | intArrayOf(LIGHT_BLUE, BLUE, DARK_BLUE, BLACK)
71 | )
72 |
73 | MaterialDialog(this).show {
74 | title(R.string.colors)
75 | colorChooser(colors, subColors = subColors) { dialog, color ->
76 | // Use color integer
77 | }
78 | positiveButton(R.string.select)
79 | }
80 | ```
81 |
82 | ### ARGB Selection
83 |
84 |
85 |
86 | ```kotlin
87 | MaterialDialog(this).show {
88 | title(R.string.colors)
89 | colorChooser(
90 | colors = colors,
91 | subColors = subColors,
92 | allowCustomArgb = true,
93 | showAlphaSelector = true
94 | ) { dialog, color ->
95 | // Use color integer
96 | }
97 | positiveButton(R.string.select)
98 | }
99 | ```
100 |
101 | Omitting `showAlphaSelector` will hide the alpha (transparency) selector.
102 |
--------------------------------------------------------------------------------
/documentation/DATETIME.md:
--------------------------------------------------------------------------------
1 | # DateTime
2 |
3 | ## Table of Contents
4 |
5 | 1. [Gradle Dependency](#gradle-dependency-4)
6 | 2. [Date](#date)
7 | 3. [Time](#time)
8 | 4. [DateTime](#datetime)
9 |
10 | ## Gradle Dependency
11 |
12 | [  ](https://repo1.maven.org/maven2/com/afollestad/material-dialogs/datetime)
13 |
14 | The `datetime` module contains extensions to make date, time, and date-time picker dialogs.
15 |
16 | ```gradle
17 | dependencies {
18 | ...
19 | implementation 'com.afollestad.material-dialogs:datetime:3.2.1'
20 | }
21 | ```
22 |
23 | ## Date
24 |
25 |
26 |
27 | ```kotlin
28 | MaterialDialog(this).show {
29 | ...
30 | datePicker { dialog, date ->
31 | // Use date (Calendar)
32 | }
33 | }
34 | ```
35 |
36 | You can optionally provide `minDate`, `maxDate` and `currentDate` parameters as well.
37 |
38 | ## Time
39 |
40 |
41 |
42 | ```kotlin
43 | MaterialDialog(this).show {
44 | ...
45 | timePicker { dialog, time ->
46 | // Use time (Calendar)
47 | }
48 | }
49 | ```
50 |
51 | You can optionally provide `currentTime` and `show24HoursView` parameters as well.
52 |
53 | ## DateTime
54 |
55 |
56 |
57 | ```kotlin
58 | MaterialDialog(this).show {
59 | ...
60 | dateTimePicker(requireFutureDateTime = true) { _, dateTime ->
61 | // Use dateTime (Calendar)
62 | }
63 | }
64 | ```
65 |
66 | You can optionally provide `minDateTime`, `maxDate`, `currentDateTime`, `show24HoursView`,
67 | and `requireFutureDateTime` parameters as well.
68 |
--------------------------------------------------------------------------------
/documentation/LIFECYCLE.md:
--------------------------------------------------------------------------------
1 | # Lifecycle
2 |
3 | ## Table of Contents
4 |
5 | 1. [Gradle Dependency](#gradle-dependency)
6 | 2. [Usage](#usage)
7 |
8 |
9 | ## Gradle Dependency
10 |
11 | [  ](https://repo1.maven.org/maven2/com/afollestad/material-dialogs/lifecycle)
12 |
13 | The `lifecycle` module contains extensions to make dialogs work with AndroidX lifecycles.
14 |
15 | ```gradle
16 | dependencies {
17 | ...
18 | implementation 'com.afollestad.material-dialogs:lifecycle:3.2.1'
19 | }
20 | ```
21 |
22 | ## Usage
23 |
24 | ```kotlin
25 | MaterialDialog(this).show {
26 | ...
27 | lifecycleOwner(owner)
28 | }
29 | ```
30 |
31 | When the given lifecycle owner is destroyed, the dialog is automatically dismissed. Lifecycle
32 | owners include Activities and Fragments from AndroidX, along with any class that implements the
33 | `LifecycleOwner` interface.
34 |
--------------------------------------------------------------------------------
/files/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/files/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "files"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api project(':core')
8 | api project(':input')
9 |
10 | implementation deps.kotlin.coroutines.android
11 | implementation deps.kotlin.stdlib8
12 | }
13 |
--------------------------------------------------------------------------------
/files/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/files/src/main/java/com/afollestad/materialdialogs/files/util/ContextExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.files.util
17 |
18 | import android.content.Context
19 | import java.io.File
20 |
21 | internal fun Context.getExternalFilesDir(): File? {
22 | return this.getExternalFilesDir(null)
23 | }
24 |
--------------------------------------------------------------------------------
/files/src/main/java/com/afollestad/materialdialogs/files/util/FilesUtilExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("SpellCheckingInspection")
17 |
18 | package com.afollestad.materialdialogs.files.util
19 |
20 | import android.Manifest.permission
21 | import android.content.Context
22 | import android.content.pm.PackageManager
23 | import androidx.core.content.ContextCompat
24 | import com.afollestad.materialdialogs.MaterialDialog
25 | import com.afollestad.materialdialogs.files.FileFilter
26 | import java.io.File
27 |
28 | internal fun File.hasParent(
29 | context: Context,
30 | writeable: Boolean,
31 | filter: FileFilter
32 | ) = betterParent(context, writeable, filter) != null
33 |
34 | internal fun File.isExternalStorage(context: Context) =
35 | absolutePath == context.getExternalFilesDir()?.absolutePath
36 |
37 | internal fun File.isRoot() = absolutePath == "/"
38 |
39 | internal fun File.betterParent(
40 | context: Context,
41 | writeable: Boolean,
42 | filter: FileFilter
43 | ): File? {
44 | val parentToUse = (if (isExternalStorage(context)) {
45 | // Emulated external storage's parent is empty so jump over it
46 | context.getExternalFilesDir()?.parentFile?.parentFile
47 | } else {
48 | parentFile
49 | }) ?: return null
50 |
51 | if ((writeable && !parentToUse.canWrite()) || !parentToUse.canRead()) {
52 | // We can't access this folder
53 | return null
54 | }
55 |
56 | val folderContent =
57 | parentToUse.listFiles()?.filter { filter?.invoke(it) ?: true } ?: emptyList()
58 | if (folderContent.isEmpty()) {
59 | // There is nothing in this folder most likely because we can't access files inside of it.
60 | // We don't want to get stuck here.
61 | return null
62 | }
63 |
64 | return parentToUse
65 | }
66 |
67 | internal fun File.jumpOverEmulated(context: Context): File {
68 | val externalFileDir = context.getExternalFilesDir()
69 | externalFileDir?.parentFile?.let { externalParentFile ->
70 | if (absolutePath == externalParentFile.absolutePath) {
71 | return externalFileDir
72 | }
73 | }
74 | return this
75 | }
76 |
77 | internal fun File.friendlyName(context: Context) = when {
78 | isExternalStorage(context) -> "External Storage"
79 | isRoot() -> "Root"
80 | else -> name
81 | }
82 |
83 | internal fun Context.hasPermission(permission: String): Boolean {
84 | return ContextCompat.checkSelfPermission(this, permission) ==
85 | PackageManager.PERMISSION_GRANTED
86 | }
87 |
88 | internal fun MaterialDialog.hasReadStoragePermission(): Boolean {
89 | return windowContext.hasPermission(permission.READ_EXTERNAL_STORAGE)
90 | }
91 |
92 | internal fun MaterialDialog.hasWriteStoragePermission(): Boolean {
93 | return windowContext.hasPermission(permission.WRITE_EXTERNAL_STORAGE)
94 | }
95 |
--------------------------------------------------------------------------------
/files/src/main/java/com/afollestad/materialdialogs/files/util/ViewExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.files.util
17 |
18 | import android.view.View
19 |
20 | internal fun T.setVisible(visible: Boolean) {
21 | visibility = if (visible) View.VISIBLE else View.INVISIBLE
22 | }
23 |
--------------------------------------------------------------------------------
/files/src/main/res-public/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_file_dark.xml:
--------------------------------------------------------------------------------
1 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_file_light.xml:
--------------------------------------------------------------------------------
1 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_folder_dark.xml:
--------------------------------------------------------------------------------
1 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_folder_light.xml:
--------------------------------------------------------------------------------
1 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_new_folder_dark.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_new_folder_light.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_return_dark.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/files/src/main/res/drawable/icon_return_light.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/files/src/main/res/layout/md_file_chooser_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/files/src/main/res/layout/md_file_chooser_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
26 |
27 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/files/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 18sp
4 | 32dp
5 | 8dp
6 | 22dp
7 | 12dp
8 | 16dp
9 |
10 |
--------------------------------------------------------------------------------
/files/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | This folder\'s empty!
4 | New Folder…
5 | New folder name
6 |
7 |
--------------------------------------------------------------------------------
/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 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
10 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
11 | org.gradle.jvmargs=-Xmx1536m
12 | # When configured, Gradle will run in incubating parallel mode.
13 | # This option should only be used with decoupled projects. More details, visit
14 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
15 | # org.gradle.parallel=true
16 | android.useAndroidX=true
17 |
--------------------------------------------------------------------------------
/gradle/android_application_config.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 | apply from: rootProject.file("gradle/android_common_config.gradle")
3 |
4 | if (module_package_id == null) {
5 | throw new IllegalStateException("module_package_id is missing!")
6 | }
7 |
8 | android.defaultConfig.applicationId = module_package_id.replace('-', '')
--------------------------------------------------------------------------------
/gradle/android_common_config.gradle:
--------------------------------------------------------------------------------
1 | ext.module_package_id = "${module_group}.${module_name}"
2 | logger.info("Package ID: $module_package_id")
3 |
4 | apply plugin: "kotlin-android"
5 | apply from: rootProject.file("dependencies.gradle")
6 | apply from: rootProject.file("gradle/spotless_plugin_config.gradle")
7 |
8 | android {
9 | compileSdkVersion versions.compile_sdk
10 | buildToolsVersion versions.build_tools
11 |
12 | compileOptions {
13 | sourceCompatibility 1.8
14 | targetCompatibility 1.8
15 | }
16 |
17 | defaultConfig {
18 | minSdkVersion versions.min_sdk
19 | targetSdkVersion versions.compile_sdk
20 | versionCode versions.publish_version_code
21 | versionName versions.publish_version
22 | }
23 |
24 | sourceSets {
25 | main.res.srcDirs = [
26 | "src/main/res",
27 | "src/main/res-public"
28 | ]
29 | }
30 |
31 | packagingOptions {
32 | exclude 'META-INF/atomicfu.kotlin_module'
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/gradle/android_library_config.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.library"
2 |
3 | apply from: rootProject.file("gradle/android_common_config.gradle")
4 | apply from: rootProject.file("gradle/android_publish_mavencentral.gradle")
5 |
--------------------------------------------------------------------------------
/gradle/spotless_plugin_config.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.diffplug.gradle.spotless"
2 | spotless {
3 | java {
4 | target "**/*.java"
5 | trimTrailingWhitespace()
6 | removeUnusedImports()
7 | googleJavaFormat()
8 | endWithNewline()
9 | }
10 | kotlin {
11 | target "**/*.kt"
12 | ktlint().userData(["indent_size": "2", "continuation_indent_size": "2"])
13 | licenseHeaderFile rootProject.file("spotless.license.kt")
14 | trimTrailingWhitespace()
15 | endWithNewline()
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle/versions_plugin_config.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.github.ben-manes.versions"
2 |
3 | dependencyUpdates.resolutionStrategy {
4 | componentSelection { rules ->
5 | rules.all { ComponentSelection selection ->
6 | boolean rejected = ['alpha', 'beta', 'rc', 'cr', 'm'].any { qualifier ->
7 | selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/
8 | }
9 | if (rejected) {
10 | selection.reject('Not stable')
11 | }
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
6 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/input/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/input/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "input"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api project(':core')
8 |
9 | implementation deps.google_material
10 | implementation deps.kotlin.stdlib8
11 | }
12 |
--------------------------------------------------------------------------------
/input/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/input/src/main/java/com/afollestad/materialdialogs/input/InputUtilExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogs.input
17 |
18 | import android.content.Context
19 | import android.view.View
20 | import android.view.inputmethod.InputMethodManager
21 | import com.afollestad.materialdialogs.MaterialDialog
22 | import com.afollestad.materialdialogs.WhichButton.POSITIVE
23 | import com.afollestad.materialdialogs.actions.setActionButtonEnabled
24 |
25 | internal fun MaterialDialog.invalidateInputMaxLength(allowEmpty: Boolean) {
26 | val currentLength = getInputField().text?.length ?: 0
27 | if (!allowEmpty && currentLength == 0) {
28 | return
29 | }
30 | val maxLength = getInputLayout().counterMaxLength
31 | if (maxLength > 0) {
32 | setActionButtonEnabled(POSITIVE, currentLength <= maxLength)
33 | }
34 | }
35 |
36 | internal fun MaterialDialog.showKeyboardIfApplicable() {
37 | getInputField().postRun {
38 | requestFocus()
39 | val imm =
40 | windowContext.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
41 | imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
42 | }
43 | }
44 |
45 | internal inline fun T.postRun(crossinline exec: T.() -> Unit) = this.post {
46 | this.exec()
47 | }
48 |
--------------------------------------------------------------------------------
/input/src/main/res-public/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/input/src/main/res/layout/md_dialog_stub_input.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/input/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16sp
4 |
5 |
--------------------------------------------------------------------------------
/lifecycle/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/lifecycle/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad.material-dialogs"
2 | ext.module_name = "lifecycle"
3 |
4 | apply from: rootProject.file("gradle/android_library_config.gradle")
5 |
6 | dependencies {
7 | api project(':core')
8 |
9 | implementation deps.kotlin.stdlib8
10 | implementation deps.androidx.lifecycle.runtime
11 | annotationProcessor deps.androidx.lifecycle.compiler
12 | }
13 |
--------------------------------------------------------------------------------
/lifecycle/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lifecycle/src/main/java/com/afollestad/materialdialogs/lifecycle/DialogLifecycleObserver.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("unused")
17 |
18 | package com.afollestad.materialdialogs.lifecycle
19 |
20 | import androidx.lifecycle.Lifecycle
21 | import androidx.lifecycle.LifecycleObserver
22 | import androidx.lifecycle.OnLifecycleEvent
23 |
24 | /** @author @jordyamc */
25 | internal class DialogLifecycleObserver(private val dismiss: () -> Unit) : LifecycleObserver {
26 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
27 | fun onDestroy() = dismiss()
28 | @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
29 | fun onPause() = dismiss()
30 | }
31 |
--------------------------------------------------------------------------------
/lifecycle/src/main/java/com/afollestad/materialdialogs/lifecycle/LifecycleExt.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | @file:Suppress("unused")
17 |
18 | package com.afollestad.materialdialogs.lifecycle
19 |
20 | import androidx.lifecycle.LifecycleOwner
21 | import com.afollestad.materialdialogs.MaterialDialog
22 |
23 | /**
24 | * Attach the dialog to a lifecycle and dismiss it when the lifecycle is destroyed.
25 | * Uses the given [owner] lifecycle if provided, else falls back to the Context of the dialog
26 | * window if it can.
27 | *
28 | * @param owner Optional lifecycle owner, if its null use windowContext.
29 | */
30 | fun MaterialDialog.lifecycleOwner(owner: LifecycleOwner? = null): MaterialDialog {
31 | val observer = DialogLifecycleObserver(::dismiss)
32 | val lifecycleOwner = owner ?: (windowContext as? LifecycleOwner
33 | ?: throw IllegalStateException(
34 | "$windowContext is not a LifecycleOwner."
35 | ))
36 | lifecycleOwner.lifecycle.addObserver(observer)
37 | return this
38 | }
39 |
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | ext.module_group = "com.afollestad"
2 | ext.module_name = "materialdialogssample"
3 |
4 | apply from: rootProject.file("gradle/android_application_config.gradle")
5 |
6 | android.defaultConfig.vectorDrawables.useSupportLibrary = true
7 |
8 | dependencies {
9 | implementation project(':core')
10 | implementation project(':input')
11 | implementation project(':files')
12 | implementation project(':color')
13 | implementation project(':datetime')
14 | implementation project(':bottomsheets')
15 | implementation project(':lifecycle')
16 |
17 | implementation deps.kotlin.stdlib8
18 |
19 | implementation deps.androidx.core
20 | implementation deps.androidx.grid_layout
21 | implementation deps.androidx.recycler_view
22 | implementation deps.google_material
23 |
24 | implementation deps.afollestad.assent
25 |
26 | debugImplementation deps.leak_canary
27 | }
28 |
--------------------------------------------------------------------------------
/sample/ic_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/ic_web.png
--------------------------------------------------------------------------------
/sample/sample.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/sample.apk
--------------------------------------------------------------------------------
/sample/src/debug/java/com/afollestad/materialdialogssample/SampleApp.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogssample
17 |
18 | import android.app.Application
19 | import leakcanary.LeakCanary
20 |
21 | /** @author Aidan Follestad (afollestad) */
22 | class SampleApp : Application() {
23 |
24 | override fun onCreate() {
25 | super.onCreate()
26 | LeakCanary.config = LeakCanary.config.copy(retainedVisibleThreshold = 3)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/Debouncer.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogssample
17 |
18 | import android.view.View
19 |
20 | internal object Debouncer {
21 | @Volatile private var enabled: Boolean = true
22 | private val enableAgain = Runnable { enabled = true }
23 |
24 | fun canPerform(view: View): Boolean {
25 | if (enabled) {
26 | enabled = false
27 | view.post(enableAgain)
28 | return true
29 | }
30 | return false
31 | }
32 | }
33 |
34 | internal fun T.onClickDebounced(click: (view: T) -> Unit) {
35 | setOnClickListener {
36 | if (Debouncer.canPerform(it)) {
37 | @Suppress("UNCHECKED_CAST")
38 | click(it as T)
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/afollestad/materialdialogssample/Utils.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogssample
17 |
18 | import android.app.Activity
19 | import android.content.SharedPreferences
20 | import android.widget.Toast
21 | import java.text.SimpleDateFormat
22 | import java.util.Calendar
23 | import java.util.Locale
24 |
25 | private var toast: Toast? = null
26 |
27 | internal fun Activity.toast(message: CharSequence) {
28 | toast?.cancel()
29 | toast = Toast.makeText(this, message, Toast.LENGTH_SHORT)
30 | .apply { show() }
31 | }
32 |
33 | typealias PrefEditor = SharedPreferences.Editor
34 |
35 | internal fun SharedPreferences.boolean(
36 | key: String,
37 | defaultValue: Boolean = false
38 | ): Boolean {
39 | return getBoolean(key, defaultValue)
40 | }
41 |
42 | internal inline fun SharedPreferences.commit(crossinline exec: PrefEditor.() -> Unit) {
43 | val editor = this.edit()
44 | editor.exec()
45 | editor.apply()
46 | }
47 |
48 | internal fun Int.toHex() = "#${Integer.toHexString(this)}"
49 |
50 | internal fun Calendar.formatTime(): String {
51 | return SimpleDateFormat("kk:mm a", Locale.US).format(this.time)
52 | }
53 |
54 | internal fun Calendar.formatDate(): String {
55 | return SimpleDateFormat("MMMM dd, yyyy", Locale.US).format(this.time)
56 | }
57 |
58 | internal fun Calendar.formatDateTime(): String {
59 | return SimpleDateFormat("kk:mm a, MMMM dd, yyyy", Locale.US).format(this.time)
60 | }
61 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/ic_icon_android.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/sample/src/main/res/font/raleway_bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/font/raleway_bold.ttf
--------------------------------------------------------------------------------
/sample/src/main/res/font/raleway_medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/font/raleway_medium.ttf
--------------------------------------------------------------------------------
/sample/src/main/res/font/raleway_semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/font/raleway_semibold.ttf
--------------------------------------------------------------------------------
/sample/src/main/res/layout/custom_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
26 |
27 |
35 |
36 |
44 |
45 |
53 |
54 |
62 |
63 |
71 |
72 |
83 |
84 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/custom_view_webview.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
15 |
16 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/afollestad/material-dialogs/709cfee9b45257af7ab4c428e4850bee38a075e7/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/values-v21/styles_parent.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - Twitter
6 | - Google+
7 | - Instagram
8 | - Facebook
9 |
10 |
11 |
12 | - Twitter is an online social networking service that enables users to send and read short 140-character messages called "tweets".
13 | - Google+ is an interest-based social network that is owned and operated by Google Inc. The service is Google\'s fourth foray into social networking.
14 | - Instagram is an online mobile photo-sharing, video-sharing and social networking service that enables its users to take pictures and videos, and share them on a variety of social networking platforms.
15 | - Facebook is an online social networking service headquartered in Menlo Park, California. Its website was launched on February 4, 2004, by Mark Zuckerberg with friends.
16 |
17 |
18 |
19 | - Alabama
20 | - Alaska
21 | - American Samoa
22 | - Arizona
23 | - Arkansas
24 | - California
25 | - Colorado
26 | - Connecticut
27 | - Delaware
28 | - District of Columbia
29 | - Florida
30 | - Georgia
31 | - Guam
32 | - Hawaii
33 | - Idaho
34 | - Illinois
35 | - Indiana
36 | - Iowa
37 | - Kansas
38 | - Kentucky
39 | - Louisiana
40 | - Maine
41 | - Maryland
42 | - Massachusetts
43 | - Michigan
44 | - Minnesota
45 | - Mississippi
46 | - Missouri
47 | - Montana
48 | - Nebraska
49 | - Nevada
50 | - New Hampshire
51 | - New Jersey
52 | - New Mexico
53 | - New York
54 | - North Carolina
55 | - North Dakota
56 | - Northern Marianas Islands
57 | - Ohio
58 | - Oklahoma
59 | - Oregon
60 | - Pennsylvania
61 | - Puerto Rico
62 | - Rhode Island
63 | - South Carolina
64 | - South Dakota
65 | - Tennessee
66 | - Texas
67 | - Utah
68 | - Vermont
69 | - Virginia
70 | - Virgin Islands
71 | - Washington
72 | - West Virginia
73 | - Wisconsin
74 | - Wyoming
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #6002ee
7 | #5002c7
8 | #9c47ff
9 |
10 | #607D8B
11 | #546E7A
12 | #388E3C
13 | #40388E3C
14 |
15 |
16 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 2dp
6 | 20sp
7 | 16dp
8 | 12dp
9 |
10 | 56dp
11 |
12 |
13 | 14sp
14 | 18sp
15 |
16 |
17 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #6002EE
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Material Dialogs
4 |
5 | Agree
6 | Disagree
7 | More Info
8 |
9 | Choose
10 |
11 | This app wants to access your location.
12 | Use Google\'s Location Services?
13 | Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
14 | Material Dialogs is a library designed and developed by
16 | Aidan Follestad. As of 2018, Aidan currently works
17 | on the Square Device Experience team at Square.
18 | Thanks for using Material Dialogs!
19 | ]]>
20 | Social Networks
21 | States
22 |
23 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae metus nec sapien
24 | elementum interdum ac mollis tortor. Nunc porttitor metus placerat orci auctor, sed dictum
25 | magna dapibus. Morbi a lacus ante. Cum sociis natoque penatibus et magnis dis parturient montes,
26 | nascetur ridiculus mus. Proin posuere nisl imperdiet lectus elementum accumsan. Etiam lacinia
27 | nisi ut nulla fermentum tempus. Integer ornare lacinia diam non maximus. Vestibulum iaculis urna
28 | eu elementum scelerisque. Etiam nisl erat, bibendum vitae magna nec, convallis malesuada erat.
29 | Cras non porttitor nibh. Pellentesque rhoncus sem luctus felis tincidunt bibendum. Pellentesque
30 | vulputate eros at nulla sollicitudin volutpat. Pellentesque laoreet est sit amet erat laoreet,
31 | id molestie nulla efficitur. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed
32 | varius nisl at imperdiet facilisis. Nam in elit sit amet metus dignissim aliquam. Nulla et ante
33 | molestie, lobortis velit accumsan, ornare massa. Praesent scelerisque quam ipsum, et feugiat
34 | ante aliquet eget. Aenean ultricies vulputate sem.
35 |
36 | I understand what this means
37 |
38 |
39 | Signal strength
40 | Excellent
41 | Security
42 | 802.1x EAP
43 | Password
44 | SSID
45 | Material Dialogs
46 | Show password
47 | Google Wifi
48 | Connect
49 |
50 |
51 | Primary Colors
52 | Accent Colors
53 | Custom Colors
54 | Custom RGB
55 | Custom ARGB
56 |
57 |
58 | Select
59 |
60 |
61 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
17 |
18 |
34 |
35 |
47 |
48 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles_parent.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/sample/src/release/java/com/afollestad/materialdialogssample/SampleApp.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.afollestad.materialdialogssample
17 |
18 | import android.app.Application
19 |
20 | /**
21 | * This does nothing in main variants. In debug, we configure leak canary.
22 | *
23 | * @author Aidan Follestad (afollestad) \
24 | */
25 | class SampleApp : Application()
26 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':core', ':sample', ':files', ':color', ':input', ':lifecycle', ':datetime', ':bottomsheets'
2 |
--------------------------------------------------------------------------------
/spotless.license.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Designed and developed by Aidan Follestad (@afollestad)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
--------------------------------------------------------------------------------