diff --git a/build.gradle b/build.gradle index 3dfcf8ce1f6..ede94c607e8 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath libs.android.gradle.plugin } } @@ -17,40 +17,10 @@ allprojects { } ext { - compileSdkVersion = 34 + compileSdkVersion = 35 minSdkVersion = 21 targetSdkVersion = 33 - androidXVersions = [ - activity : '1.8.0', - annotation : '1.2.0', - appCompat : '1.6.1', - cardView : '1.0.0', - constraintlayout : '2.0.1', - coordinatorlayout : '1.1.0', - core : '1.6.0', - drawerlayout : '1.1.1', - experimental : '1.0.0', - fragment : '1.2.5', - lifecycle : '2.0.0', - recyclerView : '1.0.0', - recyclerViewSelection : '1.0.0', - resourceInspectionAnnotation : '1.0.1', - resourceInspectionProcessor : '1.0.1', - transition : '1.5.0', - vectorDrawable : '1.1.0', - viewpager2 : '1.0.0', - dynamicanimation : '1.0.0', - graphicsShapes : '1.0.1', - ] - - errorproneVersion = '2.15.0' - testRunnerVersion = '1.4.0' - espressoVersion = '3.1.0' - mockitoCoreVersion = '2.25.0' - truthVersion = '0.45' - robolectricVersion = '4.9' - // Enforce the use of prebuilt dependencies in all sub-projects. This is // required for the doclava dependency. usePrebuilts = "true" @@ -59,7 +29,7 @@ ext { ? project.property('mavenRepoUrl') : '/tmp/myRepo/') // Current version of the library (could be in-development/unreleased). - mdcLibraryVersion = '1.13.0-alpha08' + mdcLibraryVersion = '1.13.0-alpha13' mdcLibraryPackage = "com.google.android.material" mdcLibraryDir = "com/google/android/material" } @@ -83,56 +53,6 @@ private def getTransformedProjectPath(projectPath) { return result } -/** - * Return the module dependency for the given compatibility library name. - */ -def compatibility(name) { - switch (name) { - case "activity": - return "androidx.activity:activity:${androidXVersions.activity}" - case "annotation": - return "androidx.annotation:annotation:${androidXVersions.annotation}" - case "appcompat": - return "androidx.appcompat:appcompat:${androidXVersions.appCompat}" - case "cardview": - return "androidx.cardview:cardview:${androidXVersions.cardView}" - case "constraintlayout": - return "androidx.constraintlayout:constraintlayout:${androidXVersions.constraintlayout}" - case "coordinatorlayout": - return "androidx.coordinatorlayout:coordinatorlayout:${androidXVersions.coordinatorlayout}" - case "core": - return "androidx.core:core:${androidXVersions.core}" - case "drawerlayout": - return "androidx.drawerlayout:drawerlayout:${androidXVersions.drawerlayout}" - case "dynamicanimation": - return "androidx.dynamicanimation:dynamicanimation:${androidXVersions.dynamicanimation}" - case "fragment": - return "androidx.fragment:fragment:${androidXVersions.fragment}" - case "lifecycleRuntime": - return "androidx.lifecycle:lifecycle-runtime:${androidXVersions.lifecycle}" - case "recyclerview": - return "androidx.recyclerview:recyclerview:${androidXVersions.recyclerView}" - case "transition": - return "androidx.transition:transition:${androidXVersions.transition}" - case "vectordrawable": - return "androidx.vectordrawable:vectordrawable:${androidXVersions.vectorDrawable}" - case "recyclerViewSelection": - return "androidx.recyclerview:recyclerview-selection:${androidXVersions.recyclerViewSelection}" - case "resourceInspectionAnnotation": - return "androidx.resourceinspection:resourceinspection-annotation:${androidXVersions.resourceInspectionAnnotation}" - case "resourceInspectionProcessor": - return "androidx.resourceinspection:resourceinspection-processor:${androidXVersions.resourceInspectionProcessor}" - case "viewpager2": - return "androidx.viewpager2:viewpager2:${androidXVersions.viewpager2}" - case "graphicsShapes": - return "androidx.graphics:graphics-shapes:${androidXVersions.graphicsShapes}" - case "experimental": - return "androidx.annotation:annotation-experimental:${androidXVersions.experimental}" - default: - throw new IllegalArgumentException("No mapping exists for name: $name.") - } -} - /** * Return the project dependency for the given project path. */ @@ -161,12 +81,12 @@ def getArchivesBaseName(name) { } subprojects { - tasks.withType(Test) { - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - forkEvery = 80 - maxHeapSize = "2048m" - minHeapSize = "1024m" - } + tasks.withType(Test) { + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + forkEvery = 80 + maxHeapSize = "2048m" + minHeapSize = "1024m" + } } subprojects { diff --git a/catalog/build.gradle b/catalog/build.gradle index c353dc9e102..60b8526c9fb 100644 --- a/catalog/build.gradle +++ b/catalog/build.gradle @@ -3,51 +3,50 @@ apply plugin: 'com.android.application' dependencies { // Align kotlin versions - implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.22")) + implementation(platform(libs.kotlin.bom)) - api 'com.google.dagger:dagger:2.51.1' - annotationProcessor 'com.google.dagger:dagger-compiler:2.51.1' + api libs.dagger + annotationProcessor libs.dagger.compiler - api 'com.google.dagger:dagger-android:2.51.1' - api 'com.google.dagger:dagger-android-support:2.51.1' - annotationProcessor 'com.google.dagger:dagger-android-processor:2.51.1' + api libs.dagger.android + api libs.dagger.android.support + annotationProcessor libs.dagger.android.processor - api 'androidx.multidex:multidex:2.0.1' - api 'androidx.constraintlayout:constraintlayout:2.1.0' - api 'androidx.gridlayout:gridlayout:1.0.0' - api "androidx.multidex:multidex:2.0.1" - api "androidx.recyclerview:recyclerview:1.2.1" - api 'androidx.window:window:1.0.0-beta04' - api "androidx.window:window-java:1.0.0-beta04" - api "androidx.preference:preference:1.1.1" + api libs.androidx.multidex + api libs.androidx.constraintlayout + api libs.androidx.gridlayout + api libs.androidx.recyclerview + api libs.androidx.window + api libs.androidx.window.java + api libs.androidx.preference - api 'com.google.guava:guava:33.3.1-android' + api libs.guava modules { module("com.google.guava:listenablefuture") { replacedBy("com.google.guava:guava", "listenablefuture is part of guava") } } - api 'com.github.bumptech.glide:glide:4.16.0' + api libs.glide api project(':lib') - api compatibility("recyclerViewSelection") + api libs.androidx.recyclerview.selection - implementation "com.google.errorprone:error_prone_annotations:${errorproneVersion}" + implementation libs.errorprone.annotations - androidTestImplementation "androidx.test:core:${project.rootProject.ext.testRunnerVersion}" - androidTestImplementation "androidx.test:runner:${project.rootProject.ext.testRunnerVersion}" - androidTestImplementation "androidx.test:rules:${project.rootProject.ext.testRunnerVersion}" - androidTestImplementation "androidx.test.espresso:espresso-core:${project.rootProject.ext.espressoVersion}" - androidTestImplementation "androidx.test.espresso:espresso-contrib:${project.rootProject.ext.espressoVersion}" + androidTestImplementation libs.androidx.test.core + androidTestImplementation libs.androidx.test.runner + androidTestImplementation libs.androidx.test.rules + androidTestImplementation libs.androidx.espresso.core + androidTestImplementation libs.androidx.espresso.contrib - testImplementation "androidx.test:core:${project.rootProject.ext.testRunnerVersion}" - testImplementation "androidx.test:runner:${project.rootProject.ext.testRunnerVersion}" - testImplementation "junit:junit:4.13.2" - testImplementation "com.google.truth:truth:${project.rootProject.ext.truthVersion}" - testImplementation "org.mockito:mockito-core:${project.rootProject.ext.mockitoCoreVersion}" - testImplementation "org.robolectric:robolectric:${project.rootProject.ext.robolectricVersion}" + testImplementation libs.androidx.test.core + testImplementation libs.androidx.test.runner + testImplementation libs.junit + testImplementation libs.truth + testImplementation libs.mockito.core + testImplementation libs.robolectric } def srcDirs = [ @@ -71,6 +70,7 @@ def srcDirs = [ 'dialog', 'divider', 'draggable', + 'dockedtoolbar', 'elevation', 'imageview', 'fab', @@ -103,6 +103,7 @@ def srcDirs = [ ] android { + namespace "io.material.catalog" defaultConfig { manifestPlaceholders = [ application_name : 'CatalogApplication', diff --git a/catalog/java/io/material/catalog/AndroidManifest.xml b/catalog/java/io/material/catalog/AndroidManifest.xml index 5eb4ce713cb..e59c1e2eaa0 100644 --- a/catalog/java/io/material/catalog/AndroidManifest.xml +++ b/catalog/java/io/material/catalog/AndroidManifest.xml @@ -110,6 +110,10 @@ android:name="io.material.catalog.search.SearchRecyclerDemoActivity" android:windowSoftInputMode="adjustNothing" android:exported="true" /> + diff --git a/catalog/java/io/material/catalog/adaptive/res/layout/cat_adaptive_nav_header.xml b/catalog/java/io/material/catalog/adaptive/res/layout/cat_adaptive_nav_header.xml index bca37c47b83..eea3a999165 100644 --- a/catalog/java/io/material/catalog/adaptive/res/layout/cat_adaptive_nav_header.xml +++ b/catalog/java/io/material/catalog/adaptive/res/layout/cat_adaptive_nav_header.xml @@ -24,18 +24,17 @@ android:clipToPadding="false" android:clipChildren="false"> - + android:contentDescription="@string/cat_adaptive_nav_button" + app:icon="@drawable/ic_drawer_menu_24px"/> - - - diff --git a/catalog/java/io/material/catalog/navigationrail/res/layout/cat_navigation_rail_submenus_fragment.xml b/catalog/java/io/material/catalog/navigationrail/res/layout/cat_navigation_rail_submenus_fragment.xml index 0d9a2cdaa2b..9f40bbc3047 100644 --- a/catalog/java/io/material/catalog/navigationrail/res/layout/cat_navigation_rail_submenus_fragment.xml +++ b/catalog/java/io/material/catalog/navigationrail/res/layout/cat_navigation_rail_submenus_fragment.xml @@ -26,6 +26,7 @@ app:labelVisibilityMode="labeled" android:fitsSystemWindows="false" app:scrollingEnabled="true" + app:submenuDividersEnabled="true" app:layout_constraintStart_toStartOf="parent" app:menu="@menu/navigation_rail_submenus_menu"/> { - int newThickness = Math.round(value * pixelsInDp); + int newThickness = (int) (value * pixelsInDp); if (linearIndicator.getTrackThickness() != newThickness) { linearIndicator.setTrackThickness(newThickness); } @@ -92,7 +92,7 @@ public void initDemoControls(@NonNull View view) { Slider cornerSlider = view.findViewById(R.id.cornerSlider); cornerSlider.addOnChangeListener( (slider, value, fromUser) -> { - int newCornerRadius = Math.round(value * pixelsInDp); + int newCornerRadius = (int) (value * pixelsInDp); if (linearIndicator.getTrackCornerRadius() != newCornerRadius) { linearIndicator.setTrackCornerRadius(newCornerRadius); } @@ -104,7 +104,7 @@ public void initDemoControls(@NonNull View view) { Slider gapSlider = view.findViewById(R.id.gapSlider); gapSlider.addOnChangeListener( (slider, value, fromUser) -> { - int newGapSize = Math.round(value * pixelsInDp); + int newGapSize = (int) (value * pixelsInDp); if (linearIndicator.getIndicatorTrackGapSize() != newGapSize) { linearIndicator.setIndicatorTrackGapSize(newGapSize); } @@ -125,7 +125,7 @@ public void initDemoControls(@NonNull View view) { Slider linearStopIndicatorSlider = view.findViewById(R.id.linearStopIndicatorSizeSlider); linearStopIndicatorSlider.addOnChangeListener( (slider, value, fromUser) -> { - int newStopIndicatorSize = Math.round(value * pixelsInDp); + int newStopIndicatorSize = (int) (value * pixelsInDp); if (linearIndicator.getTrackStopIndicatorSize() != newStopIndicatorSize) { linearIndicator.setTrackStopIndicatorSize(newStopIndicatorSize); } @@ -134,7 +134,7 @@ public void initDemoControls(@NonNull View view) { Slider circularSizeSlider = view.findViewById(R.id.circularSizeSlider); circularSizeSlider.addOnChangeListener( (slider, value, fromUser) -> { - int newCornerRadius = Math.round(value * pixelsInDp); + int newCornerRadius = (int) (value * pixelsInDp); if (circularIndicator.getIndicatorSize() != newCornerRadius) { circularIndicator.setIndicatorSize(newCornerRadius); } diff --git a/catalog/java/io/material/catalog/progressindicator/ProgressIndicatorStandaloneDemoFragment.java b/catalog/java/io/material/catalog/progressindicator/ProgressIndicatorStandaloneDemoFragment.java index 08e05926670..27c586aea5c 100644 --- a/catalog/java/io/material/catalog/progressindicator/ProgressIndicatorStandaloneDemoFragment.java +++ b/catalog/java/io/material/catalog/progressindicator/ProgressIndicatorStandaloneDemoFragment.java @@ -61,6 +61,6 @@ public int getProgressIndicatorContentLayout() { @StyleRes protected int getSpecStyleResId() { - return R.style.Widget_Material3_CircularProgressIndicator_ExtraSmall; + return com.google.android.material.R.style.Widget_Material3_CircularProgressIndicator_ExtraSmall; } } diff --git a/catalog/java/io/material/catalog/search/SearchBarWithAppBarIconsDemoActivity.java b/catalog/java/io/material/catalog/search/SearchBarWithAppBarIconsDemoActivity.java new file mode 100644 index 00000000000..dea547cf1eb --- /dev/null +++ b/catalog/java/io/material/catalog/search/SearchBarWithAppBarIconsDemoActivity.java @@ -0,0 +1,75 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.material.catalog.search; + +import io.material.catalog.R; + +import static io.material.catalog.search.SearchDemoUtils.showSnackbar; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.android.material.materialswitch.MaterialSwitch; +import com.google.android.material.search.SearchBar; +import com.google.android.material.search.SearchView; +import io.material.catalog.feature.DemoActivity; + +/** An activity that displays a SearchBar in an AppBar with outside icons demo. */ +public class SearchBarWithAppBarIconsDemoActivity extends DemoActivity { + + @Nullable + @Override + public View onCreateDemoView( + @NonNull LayoutInflater layoutInflater, + @Nullable ViewGroup viewGroup, + @Nullable Bundle bundle) { + View view = layoutInflater.inflate(R.layout.cat_search_appbar_icons_fragment, viewGroup, false); + + SearchBar searchBar = view.findViewById(R.id.cat_search_bar); + SearchView searchView = view.findViewById(R.id.cat_search_view); + LinearLayout suggestionContainer = view.findViewById(R.id.cat_search_view_suggestion_container); + + MaterialSwitch menuSwitch = view.findViewById(R.id.cat_search_bar_menu_switch); + menuSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (isChecked) { + searchBar.inflateMenu(R.menu.cat_searchview_menu); + searchBar.setOnMenuItemClickListener( + menuItem -> { + showSnackbar(SearchBarWithAppBarIconsDemoActivity.this, menuItem); + return true; + }); + } else { + searchBar.getMenu().clear(); + } + }); + searchView.setupWithSearchBar(searchBar); + SearchDemoUtils.setUpSearchView(this, searchBar, searchView); + SearchDemoUtils.setUpSuggestions(suggestionContainer, searchBar, searchView); + SearchDemoUtils.startOnLoadAnimation(searchBar, bundle); + + return view; + } + + @Override + protected boolean shouldShowDefaultDemoActionBar() { + return false; + } +} diff --git a/catalog/java/io/material/catalog/search/SearchFragment.java b/catalog/java/io/material/catalog/search/SearchFragment.java index bb99e9424e5..cb164cb05a9 100644 --- a/catalog/java/io/material/catalog/search/SearchFragment.java +++ b/catalog/java/io/material/catalog/search/SearchFragment.java @@ -69,6 +69,13 @@ public Intent createActivityIntent() { return new Intent(getContext(), SearchRecyclerDemoActivity.class); } }); + additionalDemos.add( + new Demo(R.string.cat_searchbar_appbar_with_icons_title) { + @Override + public Intent createActivityIntent() { + return new Intent(getContext(), SearchBarWithAppBarIconsDemoActivity.class); + } + }); return additionalDemos; } diff --git a/catalog/java/io/material/catalog/search/SearchRecyclerDemoActivity.java b/catalog/java/io/material/catalog/search/SearchRecyclerDemoActivity.java index 45114a1ba5e..06f6d2e0805 100644 --- a/catalog/java/io/material/catalog/search/SearchRecyclerDemoActivity.java +++ b/catalog/java/io/material/catalog/search/SearchRecyclerDemoActivity.java @@ -315,7 +315,7 @@ private interface OnItemSelectedStateChangedListener { void onItemSelectedStateChanged(Item item); } - /** The Dagger module for {@link SearchBarRecyclerDemoActivity} dependencies. */ + /** The Dagger module for {@link SearchRecyclerDemoActivity} dependencies. */ @dagger.Module public abstract static class Module { diff --git a/catalog/java/io/material/catalog/search/res/layout/cat_search_appbar_icons_fragment.xml b/catalog/java/io/material/catalog/search/res/layout/cat_search_appbar_icons_fragment.xml new file mode 100644 index 00000000000..b3c9114d275 --- /dev/null +++ b/catalog/java/io/material/catalog/search/res/layout/cat_search_appbar_icons_fragment.xml @@ -0,0 +1,134 @@ + + + + + + + +