Skip to content

Commit f1aff91

Browse files
dsn5ftdrchen
authored andcommitted
[Catalog] Add All Components demo to display and test cross-cutting library features
PiperOrigin-RevId: 878546901
1 parent 27c26f8 commit f1aff91

16 files changed

Lines changed: 878 additions & 7 deletions

catalog/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dependencies {
7070

7171
def srcDirs = [
7272
'adaptive',
73+
'allcomponents',
7374
'application',
7475
'application/attrs',
7576
'application/legacymultidex',
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright 2026 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 io.material.catalog.allcomponents;
18+
19+
import io.material.catalog.R;
20+
21+
import android.annotation.SuppressLint;
22+
import android.os.Bundle;
23+
import androidx.appcompat.widget.PopupMenu;
24+
import androidx.appcompat.widget.Toolbar;
25+
import android.view.LayoutInflater;
26+
import android.view.MenuInflater;
27+
import android.view.View;
28+
import android.view.ViewGroup;
29+
import androidx.annotation.NonNull;
30+
import androidx.annotation.Nullable;
31+
import androidx.core.util.Pair;
32+
import androidx.drawerlayout.widget.DrawerLayout;
33+
import com.google.android.material.bottomsheet.BottomSheetDialog;
34+
import com.google.android.material.button.MaterialButton;
35+
import com.google.android.material.datepicker.MaterialDatePicker;
36+
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
37+
import com.google.android.material.navigation.NavigationView;
38+
import com.google.android.material.sidesheet.SideSheetDialog;
39+
import com.google.android.material.snackbar.Snackbar;
40+
import com.google.android.material.timepicker.MaterialTimePicker;
41+
import com.google.android.material.timepicker.TimeFormat;
42+
import io.material.catalog.feature.DemoFragment;
43+
44+
/** A demo fragment which shows all components. */
45+
public class AllComponentsDemoFragment extends DemoFragment {
46+
47+
@Nullable
48+
@Override
49+
public View onCreateDemoView(
50+
@NonNull LayoutInflater layoutInflater,
51+
@Nullable ViewGroup viewGroup,
52+
@Nullable Bundle bundle) {
53+
View view = layoutInflater.inflate(R.layout.cat_all_components_fragment, viewGroup, false);
54+
55+
((Toolbar) view.findViewById(R.id.bottom_app_bar))
56+
.setNavigationOnClickListener(
57+
v -> ((DrawerLayout) view.findViewById(R.id.drawer_layout)).open());
58+
59+
view.findViewById(R.id.bottom_navigation).setOnApplyWindowInsetsListener(null);
60+
61+
setUpSplitButton(view);
62+
setUpDialogs(view);
63+
setUpSheets(view);
64+
65+
return view;
66+
}
67+
68+
private void setUpDialogs(View view) {
69+
view.findViewById(R.id.alert_dialog_button)
70+
.setOnClickListener(
71+
v ->
72+
new MaterialAlertDialogBuilder(requireContext())
73+
.setTitle("Alert")
74+
.setMessage("Message")
75+
.setPositiveButton(android.R.string.ok, null)
76+
.setNegativeButton(android.R.string.cancel, null)
77+
.show());
78+
79+
view.findViewById(R.id.date_picker_button)
80+
.setOnClickListener(
81+
v -> {
82+
MaterialDatePicker<Long> datePicker = MaterialDatePicker.Builder.datePicker().build();
83+
datePicker.addOnPositiveButtonClickListener(
84+
selection -> showSnackbar("Date Result: " + datePicker.getHeaderText()));
85+
datePicker.show(getChildFragmentManager(), "DATE_PICKER");
86+
});
87+
88+
view.findViewById(R.id.date_range_picker_button)
89+
.setOnClickListener(
90+
v -> {
91+
MaterialDatePicker<Pair<Long, Long>> dateRangePicker =
92+
MaterialDatePicker.Builder.dateRangePicker().build();
93+
dateRangePicker.addOnPositiveButtonClickListener(
94+
selection ->
95+
showSnackbar("Date Range Result: " + dateRangePicker.getHeaderText()));
96+
dateRangePicker.show(getChildFragmentManager(), "DATE_RANGE_PICKER");
97+
});
98+
99+
view.findViewById(R.id.time_picker_button)
100+
.setOnClickListener(
101+
v -> {
102+
MaterialTimePicker timePicker =
103+
new MaterialTimePicker.Builder()
104+
.setTimeFormat(TimeFormat.CLOCK_12H)
105+
.setHour(8)
106+
.setMinute(12)
107+
.build();
108+
timePicker.show(getChildFragmentManager(), "TIME_PICKER");
109+
});
110+
}
111+
112+
private void setUpSheets(View view) {
113+
view.findViewById(R.id.bottom_sheet_button).setOnClickListener(v -> showBottomSheet());
114+
view.findViewById(R.id.modal_side_sheet_button).setOnClickListener(v -> showSideSheet());
115+
}
116+
117+
private void showBottomSheet() {
118+
NavigationView navigationView = new NavigationView(requireContext());
119+
navigationView.inflateMenu(R.menu.cat_all_components_menu);
120+
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(requireContext());
121+
bottomSheetDialog.setContentView(navigationView);
122+
bottomSheetDialog.show();
123+
}
124+
125+
private void showSideSheet() {
126+
SideSheetDialog sideSheetDialog = new SideSheetDialog(requireContext());
127+
sideSheetDialog.setContentView(R.layout.cat_all_components_fragment);
128+
sideSheetDialog.show();
129+
}
130+
131+
private void showSnackbar(CharSequence text) {
132+
Snackbar.make(requireView(), text, Snackbar.LENGTH_SHORT).setAction("Dismiss", null).show();
133+
}
134+
135+
@SuppressLint("WrongViewCast")
136+
private void setUpSplitButton(View view) {
137+
MaterialButton button = view.findViewById(R.id.split_button_expand);
138+
button.addOnCheckedChangeListener(
139+
(buttonView, isChecked) -> {
140+
if (isChecked) {
141+
PopupMenu popup = new PopupMenu(requireContext(), button);
142+
MenuInflater menuInflater = popup.getMenuInflater();
143+
menuInflater.inflate(R.menu.cat_all_components_menu, popup.getMenu());
144+
popup.setOnDismissListener(popupMenu -> button.setChecked(false));
145+
popup.show();
146+
}
147+
});
148+
}
149+
150+
@Override
151+
public int getDemoTitleResId() {
152+
return R.string.cat_all_components_title;
153+
}
154+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2026 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+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.material.catalog.allcomponents;
18+
19+
import io.material.catalog.R;
20+
21+
import androidx.fragment.app.Fragment;
22+
import androidx.annotation.NonNull;
23+
import dagger.Provides;
24+
import dagger.android.ContributesAndroidInjector;
25+
import dagger.multibindings.IntoSet;
26+
import io.material.catalog.application.scope.ActivityScope;
27+
import io.material.catalog.application.scope.FragmentScope;
28+
import io.material.catalog.feature.Demo;
29+
import io.material.catalog.feature.DemoLandingFragment;
30+
import io.material.catalog.feature.FeatureDemo;
31+
32+
/** A landing fragment that links to All Components demos for the Catalog app. */
33+
public class AllComponentsFragment extends DemoLandingFragment {
34+
35+
@Override
36+
public int getTitleResId() {
37+
return R.string.cat_all_components_title;
38+
}
39+
40+
@Override
41+
public int getDescriptionResId() {
42+
return R.string.cat_all_components_description;
43+
}
44+
45+
@Override
46+
@NonNull
47+
public Demo getMainDemo() {
48+
return new Demo() {
49+
@Override
50+
public Fragment createFragment() {
51+
return new AllComponentsDemoFragment();
52+
}
53+
};
54+
}
55+
56+
/** The Dagger module for {@link AllComponentsFragment} dependencies. */
57+
@dagger.Module
58+
public abstract static class Module {
59+
60+
@FragmentScope
61+
@ContributesAndroidInjector
62+
abstract AllComponentsFragment contributeInjector();
63+
64+
@IntoSet
65+
@Provides
66+
@ActivityScope
67+
static FeatureDemo provideFeatureDemo() {
68+
return new FeatureDemo(
69+
R.string.cat_all_components_title, R.drawable.ic_placeholder) {
70+
@Override
71+
public Fragment createFragment() {
72+
return new AllComponentsFragment();
73+
}
74+
75+
@Override
76+
public boolean isPriority() {
77+
return true;
78+
}
79+
};
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)