├── .github ├── release-drafter.yml └── workflows │ ├── build.yml │ ├── deploy_docs.yml │ └── update-release.yml ├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── misc.xml └── vcs.xml ├── ASSETS_LICENSE ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── USAGE.md ├── build.gradle ├── buildSrc ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── google │ └── android │ └── material │ └── composethemeadapter │ └── dependencies.kt ├── checksum.sh ├── core ├── api │ └── core.api ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── google │ │ └── android │ │ └── material │ │ └── composethemeadapter │ │ └── core │ │ └── ResourceUtils.kt │ └── res │ └── values │ └── theme_attrs.xml ├── docs ├── favicon.ico ├── header.png ├── logo.svg ├── m3header.png └── using-snapshot-version.md ├── generate_docs.sh ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── material3Lib ├── api │ └── material3Lib.api ├── build.gradle ├── gradle.properties └── src │ ├── androidTest │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ └── material │ │ │ └── composethemeadapter3 │ │ │ └── test │ │ │ ├── Mdc3Activity.kt │ │ │ ├── Mdc3ThemeTest.kt │ │ │ ├── NotMdc3Activity.kt │ │ │ └── NotMdc3ThemeTest.kt │ └── res │ │ ├── font │ │ ├── rubik.xml │ │ ├── rubik_300.ttf │ │ ├── rubik_400.ttf │ │ ├── rubik_500.ttf │ │ └── rubik_700.ttf │ │ └── values │ │ ├── styles.xml │ │ ├── test_colors.xml │ │ ├── themes.xml │ │ └── type.xml │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── google │ │ └── android │ │ └── material │ │ └── composethemeadapter3 │ │ └── Mdc3Theme.kt │ └── res │ └── values │ └── theme_attrs.xml ├── materialLib ├── api │ └── materialLib.api ├── build.gradle ├── gradle.properties └── src │ ├── androidTest │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ └── material │ │ │ └── composethemeadapter │ │ │ └── test │ │ │ ├── DarkMdcActivity.kt │ │ │ ├── DarkTheme.kt │ │ │ ├── DefaultFontFamilyMdcActivity.kt │ │ │ ├── DefaultFontFamilyMdcThemeTest.kt │ │ │ ├── LightMdcActivity.kt │ │ │ ├── MdcThemeTest.kt │ │ │ ├── NotMdcActivity.kt │ │ │ └── NotMdcThemeTest.kt │ └── res │ │ ├── font │ │ ├── rubik.xml │ │ ├── rubik_300.ttf │ │ ├── rubik_400.ttf │ │ ├── rubik_500.ttf │ │ └── rubik_700.ttf │ │ └── values │ │ ├── styles.xml │ │ ├── test_colors.xml │ │ ├── themes.xml │ │ └── type.xml │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── google │ │ └── android │ │ └── material │ │ └── composethemeadapter │ │ ├── MdcTheme.kt │ │ └── Typography.kt │ └── res │ └── values │ └── theme_attrs.xml ├── mkdocs.yml ├── sample ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── google │ │ └── android │ │ └── material │ │ └── composethemeadapter │ │ └── sample │ │ ├── MainActivity.kt │ │ ├── Material3Integration.kt │ │ └── MaterialIntegration.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── font │ ├── dancingscript.xml │ ├── dancingscript_bold.ttf │ ├── dancingscript_medium.ttf │ ├── dancingscript_regular.ttf │ └── dancingscript_semibold.ttf │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── shape.xml │ ├── strings.xml │ ├── themes.xml │ └── type.xml ├── settings.gradle └── spotless └── copyright.txt /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$NEXT_PATCH_VERSION' 2 | tag-template: 'v$NEXT_PATCH_VERSION' 3 | template: | 4 | ## What’s Changed 5 | $CHANGES -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | paths-ignore: 8 | - '**.md' 9 | pull_request: 10 | paths-ignore: 11 | - '**.md' 12 | 13 | jobs: 14 | build: 15 | # Skip build if head commit contains 'skip ci' 16 | if: "!contains(github.event.head_commit.message, 'skip ci')" 17 | 18 | runs-on: ubuntu-latest 19 | env: 20 | JAVA_TOOL_OPTIONS: -Xmx5120m 21 | GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2 -Dkotlin.compiler.execution.strategy=in-process 22 | TERM: dumb 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | 27 | - name: set up JDK 11 28 | uses: actions/setup-java@v1 29 | with: 30 | java-version: 11 31 | 32 | - name: Generate cache key 33 | run: ./checksum.sh checksum.txt 34 | 35 | - uses: actions/cache@v2 36 | with: 37 | path: | 38 | ~/.gradle/caches/modules-* 39 | ~/.gradle/caches/jars-* 40 | ~/.gradle/caches/build-cache-* 41 | key: gradle-${{ hashFiles('checksum.txt') }} 42 | 43 | - name: Build, lint and spotless 44 | run: ./gradlew spotlessCheck assemble lintDebug apiCheck --scan 45 | 46 | test: 47 | runs-on: macOS-latest 48 | needs: build 49 | strategy: 50 | matrix: 51 | api-level: [23, 26, 29] 52 | env: 53 | JAVA_TOOL_OPTIONS: -Xmx3072m 54 | GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2 -Dkotlin.compiler.execution.strategy=in-process 55 | TERM: dumb 56 | 57 | steps: 58 | - uses: actions/checkout@v2 59 | 60 | - name: set up JDK 11 61 | uses: actions/setup-java@v1 62 | with: 63 | java-version: 11 64 | 65 | - name: Generate cache key 66 | run: ./checksum.sh checksum.txt 67 | 68 | - uses: actions/cache@v2 69 | with: 70 | path: | 71 | ~/.gradle/caches/modules-* 72 | ~/.gradle/caches/jars-* 73 | ~/.gradle/caches/build-cache-* 74 | key: gradle-${{ hashFiles('checksum.txt') }} 75 | 76 | - name: Run tests 77 | uses: reactivecircus/android-emulator-runner@v2 78 | with: 79 | api-level: ${{ matrix.api-level }} 80 | script: ./gradlew connectedCheck 81 | 82 | - name: Copy test results 83 | if: always() 84 | run: | 85 | mkdir -p junit 86 | find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} junit/ \; 87 | - name: Upload test results 88 | if: always() 89 | uses: actions/upload-artifact@v1 90 | with: 91 | name: junit-results 92 | path: junit 93 | 94 | deploy: 95 | if: github.event_name == 'push' # only deploy for pushed commits (not PRs) 96 | runs-on: ubuntu-latest 97 | needs: [build, test] 98 | env: 99 | JAVA_TOOL_OPTIONS: -Xmx5120m 100 | GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2 -Dkotlin.compiler.execution.strategy=in-process 101 | TERM: dumb 102 | 103 | steps: 104 | - uses: actions/checkout@v2 105 | 106 | - name: set up JDK 11 107 | uses: actions/setup-java@v1 108 | with: 109 | java-version: 11 110 | 111 | - name: Generate cache key 112 | run: ./checksum.sh checksum.txt 113 | 114 | - uses: actions/cache@v2 115 | with: 116 | path: | 117 | ~/.gradle/caches/modules-* 118 | ~/.gradle/caches/jars-* 119 | ~/.gradle/caches/build-cache-* 120 | key: gradle-${{ hashFiles('checksum.txt') }} 121 | 122 | - name: Remove current local Maven repo if it exists 123 | continue-on-error: true 124 | working-directory: ~/.m2 125 | run: rm -rf * 126 | 127 | - name: Build docs 128 | # We manually run assemble & dokka before uploadArchives. If we only run uploadArchives, 129 | # the assemble and dokka tasks are run interleaved on each module, which can cause 130 | # connection timeouts while uploading (since we need to wait for assemble+dokka to finish). 131 | # By front-loading the assemble+dokka tasks, the upload below is much quicker. 132 | run: ./gradlew assembleRelease dokkaGfm 133 | 134 | - name: Install to local Maven repo 135 | run: ./gradlew installArchives 136 | 137 | - uses: actions/upload-artifact@v2 138 | with: 139 | name: maven-release 140 | path: ~/.m2/repository 141 | 142 | # - name: Deploy to GitHub packages 143 | # run: ./gradlew uploadArchives --no-parallel 144 | # env: 145 | # SONATYPE_NEXUS_USERNAME: ${{ github.repository_owner }} 146 | # SONATYPE_NEXUS_PASSWORD: ${{ secrets.GITHUB_TOKEN }} 147 | -------------------------------------------------------------------------------- /.github/workflows/deploy_docs.yml: -------------------------------------------------------------------------------- 1 | name: Publish docs 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | jobs: 9 | deploy_docs: 10 | runs-on: ubuntu-latest 11 | env: 12 | JAVA_TOOL_OPTIONS: -Xmx5120m 13 | GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2 -Dkotlin.compiler.execution.strategy=in-process 14 | TERM: dumb 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Setup JDK 11 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 11 23 | 24 | - name: Setup Python 25 | uses: actions/setup-python@v2 26 | with: 27 | python-version: '3.x' 28 | 29 | - name: Install dependencies 30 | run: | 31 | python3 -m pip install --upgrade pip 32 | python3 -m pip install mkdocs 33 | python3 -m pip install mkdocs-material 34 | 35 | - name: Generate docs 36 | run: ./generate_docs.sh 37 | 38 | - name: Build site 39 | run: mkdocs build 40 | 41 | - name: Deploy 42 | uses: peaceiris/actions-gh-pages@v3 43 | with: 44 | github_token: ${{ secrets.GITHUB_TOKEN }} 45 | publish_dir: ./site 46 | -------------------------------------------------------------------------------- /.github/workflows/update-release.yml: -------------------------------------------------------------------------------- 1 | name: Update release 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | 8 | jobs: 9 | update_draft_release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: release-drafter/release-drafter@v5 13 | env: 14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Temporary API docs 8 | docs/api 9 | # These are generated from files in the root folder 10 | docs/index.md 11 | docs/contributing.md 12 | # Mkdocs temporary serving folder 13 | site 14 | 15 | # Files for the ART/Dalvik VM 16 | *.dex 17 | 18 | # Java class files 19 | *.class 20 | 21 | # Generated files 22 | bin/ 23 | gen/ 24 | out/ 25 | # Uncomment the following line in case you need and you don't have the release build type files in your app 26 | # release/ 27 | 28 | # Gradle files 29 | .gradle/ 30 | build/ 31 | 32 | # Local configuration file (sdk path, etc) 33 | local.properties 34 | 35 | # Proguard folder generated by Eclipse 36 | proguard/ 37 | 38 | # Log Files 39 | *.log 40 | 41 | # Android Studio Navigation editor temp files 42 | .navigation/ 43 | 44 | # Android Studio captures folder 45 | captures/ 46 | 47 | # IntelliJ 48 | *.iml 49 | .idea/workspace.xml 50 | .idea/tasks.xml 51 | .idea/gradle.xml 52 | .idea/assetWizardSettings.xml 53 | .idea/dictionaries 54 | .idea/libraries 55 | .idea/compiler.xml 56 | .idea/jarRepositories.xml 57 | # Android Studio 3 in .gitignore file. 58 | .idea/caches 59 | .idea/modules.xml 60 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 61 | .idea/navEditor.xml 62 | 63 | # Keystore files 64 | # Uncomment the following lines if you do not want to check your keystore files in. 65 | #*.jks 66 | #*.keystore 67 | 68 | # External native build folder generated in Android Studio 2.2 and later 69 | .externalNativeBuild 70 | .cxx/ 71 | 72 | # Google Services (e.g. APIs or Firebase) 73 | # google-services.json 74 | 75 | # Freeline 76 | freeline.py 77 | freeline/ 78 | freeline_project_description.json 79 | 80 | # fastlane 81 | fastlane/report.xml 82 | fastlane/Preview.html 83 | fastlane/screenshots 84 | fastlane/test_output 85 | fastlane/readme.md 86 | 87 | # Version control 88 | vcs.xml 89 | 90 | # lint 91 | lint/intermediates/ 92 | lint/generated/ 93 | lint/outputs/ 94 | lint/tmp/ 95 | # lint/reports/ 96 | 97 | # General 98 | .DS_Store -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 116 | 117 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ASSETS_LICENSE: -------------------------------------------------------------------------------- 1 | All font files are licensed under the SIL OPEN FONT LICENSE license. All other files are licensed under the Apache 2 license. 2 | 3 | 4 | SIL OPEN FONT LICENSE 5 | Version 1.1 - 26 February 2007 6 | 7 | PREAMBLE 8 | The goals of the Open Font License (OFL) are to stimulate worldwide 9 | development of collaborative font projects, to support the font creation 10 | efforts of academic and linguistic communities, and to provide a free and 11 | open framework in which fonts may be shared and improved in partnership 12 | with others. 13 | 14 | The OFL allows the licensed fonts to be used, studied, modified and 15 | redistributed freely as long as they are not sold by themselves. The 16 | fonts, including any derivative works, can be bundled, embedded, 17 | redistributed and/or sold with any software provided that any reserved 18 | names are not used by derivative works. The fonts and derivatives, 19 | however, cannot be released under any other type of license. The 20 | requirement for fonts to remain under this license does not apply 21 | to any document created using the fonts or their derivatives. 22 | 23 | DEFINITIONS 24 | "Font Software" refers to the set of files released by the Copyright 25 | Holder(s) under this license and clearly marked as such. This may 26 | include source files, build scripts and documentation. 27 | 28 | "Reserved Font Name" refers to any names specified as such after the 29 | copyright statement(s). 30 | 31 | "Original Version" refers to the collection of Font Software components as 32 | distributed by the Copyright Holder(s). 33 | 34 | "Modified Version" refers to any derivative made by adding to, deleting, 35 | or substituting — in part or in whole — any of the components of the 36 | Original Version, by changing formats or by porting the Font Software to a 37 | new environment. 38 | 39 | "Author" refers to any designer, engineer, programmer, technical 40 | writer or other person who contributed to the Font Software. 41 | 42 | PERMISSION & CONDITIONS 43 | Permission is hereby granted, free of charge, to any person obtaining 44 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 45 | redistribute, and sell modified and unmodified copies of the Font 46 | Software, subject to the following conditions: 47 | 48 | 1) Neither the Font Software nor any of its individual components, 49 | in Original or Modified Versions, may be sold by itself. 50 | 51 | 2) Original or Modified Versions of the Font Software may be bundled, 52 | redistributed and/or sold with any software, provided that each copy 53 | contains the above copyright notice and this license. These can be 54 | included either as stand-alone text files, human-readable headers or 55 | in the appropriate machine-readable metadata fields within text or 56 | binary files as long as those fields can be easily viewed by the user. 57 | 58 | 3) No Modified Version of the Font Software may use the Reserved Font 59 | Name(s) unless explicit written permission is granted by the corresponding 60 | Copyright Holder. This restriction only applies to the primary font name as 61 | presented to the users. 62 | 63 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 64 | Software shall not be used to promote, endorse or advertise any 65 | Modified Version, except to acknowledge the contribution(s) of the 66 | Copyright Holder(s) and the Author(s) or with their explicit written 67 | permission. 68 | 69 | 5) The Font Software, modified or unmodified, in part or in whole, 70 | must be distributed entirely under this license, and must not be 71 | distributed under any other license. The requirement for fonts to 72 | remain under this license does not apply to any document created 73 | using the Font Software. 74 | 75 | TERMINATION 76 | This license becomes null and void if any of the above conditions are 77 | not met. 78 | 79 | DISCLAIMER 80 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 81 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 82 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 83 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 84 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 85 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 86 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 87 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 88 | OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MDC-Android Compose Theme Adapter 2 | 3 | ## Deprecated 4 | 5 | **Material Theme Adapter is deprecated. Use the Material Theme Builder tool, to generate a matching XML and Compose theme implementation for your app. See [Migrating XML themes to Compose][migratexmltocompose] to learn more.** 6 | 7 | ## License 8 | 9 | ``` 10 | Copyright 2020 The Android Open Source Project 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at 15 | 16 | https://www.apache.org/licenses/LICENSE-2.0 17 | 18 | Unless required by applicable law or agreed to in writing, software 19 | distributed under the License is distributed on an "AS IS" BASIS, 20 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | See the License for the specific language governing permissions and 22 | limitations under the License. 23 | ``` 24 | [migratexmltocompose]: https://developer.android.com/jetpack/compose/designsystems/views-to-compose 25 | [compose]: https://developer.android.com/jetpack/compose 26 | [mdc]: https://github.com/material-components/material-components-android 27 | [appcompat]: https://developer.android.com/jetpack/androidx/releases/appcompat 28 | [materialtheme]: https://developer.android.com/reference/kotlin/androidx/compose/material/MaterialTheme 29 | [colors]: https://developer.android.com/reference/kotlin/androidx/compose/material/Colors 30 | [typography]: https://developer.android.com/reference/kotlin/androidx/compose/material/Typography 31 | [shapes]: https://developer.android.com/reference/kotlin/androidx/compose/material/Shapes 32 | [m3materialtheme]: https://developer.android.com/reference/kotlin/androidx/compose/material3/MaterialTheme 33 | [m3colorscheme]: https://developer.android.com/reference/kotlin/androidx/compose/material3/ColorScheme 34 | [m3shapes]: https://developer.android.com/reference/kotlin/androidx/compose/material3/Shapes 35 | [m3typography]: https://developer.android.com/reference/kotlin/androidx/compose/material3/Typography 36 | [accompanist]: https://github.com/google/accompanist 37 | [themeadaptermateriallib]: https://google.github.io/accompanist/themeadapter-material 38 | [themeadaptermaterial3lib]: https://google.github.io/accompanist/themeadapter-material3 39 | [themeadaptercorelib]: https://google.github.io/accompanist/themeadapter-core 40 | -------------------------------------------------------------------------------- /USAGE.md: -------------------------------------------------------------------------------- 1 | ## Library Docs 2 | 3 | A library that enables reuse of [Material Components for Android][mdc] XML themes for theming in [Jetpack Compose][compose]. 4 | 5 | ## Usage 6 | 7 | There are two artifacts available: 8 | 9 | * [`com.google.android.material:compose-theme-adapter`](#compose-material) 10 | * Compatible with Compose Material 11 | * Includes `MdcTheme` 12 | * [`com.google.android.material:compose-theme-adapter-3`](#compose-material-3) 13 | * Compatible with Compose Material 3 14 | * Includes `Mdc3Theme` 15 | 16 | ```groovy 17 | repositories { 18 | google() 19 | } 20 | 21 | dependencies { 22 | // Compatible with Compose Material, includes MdcTheme 23 | implementation "com.google.android.material:compose-theme-adapter:" 24 | // Compatible with Compose Material 3, includes Mdc3Theme 25 | implementation "com.google.android.material:compose-theme-adapter-3:" 26 | } 27 | ``` 28 | 29 | See the [releases](https://github.com/material-components/material-components-android-compose-theme-adapter/releases) page for the latest versions. 30 | 31 | --- 32 | 33 | ## Compose Material 34 | 35 | ![MDC-Android Compose Theme Adapter header](docs/header.png) 36 | 37 | The basis of Material Design 2 theming in [Jetpack Compose][compose] is the [`MaterialTheme`][materialtheme] composable, where you provide [`Colors`][colors], [`Typography`][typography] and [`Shapes`][shapes] instances containing your styling parameters: 38 | 39 | ``` kotlin 40 | MaterialTheme( 41 | colors = colors, 42 | typography = type, 43 | shapes = shapes 44 | ) { 45 | // M2 Surface, Scaffold, etc. 46 | } 47 | ``` 48 | 49 | [Material Components for Android][mdc] themes allow for similar theming for views via XML theme attributes, like so: 50 | 51 | ``` xml 52 | 64 | ``` 65 | 66 | This library attempts to bridge the gap between [Material Components for Android][mdc] M2 XML themes, and themes in [Jetpack Compose][compose], allowing your composable [`MaterialTheme`][materialtheme] to be based on the `Activity`'s XML theme: 67 | 68 | 69 | ``` kotlin 70 | MdcTheme { 71 | // MaterialTheme.colors, MaterialTheme.typography, MaterialTheme.shapes 72 | // will now contain copies of the Context's theme 73 | } 74 | ``` 75 | 76 | This is especially handy when you're migrating an existing app, a `Fragment` (or other UI container) at a time. 77 | 78 | !!! caution 79 | If you are using an AppCompat (i.e. non-MDC) theme in your app, you should use 80 | [AppCompat Compose Theme Adapter](https://github.com/google/accompanist/tree/main/appcompat-theme) 81 | instead, as it attempts to bridge the gap between [AppCompat][appcompat] XML themes, and M2 themes in [Jetpack Compose][compose]. 82 | 83 | ### Customizing the M2 theme 84 | 85 | The `MdcTheme()` function will automatically read the host `Context`'s MDC theme and pass them to [`MaterialTheme`][materialtheme] on your behalf, but if you want to customize the generated values, you can do so via the `createMdcTheme()` function: 86 | 87 | ``` kotlin 88 | val context = LocalContext.current 89 | val layoutDirection = LocalLayoutDirection.current 90 | var (colors, typography, shapes) = createMdcTheme( 91 | context = context, 92 | layoutDirection = layoutDirection 93 | ) 94 | 95 | // Modify colors, typography or shapes as required. 96 | // Then pass them through to MaterialTheme... 97 | 98 | MaterialTheme( 99 | colors = colors, 100 | typography = type, 101 | shapes = shapes 102 | ) { 103 | // Rest of M2 layout 104 | } 105 | ``` 106 | 107 | ### Limitations 108 | 109 | There are some known limitations with the implementation at the moment: 110 | 111 | * This relies on your `Activity`/`Context` theme extending one of the `Theme.MaterialComponents` themes. 112 | * Text colors are not read from the text appearances by default. You can enable it via the `setTextColors` function parameter. 113 | * Variable fonts are not supported in Compose yet, meaning that the value of `android:fontVariationSettings` are currently ignored. 114 | * MDC `ShapeAppearances` allow setting of different corner families (cut, rounded) on each corner, whereas Compose's [Shapes][shapes] allows only a single corner family for the entire shape. Therefore only the `app:cornerFamily` attribute is read, others (`app:cornerFamilyTopLeft`, etc) are ignored. 115 | * You can modify the resulting `MaterialTheme` in Compose as required, but this _only_ works in Compose. Any changes you make will not be reflected in the `Activity` theme. 116 | 117 | ## Compose Material 3 118 | 119 | ![MDC-Android Compose Theme Adapter header](docs/m3header.png) 120 | 121 | The basis of Material Design 3 theming in [Jetpack Compose][compose] is the [`MaterialTheme`][m3materialtheme] composable, where you provide [`ColorScheme`][m3colorscheme], [`Typography`][m3typography] and [`Shapes`][m3shapes] instances containing your styling parameters: 122 | 123 | ``` kotlin 124 | MaterialTheme( 125 | colorScheme = colorScheme, 126 | typography = typography, 127 | shapes = shapes 128 | ) { 129 | // M3 Surface, Scaffold, etc. 130 | } 131 | ``` 132 | 133 | [Material Components for Android][mdc] themes allow for similar theming for views via XML theme attributes, like so: 134 | 135 | ``` xml 136 | 149 | ``` 150 | 151 | This library attempts to bridge the gap between [Material Components for Android][mdc] M3 XML themes, and themes in [Jetpack Compose][compose], allowing your composable [`MaterialTheme`][m3materialtheme] to be based on the `Activity`'s XML theme: 152 | 153 | 154 | ``` kotlin 155 | Mdc3Theme { 156 | // MaterialTheme.colorScheme, MaterialTheme.typography, MaterialTheme.shapes 157 | // will now contain copies of the Context's theme 158 | } 159 | ``` 160 | 161 | This is especially handy when you're migrating an existing app, a `Fragment` (or other UI container) at a time. 162 | 163 | ### Customizing the M3 theme 164 | 165 | The `Mdc3Theme()` function will automatically read the host `Context`'s MDC theme and pass them to [`MaterialTheme`][m3materialtheme] on your behalf, but if you want to customize the generated values, you can do so via the `createMdc3Theme()` function: 166 | 167 | ``` kotlin 168 | val context = LocalContext.current 169 | var (colorScheme, typography, shapes) = createMdc3Theme( 170 | context = context 171 | ) 172 | 173 | // Modify colorScheme, typography or shapes as required. 174 | // Then pass them through to MaterialTheme... 175 | 176 | MaterialTheme( 177 | colorScheme = colorScheme, 178 | typography = typography, 179 | shapes = shapes 180 | ) { 181 | // Rest of M3 layout 182 | } 183 | ``` 184 | 185 | ### Limitations 186 | 187 | There are some known limitations with the implementation at the moment: 188 | 189 | * This relies on your `Activity`/`Context` theme extending one of the `Theme.Material3` themes. 190 | * Text colors are not read from the text appearances by default. You can enable it via the `setTextColors` function parameter. 191 | * Variable fonts are not supported in Compose yet, meaning that the value of `android:fontVariationSettings` are currently ignored. 192 | * MDC `ShapeAppearances` allow setting of different corner families (cut, rounded) on each corner, whereas Compose's [Shapes][m3shapes] allows only a single corner family for the entire shape. Therefore only the `app:cornerFamily` attribute is read, others (`app:cornerFamilyTopLeft`, etc) are ignored. 193 | * You can modify the resulting `MaterialTheme` in Compose as required, but this _only_ works in Compose. Any changes you make will not be reflected in the `Activity` theme. 194 | 195 | --- 196 | 197 | ### Library Snapshots 198 | 199 | Snapshots of the current development version of this library are available, which track the latest commit. See [here](./docs/using-snapshot-version.md) for more information on how to use them. 200 | 201 | --- 202 | 203 | ## Contributions 204 | 205 | Please contribute! We will gladly review any pull requests. 206 | Make sure to read the [Contributing](CONTRIBUTING.md) page first though. 207 | 208 | ## License 209 | 210 | ``` 211 | Copyright 2020 The Android Open Source Project 212 | 213 | Licensed under the Apache License, Version 2.0 (the "License"); 214 | you may not use this file except in compliance with the License. 215 | You may obtain a copy of the License at 216 | 217 | https://www.apache.org/licenses/LICENSE-2.0 218 | 219 | Unless required by applicable law or agreed to in writing, software 220 | distributed under the License is distributed on an "AS IS" BASIS, 221 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 222 | See the License for the specific language governing permissions and 223 | limit 224 | 225 | [migratexmltocompose]: https://developer.android.com/jetpack/compose/designsystems/views-to-compose 226 | [compose]: https://developer.android.com/jetpack/compose 227 | [mdc]: https://github.com/material-components/material-components-android 228 | [appcompat]: https://developer.android.com/jetpack/androidx/releases/appcompat 229 | [materialtheme]: https://developer.android.com/reference/kotlin/androidx/compose/material/MaterialTheme 230 | [colors]: https://developer.android.com/reference/kotlin/androidx/compose/material/Colors 231 | [typography]: https://developer.android.com/reference/kotlin/androidx/compose/material/Typography 232 | [shapes]: https://developer.android.com/reference/kotlin/androidx/compose/material/Shapes 233 | [m3materialtheme]: https://developer.android.com/reference/kotlin/androidx/compose/material3/MaterialTheme 234 | [m3colorscheme]: https://developer.android.com/reference/kotlin/androidx/compose/material3/ColorScheme 235 | [m3shapes]: https://developer.android.com/reference/kotlin/androidx/compose/material3/Shapes 236 | [m3typography]: https://developer.android.com/reference/kotlin/androidx/compose/material3/Typography 237 | [accompanist]: https://github.com/google/accompanist 238 | [themeadaptermateriallib]: https://google.github.io/accompanist/themeadapter-material 239 | [themeadaptermaterial3lib]: https://google.github.io/accompanist/themeadapter-material3 240 | [themeadaptercorelib]: https://google.github.io/accompanist/themeadapter-core -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | import com.google.android.material.composethemeadapter.Libs 18 | import com.google.android.material.composethemeadapter.Versions 19 | 20 | buildscript { 21 | repositories { 22 | google() 23 | mavenCentral() 24 | jcenter() 25 | } 26 | 27 | dependencies { 28 | classpath Libs.androidGradlePlugin 29 | classpath Libs.Kotlin.gradlePlugin 30 | 31 | classpath Libs.gradleMavenPublishPlugin 32 | 33 | classpath Libs.Dokka.gradlePlugin 34 | classpath Libs.Kotlin.binaryCompatibility 35 | } 36 | } 37 | 38 | plugins { 39 | id "com.diffplug.spotless" version "5.9.0" 40 | } 41 | 42 | apply plugin: 'org.jetbrains.dokka' 43 | 44 | apply plugin: 'binary-compatibility-validator' 45 | apiValidation { 46 | // Ignore the sample from API tracking/checking 47 | ignoredProjects += ["sample"] 48 | } 49 | 50 | tasks.withType(org.jetbrains.dokka.gradle.DokkaTask).configureEach { 51 | outputDirectory = rootProject.file('docs/api') 52 | failOnWarning = true 53 | } 54 | 55 | allprojects { 56 | repositories { 57 | google() 58 | mavenCentral() 59 | jcenter() 60 | 61 | if (!Libs.AndroidX.Compose.snapshot.isEmpty()) { 62 | maven { url Libs.AndroidX.Compose.snapshotUrl } 63 | } 64 | } 65 | // BUG: https://issuetracker.google.com/issues/240473335 66 | configurations.all { 67 | exclude group: 'androidx.lifecycle', module: 'lifecycle-viewmodel-ktx' 68 | } 69 | } 70 | 71 | subprojects { 72 | apply plugin: 'com.diffplug.spotless' 73 | spotless { 74 | kotlin { 75 | target "**/*.kt" 76 | ktlint(Versions.ktlint) 77 | licenseHeaderFile rootProject.file('spotless/copyright.txt') 78 | } 79 | } 80 | 81 | tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { 82 | kotlinOptions { 83 | // Treat all Kotlin warnings as errors 84 | allWarningsAsErrors = true 85 | 86 | // Set JVM target to 1.8 87 | jvmTarget = "1.8" 88 | 89 | // Allow use of @OptIn 90 | freeCompilerArgs += '-opt-in=kotlin.RequiresOptIn' 91 | } 92 | } 93 | 94 | // Must be afterEvaluate or else com.vanniktech.maven.publish will overwrite our 95 | // dokka configuration. 96 | afterEvaluate { 97 | if (tasks.findByName('dokkaGfm') == null) { 98 | // If dokka isn't enabled on this module, skip 99 | return 100 | } 101 | tasks.withType(org.jetbrains.dokka.gradle.DokkaTask) { 102 | dokkaSourceSets.named("main") { 103 | configuration { 104 | jdkVersion.set(8) 105 | reportUndocumented.set(true) 106 | skipEmptyPackages.set(true) 107 | skipDeprecated.set(true) 108 | 109 | // Add Android SDK packages 110 | noAndroidSdkLink.set(false) 111 | 112 | // Add samples from :sample module 113 | samples.from(rootProject.file("sample/src/main/java/")) 114 | 115 | // AndroidX + Compose docs 116 | externalDocumentationLink { 117 | url.set(new URL("https://developer.android.com/reference/")) 118 | packageListUrl.set(new URL("https://developer.android.com/reference/androidx/package-list")) 119 | } 120 | externalDocumentationLink { 121 | url.set(new URL("https://developer.android.com/reference/kotlin/")) 122 | packageListUrl.set(new URL("https://developer.android.com/reference/kotlin/androidx/package-list")) 123 | } 124 | 125 | sourceLink { 126 | localDirectory.set(project.file("src/main/java")) 127 | // URL showing where the source code can be accessed through the web browser 128 | remoteUrl.set(new URL("https://github.com/material-components/material-components-android-compose-theme-adapter/blob/develop/${project.name}/src/main/java")) 129 | // Suffix which is used to append the line number to the URL. Use #L for GitHub 130 | remoteLineSuffix.set("#L") 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | repositories { 18 | jcenter() 19 | } 20 | 21 | plugins { 22 | `kotlin-dsl` 23 | } 24 | -------------------------------------------------------------------------------- /buildSrc/src/main/java/com/google/android/material/composethemeadapter/dependencies.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter 18 | 19 | object Versions { 20 | const val ktlint = "0.40.0" 21 | } 22 | 23 | object Libs { 24 | const val androidGradlePlugin = "com.android.tools.build:gradle:7.3.1" 25 | 26 | const val gradleMavenPublishPlugin = "com.vanniktech:gradle-maven-publish-plugin:0.13.0" 27 | 28 | object Kotlin { 29 | const val version = "1.7.20" 30 | const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib:$version" 31 | const val gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$version" 32 | 33 | const val binaryCompatibility = "org.jetbrains.kotlinx:binary-compatibility-validator:0.3.0" 34 | } 35 | 36 | object Dokka { 37 | const val gradlePlugin = "org.jetbrains.dokka:dokka-gradle-plugin:1.5.0" 38 | } 39 | 40 | object AndroidX { 41 | object Compose { 42 | const val snapshot = "" 43 | 44 | @JvmStatic 45 | val snapshotUrl: String 46 | get() = when { 47 | snapshot.isNotEmpty() -> { 48 | "https://androidx.dev/snapshots/builds/$snapshot/artifacts/repository/" 49 | } 50 | else -> throw IllegalArgumentException("Snapshot version not set") 51 | } 52 | 53 | const val version = "1.3.1" 54 | const val compilerVersion = "1.3.2" 55 | 56 | const val runtime = "androidx.compose.runtime:runtime:$version" 57 | const val foundation = "androidx.compose.foundation:foundation:${version}" 58 | const val layout = "androidx.compose.foundation:foundation-layout:${version}" 59 | 60 | const val ui = "androidx.compose.ui:ui:${version}" 61 | const val material = "androidx.compose.material:material:${version}" 62 | const val material3 = "androidx.compose.material3:material3:1.0.1" 63 | 64 | const val tooling = "androidx.compose.ui:ui-tooling:${version}" 65 | const val test = "androidx.compose.ui:ui-test-junit4:${version}" 66 | } 67 | 68 | const val appcompat = "androidx.appcompat:appcompat:1.5.1" 69 | 70 | const val coreKtx = "androidx.core:core-ktx:1.9.0" 71 | 72 | object Activity { 73 | const val activityCompose = "androidx.activity:activity-compose:1.6.0" 74 | } 75 | 76 | object Test { 77 | private const val version = "1.4.0" 78 | const val runner = "androidx.test:runner:$version" 79 | const val rules = "androidx.test:rules:$version" 80 | 81 | const val ext = "androidx.test.ext:junit:1.1.3" 82 | 83 | const val espressoCore = "androidx.test.espresso:espresso-core:3.4.0" 84 | } 85 | } 86 | 87 | const val mdc = "com.google.android.material:material:1.7.0" 88 | 89 | const val junit = "junit:junit:4.13" 90 | 91 | const val truth = "com.google.truth:truth:1.0.1" 92 | } 93 | -------------------------------------------------------------------------------- /checksum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | RESULT_FILE=$1 3 | 4 | if [ -f $RESULT_FILE ]; then 5 | rm $RESULT_FILE 6 | fi 7 | touch $RESULT_FILE 8 | 9 | checksum_file() { 10 | echo $(openssl md5 $1 | awk '{print $2}') 11 | } 12 | 13 | FILES=() 14 | while read -r -d ''; do 15 | FILES+=("$REPLY") 16 | done < <(find . -type f \( -name "build.gradle*" -o -name "dependencies.kt" -o -name "gradle-wrapper.properties" \) -print0) 17 | 18 | # Loop through files and append MD5 to result file 19 | for FILE in ${FILES[@]}; do 20 | echo $(checksum_file $FILE) >> $RESULT_FILE 21 | done 22 | # Now sort the file so that it is 23 | sort $RESULT_FILE -o $RESULT_FILE -------------------------------------------------------------------------------- /core/api/core.api: -------------------------------------------------------------------------------- 1 | public final class com/google/android/material/composethemeadapter/core/FontFamilyWithWeight { 2 | public static final field $stable I 3 | public fun (Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;)V 4 | public synthetic fun (Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;ILkotlin/jvm/internal/DefaultConstructorMarker;)V 5 | public final fun component1 ()Landroidx/compose/ui/text/font/FontFamily; 6 | public final fun component2 ()Landroidx/compose/ui/text/font/FontWeight; 7 | public final fun copy (Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;)Lcom/google/android/material/composethemeadapter/core/FontFamilyWithWeight; 8 | public static synthetic fun copy$default (Lcom/google/android/material/composethemeadapter/core/FontFamilyWithWeight;Landroidx/compose/ui/text/font/FontFamily;Landroidx/compose/ui/text/font/FontWeight;ILjava/lang/Object;)Lcom/google/android/material/composethemeadapter/core/FontFamilyWithWeight; 9 | public fun equals (Ljava/lang/Object;)Z 10 | public final fun getFontFamily ()Landroidx/compose/ui/text/font/FontFamily; 11 | public final fun getWeight ()Landroidx/compose/ui/text/font/FontWeight; 12 | public fun hashCode ()I 13 | public fun toString ()Ljava/lang/String; 14 | } 15 | 16 | public final class com/google/android/material/composethemeadapter/core/ResourceUtilsKt { 17 | public static final fun parseColor-mxwnekA (Landroid/content/res/TypedArray;IJ)J 18 | public static synthetic fun parseColor-mxwnekA$default (Landroid/content/res/TypedArray;IJILjava/lang/Object;)J 19 | public static final fun parseCornerSize (Landroid/content/res/TypedArray;I)Landroidx/compose/foundation/shape/CornerSize; 20 | public static final fun parseFontFamily (Landroid/content/res/TypedArray;I)Lcom/google/android/material/composethemeadapter/core/FontFamilyWithWeight; 21 | public static final fun parseShapeAppearance (Landroid/content/Context;ILandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/foundation/shape/CornerBasedShape;)Landroidx/compose/foundation/shape/CornerBasedShape; 22 | public static final fun parseTextAppearance (Landroid/content/Context;ILandroidx/compose/ui/unit/Density;ZLandroidx/compose/ui/text/font/FontFamily;)Landroidx/compose/ui/text/TextStyle; 23 | public static final fun parseTextUnit-lGoEivg (Landroid/content/res/TypedArray;ILandroidx/compose/ui/unit/Density;J)J 24 | public static synthetic fun parseTextUnit-lGoEivg$default (Landroid/content/res/TypedArray;ILandroidx/compose/ui/unit/Density;JILjava/lang/Object;)J 25 | public static final fun parseXmlFontFamily (Landroid/content/res/Resources;I)Landroidx/compose/ui/text/font/FontFamily; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | import com.google.android.material.composethemeadapter.Libs 18 | 19 | plugins { 20 | id 'com.android.library' 21 | id 'kotlin-android' 22 | id 'org.jetbrains.dokka' 23 | } 24 | 25 | android { 26 | compileSdkVersion 33 27 | 28 | defaultConfig { 29 | minSdkVersion 21 30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 31 | } 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | buildFeatures { 39 | compose true 40 | buildConfig false 41 | } 42 | 43 | composeOptions { 44 | kotlinCompilerExtensionVersion Libs.AndroidX.Compose.compilerVersion 45 | } 46 | 47 | lintOptions { 48 | textReport true 49 | textOutput 'stdout' 50 | // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks 51 | checkReleaseBuilds false 52 | } 53 | 54 | packagingOptions { 55 | // Multiple dependencies bring these files in. Exclude them to enable 56 | // our test APK to build (has no effect on our AARs) 57 | excludes += "/META-INF/AL2.0" 58 | excludes += "/META-INF/LGPL2.1" 59 | } 60 | } 61 | 62 | dependencies { 63 | api Libs.Kotlin.stdlib 64 | api Libs.AndroidX.coreKtx 65 | api Libs.AndroidX.appcompat 66 | api Libs.mdc 67 | api Libs.AndroidX.Compose.runtime 68 | api Libs.AndroidX.Compose.foundation 69 | 70 | androidTestImplementation Libs.junit 71 | androidTestImplementation Libs.AndroidX.Compose.test 72 | androidTestImplementation Libs.AndroidX.Test.rules 73 | androidTestImplementation Libs.AndroidX.Test.runner 74 | } 75 | 76 | apply plugin: 'com.vanniktech.maven.publish' 77 | 78 | mavenPublish { 79 | targets { 80 | uploadArchives { 81 | snapshotRepositoryUrl = "https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter-core" 82 | releaseRepositoryUrl = "https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter-core" 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /core/gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 The Android Open Source Project 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 | # https://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 | 17 | POM_ARTIFACT_ID=compose-theme-adapter-core 18 | POM_NAME=MDC-Android Theme Adapter for Compose 19 | POM_PACKAGING=aar 20 | VERSION_NAME=1.0.1-SNAPHOT -------------------------------------------------------------------------------- /core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /core/src/main/res/values/theme_attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/docs/favicon.ico -------------------------------------------------------------------------------- /docs/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/docs/header.png -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/m3header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/docs/m3header.png -------------------------------------------------------------------------------- /docs/using-snapshot-version.md: -------------------------------------------------------------------------------- 1 | # Using a Snapshot Version of the Library 2 | 3 | If you would like to depend on the cutting edge version of the MDC-Android Compose Theme Adapter 4 | library, you can use the [snapshot versions][packages] that are published to 5 | [GitHub Packages](https://help.github.com/en/packages/publishing-and-managing-packages/about-github-packages). These are updated on every commit to `develop`. 6 | 7 | To do so, you need to 8 | [create a GitHub access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line#creating-a-token), 9 | and add the following to your `build.gradle` Maven repositories: 10 | 11 | ```groovy 12 | maven { 13 | url = uri("https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter") 14 | credentials { 15 | username = 16 | password = 17 | } 18 | } 19 | ``` 20 | 21 | Then you can use a snapshot version by adding a 22 | `com.google.android.material:compose-theme-adapter:-SNAPSHOT` dependency as per 23 | usual (see latest release [here][versions]). 24 | This will fetch the latest snapshot version, which your Gradle build won't 25 | cache. If you build after a new version has been published, that version will be 26 | used. 27 | 28 | See the official doc on 29 | [Configuring Gradle for use with GitHub Packages](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-gradle-for-use-with-github-packages) 30 | for additional information. 31 | 32 | If you prefer to depend on a specific snapshot version, you can add 33 | `com.google.android.material:compose-theme-adapter:-`, where 34 | `` is a combination of the date, a timestamp, and a counter (see 35 | all versions [here][versions]). 36 | 37 | [packages]: https://github.com/material-components/material-components-android-compose-theme-adapter/packages/333328 38 | [versions]: https://github.com/material-components/material-components-android-compose-theme-adapter/packages/333328/versions 39 | -------------------------------------------------------------------------------- /generate_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cp README.md docs/index.md 4 | cp CONTRIBUTING.md docs/contributing.md 5 | 6 | sed -i 's/CONTRIBUTING.md/\/contributing/' docs/index.md 7 | sed -i 's/docs\/using-snapshot-version.md/using-snapshot-version/' docs/index.md 8 | 9 | # Build the docs 10 | ./gradlew clean dokkaGfm 11 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 The Android Open Source Project 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 | # https://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 | 17 | # We use AndroidX 18 | android.useAndroidX=true 19 | 20 | org.gradle.configureondemand=true 21 | org.gradle.caching=true 22 | org.gradle.parallel=true 23 | 24 | # Increase timeout when uploading archives (otherwise we get timeouts)s 25 | systemProp.org.gradle.internal.http.socketTimeout=120000 26 | 27 | # Metaspace size limit 28 | org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m 29 | 30 | ########################## 31 | # POM/Maven information 32 | ########################## 33 | 34 | GROUP=com.google.android.material 35 | 36 | POM_DESCRIPTION=A library that enables reuse of Material Components for Android themes for theming in Jetpack Compose 37 | 38 | POM_URL=https://github.com/material-components/material-components-android-compose-theme-adapter/ 39 | POM_SCM_URL=https://github.com/material-components/material-components-android-compose-theme-adapter/ 40 | POM_SCM_CONNECTION=scm:git:git://github.com/material-components/material-components-android-compose-theme-adapter.git 41 | POM_SCM_DEV_CONNECTION=scm:git:git://github.com/material-components/material-components-android-compose-theme-adapter.git 42 | 43 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 44 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 45 | POM_LICENCE_DIST=repo 46 | 47 | POM_DEVELOPER_ID=material-components 48 | POM_DEVELOPER_NAME=Material Design Components 49 | 50 | # Turn off release signing 51 | RELEASE_SIGNING_ENABLED=false 52 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Sep 22 10:12:26 BST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: openjdk11 2 | -------------------------------------------------------------------------------- /material3Lib/api/material3Lib.api: -------------------------------------------------------------------------------- 1 | public final class com/google/android/material/composethemeadapter3/Mdc3Theme { 2 | public static final fun Mdc3Theme (Landroid/content/Context;ZZZZZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V 3 | public static final fun createMdc3Theme (Landroid/content/Context;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;ZZZZZ)Lcom/google/android/material/composethemeadapter3/Theme3Parameters; 4 | public static synthetic fun createMdc3Theme$default (Landroid/content/Context;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;ZZZZZILjava/lang/Object;)Lcom/google/android/material/composethemeadapter3/Theme3Parameters; 5 | } 6 | 7 | public final class com/google/android/material/composethemeadapter3/Theme3Parameters { 8 | public static final field $stable I 9 | public fun (Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/Typography;Landroidx/compose/material3/Shapes;)V 10 | public final fun component1 ()Landroidx/compose/material3/ColorScheme; 11 | public final fun component2 ()Landroidx/compose/material3/Typography; 12 | public final fun component3 ()Landroidx/compose/material3/Shapes; 13 | public final fun copy (Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/Typography;Landroidx/compose/material3/Shapes;)Lcom/google/android/material/composethemeadapter3/Theme3Parameters; 14 | public static synthetic fun copy$default (Lcom/google/android/material/composethemeadapter3/Theme3Parameters;Landroidx/compose/material3/ColorScheme;Landroidx/compose/material3/Typography;Landroidx/compose/material3/Shapes;ILjava/lang/Object;)Lcom/google/android/material/composethemeadapter3/Theme3Parameters; 15 | public fun equals (Ljava/lang/Object;)Z 16 | public final fun getColorScheme ()Landroidx/compose/material3/ColorScheme; 17 | public final fun getShapes ()Landroidx/compose/material3/Shapes; 18 | public final fun getTypography ()Landroidx/compose/material3/Typography; 19 | public fun hashCode ()I 20 | public fun toString ()Ljava/lang/String; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /material3Lib/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | import com.google.android.material.composethemeadapter.Libs 18 | 19 | plugins { 20 | id 'com.android.library' 21 | id 'kotlin-android' 22 | id 'org.jetbrains.dokka' 23 | } 24 | 25 | android { 26 | compileSdkVersion 33 27 | 28 | defaultConfig { 29 | minSdkVersion 21 30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 31 | } 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | buildFeatures { 39 | compose true 40 | buildConfig false 41 | } 42 | 43 | composeOptions { 44 | kotlinCompilerExtensionVersion Libs.AndroidX.Compose.compilerVersion 45 | } 46 | 47 | lintOptions { 48 | textReport true 49 | textOutput 'stdout' 50 | // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks 51 | checkReleaseBuilds false 52 | } 53 | 54 | packagingOptions { 55 | // Multiple dependencies bring these files in. Exclude them to enable 56 | // our test APK to build (has no effect on our AARs) 57 | excludes += "/META-INF/AL2.0" 58 | excludes += "/META-INF/LGPL2.1" 59 | } 60 | } 61 | 62 | dependencies { 63 | implementation(project(':core')) 64 | 65 | implementation Libs.AndroidX.Compose.material3 66 | 67 | androidTestImplementation Libs.junit 68 | androidTestImplementation Libs.AndroidX.Compose.test 69 | androidTestImplementation Libs.AndroidX.Test.rules 70 | androidTestImplementation Libs.AndroidX.Test.runner 71 | } 72 | 73 | apply plugin: 'com.vanniktech.maven.publish' 74 | 75 | mavenPublish { 76 | targets { 77 | uploadArchives { 78 | snapshotRepositoryUrl = "https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter-3" 79 | releaseRepositoryUrl = "https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter-3" 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /material3Lib/gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 The Android Open Source Project 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 | # https://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 | 17 | POM_ARTIFACT_ID=compose-theme-adapter-3 18 | POM_NAME=MDC-Android Theme Adapter for Compose Material 3 19 | POM_PACKAGING=aar 20 | VERSION_NAME=1.1.1-SNAPHOT -------------------------------------------------------------------------------- /material3Lib/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/java/com/google/android/material/composethemeadapter3/test/Mdc3Activity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter3.test 18 | 19 | import androidx.appcompat.app.AppCompatActivity 20 | 21 | class Mdc3Activity : AppCompatActivity() 22 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/java/com/google/android/material/composethemeadapter3/test/Mdc3ThemeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") 18 | 19 | package com.google.android.material.composethemeadapter3.test 20 | 21 | import androidx.compose.foundation.shape.CornerSize 22 | import androidx.compose.foundation.shape.CutCornerShape 23 | import androidx.compose.foundation.shape.RoundedCornerShape 24 | import androidx.compose.material3.LocalContentColor 25 | import androidx.compose.material3.MaterialTheme 26 | import androidx.compose.ui.geometry.Size 27 | import androidx.compose.ui.platform.LocalDensity 28 | import androidx.compose.ui.res.colorResource 29 | import androidx.compose.ui.test.junit4.createAndroidComposeRule 30 | import androidx.compose.ui.text.font.Font 31 | import androidx.compose.ui.text.font.FontFamily 32 | import androidx.compose.ui.text.font.FontWeight 33 | import androidx.compose.ui.text.font.toFontFamily 34 | import androidx.compose.ui.unit.Density 35 | import androidx.compose.ui.unit.Dp 36 | import androidx.compose.ui.unit.TextUnit 37 | import androidx.compose.ui.unit.dp 38 | import androidx.compose.ui.unit.em 39 | import androidx.compose.ui.unit.sp 40 | import androidx.test.filters.MediumTest 41 | import com.google.android.material.composethemeadapter.core.FontFamilyWithWeight 42 | import com.google.android.material.composethemeadapter3.Mdc3Theme 43 | import org.junit.Assert 44 | import org.junit.Rule 45 | import org.junit.Test 46 | import org.junit.runner.RunWith 47 | import org.junit.runners.JUnit4 48 | 49 | @MediumTest 50 | @RunWith(JUnit4::class) 51 | class Mdc3ThemeTest { 52 | @get:Rule 53 | val composeTestRule = createAndroidComposeRule() 54 | 55 | @Test 56 | fun colors() = composeTestRule.setContent { 57 | Mdc3Theme { 58 | val colorScheme = MaterialTheme.colorScheme 59 | 60 | Assert.assertEquals(colorResource(R.color.aquamarine), colorScheme.primary) 61 | Assert.assertEquals(colorResource(R.color.pale_turquoise), colorScheme.onPrimary) 62 | Assert.assertEquals(colorResource(R.color.midnight_blue), colorScheme.inversePrimary) 63 | Assert.assertEquals(colorResource(R.color.royal_blue), colorScheme.primaryContainer) 64 | Assert.assertEquals(colorResource(R.color.steel_blue), colorScheme.onPrimaryContainer) 65 | 66 | Assert.assertEquals(colorResource(R.color.dodger_blue), colorScheme.secondary) 67 | Assert.assertEquals(colorResource(R.color.dark_golden_rod), colorScheme.onSecondary) 68 | Assert.assertEquals(colorResource(R.color.peru), colorScheme.secondaryContainer) 69 | Assert.assertEquals(colorResource(R.color.blue_violet), colorScheme.onSecondaryContainer) 70 | 71 | Assert.assertEquals(colorResource(R.color.dark_orchid), colorScheme.tertiary) 72 | Assert.assertEquals(colorResource(R.color.slate_gray), colorScheme.onTertiary) 73 | Assert.assertEquals(colorResource(R.color.gray), colorScheme.tertiaryContainer) 74 | Assert.assertEquals(colorResource(R.color.spring_green), colorScheme.onTertiaryContainer) 75 | 76 | Assert.assertEquals(colorResource(R.color.medium_spring_green), colorScheme.background) 77 | Assert.assertEquals(colorResource(R.color.navy), colorScheme.onBackground) 78 | 79 | Assert.assertEquals(colorResource(R.color.dark_blue), colorScheme.surface) 80 | Assert.assertEquals(colorResource(R.color.light_coral), colorScheme.onSurface) 81 | Assert.assertEquals(colorResource(R.color.salmon), colorScheme.surfaceVariant) 82 | Assert.assertEquals(colorResource(R.color.dark_salmon), colorScheme.onSurfaceVariant) 83 | Assert.assertEquals(colorResource(R.color.indian_red), colorScheme.surfaceTint) 84 | Assert.assertEquals(colorResource(R.color.light_salmon), colorScheme.inverseSurface) 85 | Assert.assertEquals(colorResource(R.color.orchid), colorScheme.inverseOnSurface) 86 | 87 | Assert.assertEquals(colorResource(R.color.violet), colorScheme.outline) 88 | // TODO: MDC-Android doesn't include outlineVariant yet, add when available 89 | 90 | Assert.assertEquals(colorResource(R.color.beige), colorScheme.error) 91 | Assert.assertEquals(colorResource(R.color.white_smoke), colorScheme.onError) 92 | Assert.assertEquals(colorResource(R.color.olive), colorScheme.errorContainer) 93 | Assert.assertEquals(colorResource(R.color.olive_drab), colorScheme.onErrorContainer) 94 | 95 | Assert.assertEquals(colorResource(R.color.crimson), colorScheme.scrim) 96 | 97 | // Mdc3Theme updates the LocalContentColor to match the calculated onBackground 98 | Assert.assertEquals(colorResource(R.color.navy), LocalContentColor.current) 99 | } 100 | } 101 | 102 | @Test 103 | fun shapes() = composeTestRule.setContent { 104 | Mdc3Theme { 105 | val shapes = MaterialTheme.shapes 106 | val density = LocalDensity.current 107 | 108 | shapes.extraSmall.run { 109 | Assert.assertTrue(this is RoundedCornerShape) 110 | Assert.assertEquals(4f, topStart.toPx(density)) 111 | Assert.assertEquals(9.dp.scaleToPx(density), topEnd.toPx(density)) 112 | Assert.assertEquals(5f, bottomEnd.toPx(density)) 113 | Assert.assertEquals(3.dp.scaleToPx(density), bottomStart.toPx(density)) 114 | } 115 | shapes.small.run { 116 | Assert.assertTrue(this is CutCornerShape) 117 | Assert.assertEquals(4f, topStart.toPx(density)) 118 | Assert.assertEquals(9.dp.scaleToPx(density), topEnd.toPx(density)) 119 | Assert.assertEquals(5f, bottomEnd.toPx(density)) 120 | Assert.assertEquals(3.dp.scaleToPx(density), bottomStart.toPx(density)) 121 | } 122 | shapes.medium.run { 123 | Assert.assertTrue(this is RoundedCornerShape) 124 | Assert.assertEquals(12.dp.scaleToPx(density), topStart.toPx(density)) 125 | Assert.assertEquals(12.dp.scaleToPx(density), topEnd.toPx(density)) 126 | Assert.assertEquals(12.dp.scaleToPx(density), bottomEnd.toPx(density)) 127 | Assert.assertEquals(12.dp.scaleToPx(density), bottomStart.toPx(density)) 128 | } 129 | shapes.large.run { 130 | Assert.assertTrue(this is CutCornerShape) 131 | Assert.assertEquals(16.dp.scaleToPx(density), topStart.toPx(density)) 132 | Assert.assertEquals(16.dp.scaleToPx(density), topEnd.toPx(density)) 133 | Assert.assertEquals(16.dp.scaleToPx(density), bottomEnd.toPx(density)) 134 | Assert.assertEquals(16.dp.scaleToPx(density), bottomStart.toPx(density)) 135 | } 136 | shapes.extraLarge.run { 137 | Assert.assertTrue(this is RoundedCornerShape) 138 | Assert.assertEquals(28.dp.scaleToPx(density), topStart.toPx(density)) 139 | Assert.assertEquals(28.dp.scaleToPx(density), topEnd.toPx(density)) 140 | Assert.assertEquals(28.dp.scaleToPx(density), bottomEnd.toPx(density)) 141 | Assert.assertEquals(28.dp.scaleToPx(density), bottomStart.toPx(density)) 142 | } 143 | } 144 | } 145 | 146 | @Test 147 | fun type() = composeTestRule.setContent { 148 | Mdc3Theme { 149 | val typography = MaterialTheme.typography 150 | val density = LocalDensity.current 151 | 152 | val rubik = FontFamily( 153 | Font(resId = R.font.rubik_300, weight = FontWeight.W300), 154 | Font(resId = R.font.rubik_400, weight = FontWeight.W400), 155 | Font(resId = R.font.rubik_500, weight = FontWeight.W500), 156 | Font(resId = R.font.rubik_700, weight = FontWeight.W700) 157 | ) 158 | val rubik300 = Font(R.font.rubik_300).toFontFamily() 159 | val rubik400 = Font(R.font.rubik_400).toFontFamily() 160 | val sansSerif = FontFamilyWithWeight(FontFamily.SansSerif) 161 | val sansSerifLight = FontFamilyWithWeight(FontFamily.SansSerif, FontWeight.Light) 162 | val sansSerifBlack = FontFamilyWithWeight(FontFamily.SansSerif, FontWeight.Black) 163 | val serif = FontFamilyWithWeight(FontFamily.Serif) 164 | val cursive = FontFamilyWithWeight(FontFamily.Cursive) 165 | val monospace = FontFamilyWithWeight(FontFamily.Monospace) 166 | 167 | typography.displayLarge.run { 168 | assertTextUnitEquals(97.54.sp, fontSize, density) 169 | assertTextUnitEquals((-0.0015).em, letterSpacing, density) 170 | Assert.assertEquals(rubik300, fontFamily) 171 | } 172 | 173 | Assert.assertNotNull(typography.displayMedium.shadow) 174 | typography.displayMedium.shadow!!.run { 175 | Assert.assertEquals(colorResource(R.color.olive_drab), color) 176 | Assert.assertEquals(4.43f, offset.x) 177 | Assert.assertEquals(8.19f, offset.y) 178 | Assert.assertEquals(2.13f, blurRadius) 179 | } 180 | 181 | typography.displaySmall.run { 182 | Assert.assertEquals(sansSerif.fontFamily, fontFamily) 183 | Assert.assertEquals(sansSerif.weight, fontWeight) 184 | } 185 | 186 | typography.headlineLarge.run { 187 | Assert.assertEquals(sansSerifLight.fontFamily, fontFamily) 188 | Assert.assertEquals(sansSerifLight.weight, fontWeight) 189 | } 190 | 191 | typography.headlineMedium.run { 192 | Assert.assertEquals(sansSerifLight.fontFamily, fontFamily) 193 | Assert.assertEquals(sansSerifLight.weight, fontWeight) 194 | } 195 | 196 | typography.headlineSmall.run { 197 | Assert.assertEquals(sansSerifBlack.fontFamily, fontFamily) 198 | Assert.assertEquals(sansSerifBlack.weight, fontWeight) 199 | } 200 | 201 | typography.titleLarge.run { 202 | Assert.assertEquals(serif.fontFamily, fontFamily) 203 | Assert.assertEquals(serif.weight, fontWeight) 204 | } 205 | 206 | typography.titleMedium.run { 207 | Assert.assertEquals(monospace.fontFamily, fontFamily) 208 | Assert.assertEquals(monospace.weight, fontWeight) 209 | assertTextUnitEquals(0.em, letterSpacing, density) 210 | } 211 | 212 | typography.titleSmall.run { 213 | Assert.assertEquals(FontFamily.SansSerif, fontFamily) 214 | } 215 | 216 | typography.bodyLarge.run { 217 | assertTextUnitEquals(16.26.sp, fontSize, density) 218 | assertTextUnitEquals(0.005.em, letterSpacing, density) 219 | Assert.assertEquals(rubik400, fontFamily) 220 | Assert.assertNull(shadow) 221 | } 222 | 223 | typography.bodyMedium.run { 224 | Assert.assertEquals(cursive.fontFamily, fontFamily) 225 | Assert.assertEquals(cursive.weight, fontWeight) 226 | } 227 | 228 | typography.bodySmall.run { 229 | Assert.assertEquals(FontFamily.SansSerif, fontFamily) 230 | assertTextUnitEquals(0.04.em, letterSpacing, density) 231 | } 232 | 233 | typography.labelLarge.run { 234 | Assert.assertEquals(rubik, fontFamily) 235 | } 236 | 237 | typography.labelMedium.run { 238 | Assert.assertEquals(rubik, fontFamily) 239 | } 240 | 241 | typography.labelSmall.run { 242 | Assert.assertEquals(FontFamily.SansSerif, fontFamily) 243 | } 244 | } 245 | } 246 | } 247 | 248 | private fun Dp.scaleToPx(density: Density): Float { 249 | val dp = this 250 | return with(density) { dp.toPx() } 251 | } 252 | 253 | private fun assertTextUnitEquals(expected: TextUnit, actual: TextUnit, density: Density) { 254 | if (expected.javaClass == actual.javaClass) { 255 | // If the expected and actual are the same type, compare the raw values with a 256 | // delta to account for float inaccuracy 257 | Assert.assertEquals(expected.value, actual.value, 0.001f) 258 | } else { 259 | // Otherwise we need to flatten to a px to compare the values. Again using a 260 | // delta to account for float inaccuracy 261 | with(density) { Assert.assertEquals(expected.toPx(), actual.toPx(), 0.001f) } 262 | } 263 | } 264 | 265 | private fun CornerSize.toPx(density: Density) = toPx(Size.Unspecified, density) 266 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/java/com/google/android/material/composethemeadapter3/test/NotMdc3Activity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter3.test 18 | 19 | import androidx.appcompat.app.AppCompatActivity 20 | 21 | class NotMdc3Activity : AppCompatActivity() 22 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/java/com/google/android/material/composethemeadapter3/test/NotMdc3ThemeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") 18 | 19 | package com.google.android.material.composethemeadapter3.test 20 | 21 | import androidx.compose.ui.test.junit4.createAndroidComposeRule 22 | import androidx.test.filters.MediumTest 23 | import com.google.android.material.composethemeadapter3.Mdc3Theme 24 | import org.junit.Rule 25 | import org.junit.Test 26 | import org.junit.runner.RunWith 27 | import org.junit.runners.JUnit4 28 | 29 | @MediumTest 30 | @RunWith(JUnit4::class) 31 | class NotMdc3ThemeTest { 32 | @get:Rule 33 | val composeTestRule = createAndroidComposeRule() 34 | 35 | @Test(expected = IllegalArgumentException::class) 36 | fun throwForNonMdc3Theme() = composeTestRule.setContent { 37 | Mdc3Theme { 38 | // Nothing to do here, exception should be thrown 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/font/rubik.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 22 | 25 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/font/rubik_300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/material3Lib/src/androidTest/res/font/rubik_300.ttf -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/font/rubik_400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/material3Lib/src/androidTest/res/font/rubik_400.ttf -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/font/rubik_500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/material3Lib/src/androidTest/res/font/rubik_500.ttf -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/font/rubik_700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/material3Lib/src/androidTest/res/font/rubik_700.ttf -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 30 | 31 | 41 | 42 | 46 | 47 | 50 | 51 | 54 | 55 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/values/test_colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | #7FFFD4 21 | #AFEEEE 22 | #191970 23 | #4169E1 24 | #4682B4 25 | #1E90FF 26 | #B8860B 27 | #CD853F 28 | #8A2BE2 29 | #9932CC 30 | #708090 31 | #808080 32 | #00FF7F 33 | #00FA9A 34 | #000080 35 | #00008B 36 | #DC143C 37 | #CD5C5C 38 | #F08080 39 | #FA8072 40 | #E9967A 41 | #FFA07A 42 | #DA70D6 43 | #EE82EE 44 | #F5F5DC 45 | #F5F5F5 46 | #808000 47 | #6B8E23 48 | -------------------------------------------------------------------------------- /material3Lib/src/androidTest/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 76 | 77 | 25 | 26 | 32 | 33 | 36 | 37 | 40 | 41 | 44 | 45 | 48 | 49 | 52 | 53 | 57 | 58 | 61 | 62 | 67 | 68 | 71 | 72 | 76 | 77 | 78 | 79 | sans-serif-condensed-light 80 | 81 | 84 | 85 | 88 | 89 | 92 | 93 | -------------------------------------------------------------------------------- /material3Lib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /material3Lib/src/main/res/values/theme_attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /materialLib/api/materialLib.api: -------------------------------------------------------------------------------- 1 | public final class com/google/android/material/composethemeadapter/MdcTheme { 2 | public static final fun MdcTheme (Landroid/content/Context;ZZZZZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V 3 | public static final fun createMdcTheme (Landroid/content/Context;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;ZZZZZ)Lcom/google/android/material/composethemeadapter/ThemeParameters; 4 | public static synthetic fun createMdcTheme$default (Landroid/content/Context;Landroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/unit/Density;ZZZZZILjava/lang/Object;)Lcom/google/android/material/composethemeadapter/ThemeParameters; 5 | } 6 | 7 | public final class com/google/android/material/composethemeadapter/ThemeParameters { 8 | public static final field $stable I 9 | public fun (Landroidx/compose/material/Colors;Landroidx/compose/material/Typography;Landroidx/compose/material/Shapes;)V 10 | public final fun component1 ()Landroidx/compose/material/Colors; 11 | public final fun component2 ()Landroidx/compose/material/Typography; 12 | public final fun component3 ()Landroidx/compose/material/Shapes; 13 | public final fun copy (Landroidx/compose/material/Colors;Landroidx/compose/material/Typography;Landroidx/compose/material/Shapes;)Lcom/google/android/material/composethemeadapter/ThemeParameters; 14 | public static synthetic fun copy$default (Lcom/google/android/material/composethemeadapter/ThemeParameters;Landroidx/compose/material/Colors;Landroidx/compose/material/Typography;Landroidx/compose/material/Shapes;ILjava/lang/Object;)Lcom/google/android/material/composethemeadapter/ThemeParameters; 15 | public fun equals (Ljava/lang/Object;)Z 16 | public final fun getColors ()Landroidx/compose/material/Colors; 17 | public final fun getShapes ()Landroidx/compose/material/Shapes; 18 | public final fun getTypography ()Landroidx/compose/material/Typography; 19 | public fun hashCode ()I 20 | public fun toString ()Ljava/lang/String; 21 | } 22 | 23 | public final class com/google/android/material/composethemeadapter/TypographyKt { 24 | public static final fun merge (Landroidx/compose/material/Typography;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;)Landroidx/compose/material/Typography; 25 | public static synthetic fun merge$default (Landroidx/compose/material/Typography;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;Landroidx/compose/ui/text/TextStyle;ILjava/lang/Object;)Landroidx/compose/material/Typography; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /materialLib/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | import com.google.android.material.composethemeadapter.Libs 18 | 19 | plugins { 20 | id 'com.android.library' 21 | id 'kotlin-android' 22 | id 'org.jetbrains.dokka' 23 | } 24 | 25 | android { 26 | compileSdkVersion 33 27 | 28 | defaultConfig { 29 | minSdkVersion 21 30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 31 | } 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | buildFeatures { 39 | compose true 40 | buildConfig false 41 | } 42 | 43 | composeOptions { 44 | kotlinCompilerExtensionVersion Libs.AndroidX.Compose.compilerVersion 45 | } 46 | 47 | lintOptions { 48 | textReport true 49 | textOutput 'stdout' 50 | // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks 51 | checkReleaseBuilds false 52 | } 53 | 54 | packagingOptions { 55 | // Multiple dependencies bring these files in. Exclude them to enable 56 | // our test APK to build (has no effect on our AARs) 57 | excludes += "/META-INF/AL2.0" 58 | excludes += "/META-INF/LGPL2.1" 59 | } 60 | } 61 | 62 | dependencies { 63 | implementation(project(':core')) 64 | 65 | implementation Libs.AndroidX.Compose.material 66 | 67 | androidTestImplementation Libs.junit 68 | androidTestImplementation Libs.AndroidX.Compose.test 69 | androidTestImplementation Libs.AndroidX.Test.rules 70 | androidTestImplementation Libs.AndroidX.Test.runner 71 | } 72 | 73 | apply plugin: 'com.vanniktech.maven.publish' 74 | 75 | mavenPublish { 76 | targets { 77 | uploadArchives { 78 | snapshotRepositoryUrl = "https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter" 79 | releaseRepositoryUrl = "https://maven.pkg.github.com/material-components/material-components-android-compose-theme-adapter" 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /materialLib/gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 The Android Open Source Project 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 | # https://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 | 17 | POM_ARTIFACT_ID=compose-theme-adapter 18 | POM_NAME=MDC-Android Theme Adapter for Compose Material 19 | POM_PACKAGING=aar 20 | VERSION_NAME=1.2.1-SNAPHOT 21 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/DarkMdcActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter.test 18 | 19 | import android.content.Context 20 | import androidx.appcompat.app.AppCompatActivity 21 | import androidx.appcompat.app.AppCompatDelegate 22 | 23 | /** 24 | * An [AppCompatActivity] which forces the night mode to 'dark theme'. 25 | */ 26 | class DarkMdcActivity : AppCompatActivity() { 27 | override fun attachBaseContext(newBase: Context) { 28 | delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES 29 | super.attachBaseContext(newBase) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/DarkTheme.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter.test 18 | 19 | import android.content.Context 20 | import android.content.res.Configuration 21 | 22 | /** 23 | * This allows us to check whether this [Context]s resource configuration is in 'night mode', 24 | * which is also known as dark theme. 25 | */ 26 | fun Context.isInDarkTheme(): Boolean { 27 | return resources.configuration.uiMode and 28 | Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES 29 | } 30 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/DefaultFontFamilyMdcActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter.test 18 | 19 | import androidx.appcompat.app.AppCompatActivity 20 | 21 | class DefaultFontFamilyMdcActivity : AppCompatActivity() 22 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/DefaultFontFamilyMdcThemeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") 18 | 19 | package com.google.android.material.composethemeadapter.test 20 | 21 | import android.view.ContextThemeWrapper 22 | import androidx.annotation.StyleRes 23 | import androidx.compose.material.MaterialTheme 24 | import androidx.compose.material.Typography 25 | import androidx.compose.runtime.Composable 26 | import androidx.compose.runtime.CompositionLocalProvider 27 | import androidx.compose.ui.platform.LocalContext 28 | import androidx.compose.ui.test.junit4.createAndroidComposeRule 29 | import androidx.compose.ui.text.font.Font 30 | import androidx.compose.ui.text.font.FontFamily 31 | import androidx.compose.ui.text.font.FontWeight 32 | import androidx.compose.ui.text.font.toFontFamily 33 | import androidx.test.filters.MediumTest 34 | import androidx.test.filters.SdkSuppress 35 | import com.google.android.material.composethemeadapter.MdcTheme 36 | import org.junit.Assert.assertEquals 37 | import org.junit.Assert.assertNotEquals 38 | import org.junit.Rule 39 | import org.junit.Test 40 | import org.junit.runner.RunWith 41 | import org.junit.runners.JUnit4 42 | 43 | @MediumTest 44 | @RunWith(JUnit4::class) 45 | class DefaultFontFamilyMdcThemeTest { 46 | @get:Rule 47 | val composeTestRule = createAndroidComposeRule() 48 | 49 | @Test 50 | @SdkSuppress(maxSdkVersion = 22) // On API 21-22, the family is loaded with only the 400 font 51 | fun rubik_family_api21() = composeTestRule.setContent { 52 | val rubik = Font(R.font.rubik, FontWeight.W400).toFontFamily() 53 | WithThemeOverlay(R.style.ThemeOverlay_MdcThemeTest_DefaultFontFamily_Rubik) { 54 | MdcTheme(setDefaultFontFamily = true) { 55 | MaterialTheme.typography.assertFontFamilies(expected = rubik) 56 | } 57 | } 58 | WithThemeOverlay(R.style.ThemeOverlay_MdcThemeTest_DefaultAndroidFontFamily_Rubik) { 59 | MdcTheme(setDefaultFontFamily = true) { 60 | MaterialTheme.typography.assertFontFamilies(expected = rubik) 61 | } 62 | } 63 | } 64 | 65 | @Test 66 | @SdkSuppress(minSdkVersion = 23) // XML font families with >1 fonts are only supported on API 23+ 67 | fun rubik_family_api23() = composeTestRule.setContent { 68 | val rubik = FontFamily( 69 | Font(R.font.rubik_300, FontWeight.W300), 70 | Font(R.font.rubik_400, FontWeight.W400), 71 | Font(R.font.rubik_500, FontWeight.W500), 72 | Font(R.font.rubik_700, FontWeight.W700), 73 | ) 74 | WithThemeOverlay(R.style.ThemeOverlay_MdcThemeTest_DefaultFontFamily_Rubik) { 75 | MdcTheme(setDefaultFontFamily = true) { 76 | MaterialTheme.typography.assertFontFamilies(expected = rubik) 77 | } 78 | } 79 | WithThemeOverlay(R.style.ThemeOverlay_MdcThemeTest_DefaultAndroidFontFamily_Rubik) { 80 | MdcTheme(setDefaultFontFamily = true) { 81 | MaterialTheme.typography.assertFontFamilies(expected = rubik) 82 | } 83 | } 84 | } 85 | 86 | @Test 87 | fun rubik_fixed400() = composeTestRule.setContent { 88 | val rubik400 = Font(R.font.rubik_400, FontWeight.W400).toFontFamily() 89 | WithThemeOverlay(R.style.ThemeOverlay_MdcThemeTest_DefaultFontFamily_Rubik400) { 90 | MdcTheme(setDefaultFontFamily = true) { 91 | MaterialTheme.typography.assertFontFamilies(expected = rubik400) 92 | } 93 | } 94 | WithThemeOverlay(R.style.ThemeOverlay_MdcThemeTest_DefaultAndroidFontFamily_Rubik400) { 95 | MdcTheme(setDefaultFontFamily = true) { 96 | MaterialTheme.typography.assertFontFamilies(expected = rubik400) 97 | } 98 | } 99 | } 100 | 101 | @Test 102 | fun rubik_fixed700_withTextAppearances() = composeTestRule.setContent { 103 | val rubik700 = Font(R.font.rubik_700, FontWeight.W700).toFontFamily() 104 | WithThemeOverlay( 105 | R.style.ThemeOverlay_MdcThemeTest_DefaultFontFamilies_Rubik700_WithTextAppearances 106 | ) { 107 | MdcTheme { 108 | MaterialTheme.typography.assertFontFamilies( 109 | expected = rubik700, 110 | notEquals = true 111 | ) 112 | } 113 | } 114 | } 115 | } 116 | 117 | private fun Typography.assertFontFamilies( 118 | expected: FontFamily, 119 | notEquals: Boolean = false 120 | ) { 121 | if (notEquals) assertNotEquals(expected, h1.fontFamily) else assertEquals(expected, h1.fontFamily) 122 | if (notEquals) assertNotEquals(expected, h2.fontFamily) else assertEquals(expected, h2.fontFamily) 123 | if (notEquals) assertNotEquals(expected, h3.fontFamily) else assertEquals(expected, h3.fontFamily) 124 | if (notEquals) assertNotEquals(expected, h4.fontFamily) else assertEquals(expected, h4.fontFamily) 125 | if (notEquals) assertNotEquals(expected, h5.fontFamily) else assertEquals(expected, h5.fontFamily) 126 | if (notEquals) assertNotEquals(expected, h6.fontFamily) else assertEquals(expected, h6.fontFamily) 127 | if (notEquals) assertNotEquals(expected, subtitle1.fontFamily) else assertEquals(expected, subtitle1.fontFamily) 128 | if (notEquals) assertNotEquals(expected, subtitle2.fontFamily) else assertEquals(expected, subtitle2.fontFamily) 129 | if (notEquals) assertNotEquals(expected, body1.fontFamily) else assertEquals(expected, body1.fontFamily) 130 | if (notEquals) assertNotEquals(expected, body2.fontFamily) else assertEquals(expected, body2.fontFamily) 131 | if (notEquals) assertNotEquals(expected, button.fontFamily) else assertEquals(expected, button.fontFamily) 132 | if (notEquals) assertNotEquals(expected, caption.fontFamily) else assertEquals(expected, caption.fontFamily) 133 | if (notEquals) assertNotEquals(expected, overline.fontFamily) else assertEquals(expected, overline.fontFamily) 134 | } 135 | 136 | /** 137 | * Function which applies an Android theme overlay to the current context. 138 | */ 139 | @Composable 140 | fun WithThemeOverlay( 141 | @StyleRes themeOverlayId: Int, 142 | content: @Composable () -> Unit, 143 | ) { 144 | val themedContext = ContextThemeWrapper(LocalContext.current, themeOverlayId) 145 | CompositionLocalProvider(LocalContext provides themedContext, content = content) 146 | } 147 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/LightMdcActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter.test 18 | 19 | import android.content.Context 20 | import androidx.appcompat.app.AppCompatActivity 21 | import androidx.appcompat.app.AppCompatDelegate 22 | 23 | /** 24 | * An [AppCompatActivity] which forces the night mode to 'light theme'. 25 | */ 26 | class LightMdcActivity : AppCompatActivity() { 27 | override fun attachBaseContext(newBase: Context) { 28 | delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_NO 29 | super.attachBaseContext(newBase) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/MdcThemeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") 18 | 19 | package com.google.android.material.composethemeadapter.test 20 | 21 | import androidx.appcompat.app.AppCompatActivity 22 | import androidx.compose.foundation.shape.CornerSize 23 | import androidx.compose.foundation.shape.CutCornerShape 24 | import androidx.compose.foundation.shape.RoundedCornerShape 25 | import androidx.compose.material.LocalContentColor 26 | import androidx.compose.material.MaterialTheme 27 | import androidx.compose.ui.geometry.Size 28 | import androidx.compose.ui.platform.LocalDensity 29 | import androidx.compose.ui.res.colorResource 30 | import androidx.compose.ui.test.junit4.createAndroidComposeRule 31 | import androidx.compose.ui.text.font.Font 32 | import androidx.compose.ui.text.font.FontFamily 33 | import androidx.compose.ui.text.font.FontWeight 34 | import androidx.compose.ui.text.font.toFontFamily 35 | import androidx.compose.ui.unit.Density 36 | import androidx.compose.ui.unit.Dp 37 | import androidx.compose.ui.unit.TextUnit 38 | import androidx.compose.ui.unit.dp 39 | import androidx.compose.ui.unit.em 40 | import androidx.compose.ui.unit.sp 41 | import androidx.test.filters.MediumTest 42 | import com.google.android.material.composethemeadapter.MdcTheme 43 | import com.google.android.material.composethemeadapter.core.FontFamilyWithWeight 44 | import org.junit.Assert.assertEquals 45 | import org.junit.Assert.assertNotNull 46 | import org.junit.Assert.assertNull 47 | import org.junit.Assert.assertTrue 48 | import org.junit.Rule 49 | import org.junit.Test 50 | import org.junit.runner.RunWith 51 | import org.junit.runners.Parameterized 52 | 53 | @MediumTest 54 | @RunWith(Parameterized::class) 55 | class MdcThemeTest(activityClass: Class) { 56 | companion object { 57 | @JvmStatic 58 | @Parameterized.Parameters 59 | fun activities() = listOf(DarkMdcActivity::class.java, LightMdcActivity::class.java) 60 | } 61 | 62 | @get:Rule 63 | val composeTestRule = createAndroidComposeRule(activityClass) 64 | 65 | @Test 66 | fun colors() = composeTestRule.setContent { 67 | MdcTheme { 68 | val color = MaterialTheme.colors 69 | 70 | assertEquals(colorResource(R.color.aquamarine), color.primary) 71 | assertEquals(colorResource(R.color.royal_blue), color.primaryVariant) 72 | assertEquals(colorResource(R.color.midnight_blue), color.onPrimary) 73 | 74 | assertEquals(colorResource(R.color.dark_golden_rod), color.secondary) 75 | assertEquals(colorResource(R.color.slate_gray), color.onSecondary) 76 | assertEquals(colorResource(R.color.blue_violet), color.secondaryVariant) 77 | 78 | assertEquals(colorResource(R.color.spring_green), color.surface) 79 | assertEquals(colorResource(R.color.navy), color.onSurface) 80 | 81 | assertEquals(colorResource(R.color.dark_salmon), color.error) 82 | assertEquals(colorResource(R.color.beige), color.onError) 83 | 84 | assertEquals(colorResource(R.color.light_coral), color.background) 85 | assertEquals(colorResource(R.color.orchid), color.onBackground) 86 | 87 | // MdcTheme updates the LocalContentColor to match the calculated onBackground 88 | assertEquals(colorResource(R.color.orchid), LocalContentColor.current) 89 | } 90 | } 91 | 92 | @Test 93 | fun shapes() = composeTestRule.setContent { 94 | MdcTheme { 95 | val shapes = MaterialTheme.shapes 96 | val density = LocalDensity.current 97 | 98 | shapes.small.run { 99 | assertTrue(this is CutCornerShape) 100 | assertEquals(4f, topStart.toPx(density)) 101 | assertEquals(9.dp.scaleToPx(density), topEnd.toPx(density)) 102 | assertEquals(5f, bottomEnd.toPx(density)) 103 | assertEquals(3.dp.scaleToPx(density), bottomStart.toPx(density)) 104 | } 105 | shapes.medium.run { 106 | assertTrue(this is RoundedCornerShape) 107 | assertEquals(12.dp.scaleToPx(density), topStart.toPx(density)) 108 | assertEquals(12.dp.scaleToPx(density), topEnd.toPx(density)) 109 | assertEquals(12.dp.scaleToPx(density), bottomEnd.toPx(density)) 110 | assertEquals(12.dp.scaleToPx(density), bottomStart.toPx(density)) 111 | } 112 | shapes.large.run { 113 | assertTrue(this is CutCornerShape) 114 | assertEquals(0f, topStart.toPx(density)) 115 | assertEquals(0f, topEnd.toPx(density)) 116 | assertEquals(0f, bottomEnd.toPx(density)) 117 | assertEquals(0f, bottomStart.toPx(density)) 118 | } 119 | } 120 | } 121 | 122 | @Test 123 | fun type() = composeTestRule.setContent { 124 | MdcTheme { 125 | val typography = MaterialTheme.typography 126 | val density = LocalDensity.current 127 | 128 | val rubik = FontFamily( 129 | Font(resId = R.font.rubik_300, weight = FontWeight.W300), 130 | Font(resId = R.font.rubik_400, weight = FontWeight.W400), 131 | Font(resId = R.font.rubik_500, weight = FontWeight.W500), 132 | Font(resId = R.font.rubik_700, weight = FontWeight.W700) 133 | ) 134 | val rubik300 = Font(R.font.rubik_300).toFontFamily() 135 | val rubik400 = Font(R.font.rubik_400).toFontFamily() 136 | val sansSerif = FontFamilyWithWeight(FontFamily.SansSerif) 137 | val sansSerifLight = FontFamilyWithWeight(FontFamily.SansSerif, FontWeight.Light) 138 | val sansSerifBlack = FontFamilyWithWeight(FontFamily.SansSerif, FontWeight.Black) 139 | val serif = FontFamilyWithWeight(FontFamily.Serif) 140 | val cursive = FontFamilyWithWeight(FontFamily.Cursive) 141 | val monospace = FontFamilyWithWeight(FontFamily.Monospace) 142 | 143 | typography.h1.run { 144 | assertTextUnitEquals(97.54.sp, fontSize, density) 145 | assertTextUnitEquals((-0.0015).em, letterSpacing, density) 146 | assertEquals(rubik300, fontFamily) 147 | } 148 | 149 | assertNotNull(typography.h2.shadow) 150 | typography.h2.shadow!!.run { 151 | assertEquals(colorResource(R.color.olive_drab), color) 152 | assertEquals(4.43f, offset.x) 153 | assertEquals(8.19f, offset.y) 154 | assertEquals(2.13f, blurRadius) 155 | } 156 | 157 | typography.h3.run { 158 | assertEquals(sansSerif.fontFamily, fontFamily) 159 | assertEquals(sansSerif.weight, fontWeight) 160 | } 161 | 162 | typography.h4.run { 163 | assertEquals(sansSerifLight.fontFamily, fontFamily) 164 | assertEquals(sansSerifLight.weight, fontWeight) 165 | } 166 | 167 | typography.h5.run { 168 | assertEquals(sansSerifBlack.fontFamily, fontFamily) 169 | assertEquals(sansSerifBlack.weight, fontWeight) 170 | } 171 | 172 | typography.h6.run { 173 | assertEquals(serif.fontFamily, fontFamily) 174 | assertEquals(serif.weight, fontWeight) 175 | } 176 | 177 | typography.body1.run { 178 | assertTextUnitEquals(16.26.sp, fontSize, density) 179 | assertTextUnitEquals(0.005.em, letterSpacing, density) 180 | assertEquals(rubik400, fontFamily) 181 | assertNull(shadow) 182 | } 183 | 184 | typography.body2.run { 185 | assertEquals(cursive.fontFamily, fontFamily) 186 | assertEquals(cursive.weight, fontWeight) 187 | } 188 | 189 | typography.subtitle1.run { 190 | assertEquals(monospace.fontFamily, fontFamily) 191 | assertEquals(monospace.weight, fontWeight) 192 | assertTextUnitEquals(0.em, letterSpacing, density) 193 | } 194 | 195 | typography.subtitle2.run { 196 | assertEquals(FontFamily.SansSerif, fontFamily) 197 | } 198 | 199 | typography.button.run { 200 | assertEquals(rubik, fontFamily) 201 | } 202 | 203 | typography.caption.run { 204 | assertEquals(FontFamily.SansSerif, fontFamily) 205 | assertTextUnitEquals(0.04.em, letterSpacing, density) 206 | } 207 | 208 | typography.overline.run { 209 | assertEquals(FontFamily.SansSerif, fontFamily) 210 | } 211 | } 212 | } 213 | } 214 | 215 | private fun Dp.scaleToPx(density: Density): Float { 216 | val dp = this 217 | return with(density) { dp.toPx() } 218 | } 219 | 220 | private fun assertTextUnitEquals(expected: TextUnit, actual: TextUnit, density: Density) { 221 | if (expected.javaClass == actual.javaClass) { 222 | // If the expected and actual are the same type, compare the raw values with a 223 | // delta to account for float inaccuracy 224 | assertEquals(expected.value, actual.value, 0.001f) 225 | } else { 226 | // Otherwise we need to flatten to a px to compare the values. Again using a 227 | // delta to account for float inaccuracy 228 | with(density) { assertEquals(expected.toPx(), actual.toPx(), 0.001f) } 229 | } 230 | } 231 | 232 | private fun CornerSize.toPx(density: Density) = toPx(Size.Unspecified, density) 233 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/NotMdcActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter.test 18 | 19 | import androidx.appcompat.app.AppCompatActivity 20 | 21 | class NotMdcActivity : AppCompatActivity() 22 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/java/com/google/android/material/composethemeadapter/test/NotMdcThemeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") 18 | 19 | package com.google.android.material.composethemeadapter.test 20 | 21 | import androidx.compose.ui.test.junit4.createAndroidComposeRule 22 | import androidx.test.filters.MediumTest 23 | import com.google.android.material.composethemeadapter.MdcTheme 24 | import org.junit.Rule 25 | import org.junit.Test 26 | import org.junit.runner.RunWith 27 | import org.junit.runners.JUnit4 28 | 29 | @MediumTest 30 | @RunWith(JUnit4::class) 31 | class NotMdcThemeTest { 32 | @get:Rule 33 | val composeTestRule = createAndroidComposeRule() 34 | 35 | @Test(expected = IllegalArgumentException::class) 36 | fun throwForNonMdcTheme() = composeTestRule.setContent { 37 | MdcTheme { 38 | // Nothing to do here, exception should be thrown 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/font/rubik.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 22 | 25 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/font/rubik_300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/materialLib/src/androidTest/res/font/rubik_300.ttf -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/font/rubik_400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/materialLib/src/androidTest/res/font/rubik_400.ttf -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/font/rubik_500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/materialLib/src/androidTest/res/font/rubik_500.ttf -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/font/rubik_700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/materialLib/src/androidTest/res/font/rubik_700.ttf -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 30 | 31 | 35 | 36 | 39 | 40 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/values/test_colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | #7FFFD4 21 | #4169E1 22 | #191970 23 | #B8860B 24 | #8A2BE2 25 | #708090 26 | #00FA9A 27 | #000080 28 | #F08080 29 | #DA70D6 30 | #E9967A 31 | #F5F5DC 32 | #6B8E23 33 | -------------------------------------------------------------------------------- /materialLib/src/androidTest/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 55 | 56 | 61 | 62 | 65 | 66 | 69 | 70 | 73 | 74 | 92 | 93 | 25 | 26 | 32 | 33 | 36 | 37 | 40 | 41 | 44 | 45 | 48 | 49 | 54 | 55 | 58 | 59 | 60 | 63 | 64 | 67 | 68 | 71 | 72 | 76 | 77 | 78 | 79 | sans-serif-condensed-light 80 | 81 | 84 | 85 | -------------------------------------------------------------------------------- /materialLib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /materialLib/src/main/java/com/google/android/material/composethemeadapter/Typography.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | package com.google.android.material.composethemeadapter 18 | 19 | import androidx.compose.material.Typography 20 | import androidx.compose.ui.text.TextStyle 21 | 22 | private val emptyTextStyle = TextStyle() 23 | 24 | internal fun Typography.merge( 25 | h1: TextStyle = emptyTextStyle, 26 | h2: TextStyle = emptyTextStyle, 27 | h3: TextStyle = emptyTextStyle, 28 | h4: TextStyle = emptyTextStyle, 29 | h5: TextStyle = emptyTextStyle, 30 | h6: TextStyle = emptyTextStyle, 31 | subtitle1: TextStyle = emptyTextStyle, 32 | subtitle2: TextStyle = emptyTextStyle, 33 | body1: TextStyle = emptyTextStyle, 34 | body2: TextStyle = emptyTextStyle, 35 | button: TextStyle = emptyTextStyle, 36 | caption: TextStyle = emptyTextStyle, 37 | overline: TextStyle = emptyTextStyle 38 | ) = copy( 39 | h1 = this.h1.merge(h1), 40 | h2 = this.h2.merge(h2), 41 | h3 = this.h3.merge(h3), 42 | h4 = this.h4.merge(h4), 43 | h5 = this.h5.merge(h5), 44 | h6 = this.h6.merge(h6), 45 | subtitle1 = this.subtitle1.merge(subtitle1), 46 | subtitle2 = this.subtitle2.merge(subtitle2), 47 | body1 = this.body1.merge(body1), 48 | body2 = this.body2.merge(body2), 49 | button = this.button.merge(button), 50 | caption = this.caption.merge(caption), 51 | overline = this.overline.merge(overline) 52 | ) 53 | -------------------------------------------------------------------------------- /materialLib/src/main/res/values/theme_attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Project information 2 | site_name: 'MDC-Android Compose Theme Adapter' 3 | site_description: 'A library that enables reuse of Material Components for Android XML themes for theming in Jetpack Compose.' 4 | site_author: 'Material Components' 5 | site_url: 'https://material-components.github.io/material-components-android-compose-theme-adapter/' 6 | remote_branch: gh-pages 7 | 8 | # Repository 9 | repo_name: 'MDC-Android Compose Theme Adapter' 10 | repo_url: 'https://github.com/material-components/material-components-android-compose-theme-adapter' 11 | 12 | # Navigation 13 | nav: 14 | - 'Overview': index.md 15 | - 'API': api/lib/index.md 16 | - 'Snapshots': using-snapshot-version.md 17 | - 'Contributing': contributing.md 18 | 19 | # Configuration 20 | theme: 21 | name: 'material' 22 | language: 'en' 23 | favicon: 'favicon.ico' 24 | logo: 'logo.svg' 25 | palette: 26 | primary: 'black' 27 | accent: 'white' 28 | font: 29 | text: 'Roboto' 30 | code: 'Roboto Mono' 31 | 32 | # Extensions 33 | markdown_extensions: 34 | - admonition 35 | - codehilite: 36 | guess_lang: false 37 | - footnotes 38 | - toc: 39 | permalink: true 40 | - pymdownx.betterem 41 | - pymdownx.superfences -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | import com.google.android.material.composethemeadapter.Libs 18 | 19 | plugins { 20 | id 'com.android.application' 21 | id 'kotlin-android' 22 | } 23 | 24 | android { 25 | compileSdkVersion 33 26 | 27 | defaultConfig { 28 | minSdkVersion 21 29 | targetSdkVersion 33 30 | 31 | versionCode 1 32 | versionName "1.0" 33 | } 34 | 35 | compileOptions { 36 | sourceCompatibility JavaVersion.VERSION_1_8 37 | targetCompatibility JavaVersion.VERSION_1_8 38 | } 39 | 40 | buildFeatures { 41 | compose true 42 | } 43 | 44 | composeOptions { 45 | kotlinCompilerExtensionVersion Libs.AndroidX.Compose.compilerVersion 46 | } 47 | 48 | buildTypes { 49 | release { 50 | signingConfig signingConfigs.debug 51 | } 52 | } 53 | } 54 | 55 | dependencies { 56 | implementation project(':materialLib') 57 | implementation project(':material3Lib') 58 | 59 | implementation Libs.AndroidX.Compose.runtime 60 | implementation Libs.AndroidX.Compose.material 61 | implementation Libs.AndroidX.Compose.material3 62 | implementation Libs.AndroidX.Compose.layout 63 | implementation Libs.AndroidX.Compose.tooling 64 | 65 | implementation Libs.AndroidX.coreKtx 66 | 67 | implementation Libs.mdc 68 | implementation Libs.Kotlin.stdlib 69 | } 70 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /sample/src/main/java/com/google/android/material/composethemeadapter/sample/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") // ListActivity 18 | 19 | package com.google.android.material.composethemeadapter.sample 20 | 21 | import android.annotation.SuppressLint 22 | import android.app.ListActivity 23 | import android.content.Intent 24 | import android.os.Bundle 25 | import android.view.View 26 | import android.widget.ListView 27 | import android.widget.SimpleAdapter 28 | import java.text.Collator 29 | import java.util.ArrayList 30 | import java.util.Collections 31 | import java.util.Comparator 32 | import java.util.HashMap 33 | 34 | /** 35 | * A [ListActivity] which automatically populates the list of sample activities in this app 36 | * with the category defined as the app package name + `.SAMPLE_CODE`. 37 | */ 38 | class MainActivity : ListActivity() { 39 | override fun onCreate(savedInstanceState: Bundle?) { 40 | super.onCreate(savedInstanceState) 41 | 42 | listAdapter = SimpleAdapter( 43 | this, 44 | getData(intent.getStringExtra(EXTRA_PATH)), 45 | android.R.layout.simple_list_item_1, 46 | arrayOf("title"), 47 | intArrayOf(android.R.id.text1) 48 | ) 49 | 50 | listView.isTextFilterEnabled = true 51 | } 52 | 53 | private fun getData(prefix: String?): List> { 54 | val myData = ArrayList>() 55 | 56 | val mainIntent = Intent(Intent.ACTION_MAIN, null) 57 | mainIntent.addCategory("${applicationInfo.packageName}.SAMPLE_CODE") 58 | 59 | @SuppressLint("QueryPermissionsNeeded") 60 | val list = packageManager.queryIntentActivities(mainIntent, 0) 61 | 62 | val prefixPath: Array? 63 | var prefixWithSlash = prefix 64 | 65 | if (prefix.isNullOrEmpty()) { 66 | prefixPath = null 67 | } else { 68 | prefixPath = prefix.split("/".toRegex()).toTypedArray() 69 | prefixWithSlash = "$prefix/" 70 | } 71 | 72 | val entries = HashMap() 73 | 74 | list.forEach { info -> 75 | val labelSeq = info.loadLabel(packageManager) 76 | val label = labelSeq?.toString() ?: info.activityInfo.name 77 | 78 | if (prefixWithSlash.isNullOrEmpty() || label.startsWith(prefixWithSlash)) { 79 | val labelPath = label.split("/".toRegex()).toTypedArray() 80 | val nextLabel = if (prefixPath == null) labelPath[0] else labelPath[prefixPath.size] 81 | if (prefixPath?.size ?: 0 == labelPath.size - 1) { 82 | addItem( 83 | data = myData, 84 | name = nextLabel, 85 | intent = activityIntent( 86 | info.activityInfo.applicationInfo.packageName, 87 | info.activityInfo.name 88 | ) 89 | ) 90 | } else { 91 | if (entries[nextLabel] == null) { 92 | addItem( 93 | data = myData, 94 | name = nextLabel, 95 | intent = browseIntent( 96 | if (prefix == "") nextLabel else "$prefix/$nextLabel" 97 | ) 98 | ) 99 | entries[nextLabel] = true 100 | } 101 | } 102 | } 103 | } 104 | 105 | Collections.sort(myData, sDisplayNameComparator) 106 | 107 | return myData 108 | } 109 | 110 | private fun activityIntent(pkg: String, componentName: String): Intent { 111 | val result = Intent() 112 | result.setClassName(pkg, componentName) 113 | return result 114 | } 115 | 116 | private fun browseIntent(path: String): Intent { 117 | val result = Intent() 118 | result.setClass(this, MainActivity::class.java) 119 | result.putExtra(EXTRA_PATH, path) 120 | return result 121 | } 122 | 123 | private fun addItem(data: MutableList>, name: String, intent: Intent) { 124 | val temp = mutableMapOf() 125 | temp["title"] = name 126 | temp["intent"] = intent 127 | data += temp 128 | } 129 | 130 | override fun onListItemClick(l: ListView, v: View, position: Int, id: Long) { 131 | val map = l.getItemAtPosition(position) as Map<*, *> 132 | val intent = map["intent"] as Intent? 133 | startActivity(intent) 134 | } 135 | 136 | companion object { 137 | private const val EXTRA_PATH = "com.example.android.apis.Path" 138 | 139 | private val sDisplayNameComparator = object : Comparator> { 140 | private val collator = Collator.getInstance() 141 | 142 | override fun compare(map1: Map, map2: Map): Int { 143 | return collator.compare(map1["title"], map2["title"]) 144 | } 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /sample/src/main/java/com/google/android/material/composethemeadapter/sample/MaterialIntegration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | @file:Suppress("DEPRECATION") 18 | 19 | package com.google.android.material.composethemeadapter.sample 20 | 21 | import android.os.Bundle 22 | import androidx.appcompat.app.AppCompatActivity 23 | import androidx.compose.foundation.layout.Column 24 | import androidx.compose.foundation.layout.Spacer 25 | import androidx.compose.foundation.layout.height 26 | import androidx.compose.foundation.layout.padding 27 | import androidx.compose.foundation.rememberScrollState 28 | import androidx.compose.foundation.verticalScroll 29 | import androidx.compose.material.Button 30 | import androidx.compose.material.CircularProgressIndicator 31 | import androidx.compose.material.ExtendedFloatingActionButton 32 | import androidx.compose.material.FloatingActionButton 33 | import androidx.compose.material.Icon 34 | import androidx.compose.material.MaterialTheme 35 | import androidx.compose.material.OutlinedButton 36 | import androidx.compose.material.Scaffold 37 | import androidx.compose.material.Text 38 | import androidx.compose.material.TextButton 39 | import androidx.compose.material.TextField 40 | import androidx.compose.material.TopAppBar 41 | import androidx.compose.material.icons.Icons 42 | import androidx.compose.material.icons.filled.Favorite 43 | import androidx.compose.runtime.Composable 44 | import androidx.compose.ui.Modifier 45 | import androidx.compose.ui.platform.ComposeView 46 | import androidx.compose.ui.res.stringResource 47 | import androidx.compose.ui.tooling.preview.Preview 48 | import androidx.compose.ui.unit.dp 49 | import com.google.android.material.composethemeadapter.MdcTheme 50 | 51 | class MaterialIntegrationActivity : AppCompatActivity() { 52 | override fun onCreate(savedInstanceState: Bundle?) { 53 | super.onCreate(savedInstanceState) 54 | 55 | val contentView = ComposeView(this) 56 | setContentView(contentView) 57 | 58 | contentView.setContent { 59 | MdcTheme { 60 | MaterialComponentsSample() 61 | } 62 | } 63 | } 64 | } 65 | 66 | @Preview 67 | @Composable 68 | fun MaterialComponentsSamplePreview() { 69 | MdcTheme { 70 | MaterialComponentsSample() 71 | } 72 | } 73 | 74 | @Composable 75 | fun MaterialComponentsSample() { 76 | Scaffold( 77 | topBar = { 78 | TopAppBar( 79 | title = { Text(text = stringResource(R.string.material_integration)) } 80 | ) 81 | } 82 | ) { padding -> 83 | Column( 84 | modifier = Modifier 85 | .verticalScroll(rememberScrollState()) 86 | .padding(padding) 87 | .padding(16.dp) 88 | ) { 89 | CircularProgressIndicator() 90 | VerticalSpacer() 91 | 92 | Button(onClick = {}) { 93 | Text(text = "Button") 94 | } 95 | VerticalSpacer() 96 | 97 | OutlinedButton(onClick = {}) { 98 | Text(text = "Outlined Button") 99 | } 100 | VerticalSpacer() 101 | 102 | TextButton(onClick = {}) { 103 | Text(text = "Text Button") 104 | } 105 | VerticalSpacer() 106 | 107 | FloatingActionButton( 108 | onClick = {}, 109 | content = { Icon(Icons.Default.Favorite, null) } 110 | ) 111 | VerticalSpacer() 112 | 113 | ExtendedFloatingActionButton( 114 | onClick = {}, 115 | text = { Text(text = "Extended FAB") }, 116 | icon = { Icon(Icons.Default.Favorite, null) } 117 | ) 118 | VerticalSpacer() 119 | 120 | TextField( 121 | value = "", 122 | onValueChange = {}, 123 | label = { Text(text = "Text field") } 124 | ) 125 | VerticalSpacer() 126 | 127 | Text( 128 | text = "H1", 129 | style = MaterialTheme.typography.h1 130 | ) 131 | Text( 132 | text = "Headline 2", 133 | style = MaterialTheme.typography.h2 134 | ) 135 | Text( 136 | text = "Headline 3", 137 | style = MaterialTheme.typography.h3 138 | ) 139 | Text( 140 | text = "Headline 4", 141 | style = MaterialTheme.typography.h4 142 | ) 143 | Text( 144 | text = "Headline 5", 145 | style = MaterialTheme.typography.h5 146 | ) 147 | Text( 148 | text = "Headline 6", 149 | style = MaterialTheme.typography.h6 150 | ) 151 | Text( 152 | text = "Subtitle 1", 153 | style = MaterialTheme.typography.subtitle1 154 | ) 155 | Text( 156 | text = "Subtitle 2", 157 | style = MaterialTheme.typography.subtitle2 158 | ) 159 | Text( 160 | text = "Body 1", 161 | style = MaterialTheme.typography.body1 162 | ) 163 | Text( 164 | text = "Body 2", 165 | style = MaterialTheme.typography.body2 166 | ) 167 | Text( 168 | text = "Caption", 169 | style = MaterialTheme.typography.caption 170 | ) 171 | Text( 172 | text = "Overline", 173 | style = MaterialTheme.typography.overline 174 | ) 175 | } 176 | } 177 | } 178 | 179 | @Composable 180 | private fun VerticalSpacer() { 181 | Spacer(Modifier.height(8.dp)) 182 | } 183 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 23 | 28 | 29 | 35 | 38 | 41 | 42 | 43 | 44 | 50 | 51 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 | 71 | 76 | 81 | 86 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 136 | 141 | 146 | 151 | 156 | 161 | 166 | 171 | 176 | 181 | 186 | 187 | -------------------------------------------------------------------------------- /sample/src/main/res/font/dancingscript.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 22 | 25 | 28 | 31 | -------------------------------------------------------------------------------- /sample/src/main/res/font/dancingscript_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/font/dancingscript_bold.ttf -------------------------------------------------------------------------------- /sample/src/main/res/font/dancingscript_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/font/dancingscript_medium.ttf -------------------------------------------------------------------------------- /sample/src/main/res/font/dancingscript_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/font/dancingscript_regular.ttf -------------------------------------------------------------------------------- /sample/src/main/res/font/dancingscript_semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/font/dancingscript_semibold.ttf -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/material-components/material-components-android-compose-theme-adapter/55c475bd31f60f5cc2e4f8a9659a6a73dd0cc625/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | #ff8a65 19 | #f4511e 20 | #ff4081 21 | #c60055 22 | 23 | -------------------------------------------------------------------------------- /sample/src/main/res/values/shape.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 22 | 23 | 27 | 28 | 32 | 33 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Compose Theme Adapter Sample 19 | Material integration sample 20 | Material 3 integration sample 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 34 | 37 | 38 | -------------------------------------------------------------------------------- /sample/src/main/res/values/type.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | 29 | 30 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 The Android Open Source Project 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 | * https://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 | 17 | include ':core' 18 | include ':materialLib' 19 | include ':material3Lib' 20 | include ':sample' 21 | -------------------------------------------------------------------------------- /spotless/copyright.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright $YEAR The Android Open Source Project 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 | * https://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 | 17 | --------------------------------------------------------------------------------