Skip to content

Commit cd24d3f

Browse files
dsn5ftldjcmu
authored andcommitted
Add Dark Theme toggle to Catalog
PiperOrigin-RevId: 246397450
1 parent 213f93e commit cd24d3f

File tree

10 files changed

+208
-45
lines changed

10 files changed

+208
-45
lines changed

catalog/java/io/material/catalog/application/theme/res/values-night/styles.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@
1818

1919
<style name="Widget.Catalog.Toolbar" parent="Widget.MaterialComponents.Toolbar"/>
2020

21+
<style name="ThemeOverlay.Catalog.AppBarLayout" parent="">
22+
<item name="android:textColorPrimary">?attr/colorOnSurface</item>
23+
<item name="colorControlNormal">?attr/colorOnSurface</item>
24+
</style>
25+
2126
</resources>

catalog/java/io/material/catalog/application/theme/res/values/colors.xml renamed to catalog/java/io/material/catalog/application/theme/res/values/ids.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@
1515
limitations under the License.
1616
-->
1717
<resources>
18-
<color name="cat_toc_title_text_color">@color/design_default_color_on_primary</color>
18+
19+
<item name="cat_toc_dark_theme_toggle" type="id"/>
20+
1921
</resources>

catalog/java/io/material/catalog/application/theme/res/values/styles.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,17 @@
2323
<item name="navigationIcon">@drawable/ic_close_vd_theme_24px</item>
2424
</style>
2525

26+
<style name="Widget.Catalog.ImageButton.DarkThemeToggle" parent="Widget.AppCompat.ImageButton">
27+
<item name="android:id">@id/cat_toc_dark_theme_toggle</item>
28+
<item name="android:layout_width">@dimen/mtrl_min_touch_target_size</item>
29+
<item name="android:layout_height">@dimen/mtrl_min_touch_target_size</item>
30+
<item name="android:layout_gravity">center_vertical|end</item>
31+
<item name="android:background">?attr/actionBarItemBackground</item>
32+
</style>
33+
34+
<style name="ThemeOverlay.Catalog.AppBarLayout" parent="">
35+
<item name="android:textColorPrimary">?attr/colorOnPrimary</item>
36+
<item name="colorControlNormal">?attr/colorOnPrimary</item>
37+
</style>
38+
2639
</resources>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!--
2+
Copyright 2019 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+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
17+
android:width="24dp"
18+
android:height="24dp"
19+
android:viewportHeight="24.0"
20+
android:viewportWidth="24.0">
21+
<path
22+
android:fillColor="?attr/colorControlNormal"
23+
android:pathData="M20,8.69L20,4h-4.69L12,0.69 8.69,4L4,4v4.69L0.69,12 4,15.31L4,20h4.69L12,23.31 15.31,20L20,20v-4.69L23.31,12 20,8.69zM12,18c-3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6 6,2.69 6,6 -2.69,6 -6,6zM12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4z"/>
24+
</vector>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!--
2+
Copyright 2019 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+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
17+
android:width="24dp"
18+
android:height="24dp"
19+
android:viewportHeight="24.0"
20+
android:viewportWidth="24.0">
21+
<path
22+
android:fillColor="?attr/colorControlNormal"
23+
android:pathData="M20,8.69V4h-4.69L12,0.69 8.69,4H4v4.69L0.69,12 4,15.31V20h4.69L12,23.31 15.31,20H20v-4.69L23.31,12 20,8.69zM12,18c-0.89,0 -1.74,-0.2 -2.5,-0.55C11.56,16.5 13,14.42 13,12s-1.44,-4.5 -3.5,-5.45C10.26,6.2 11.11,6 12,6c3.31,0 6,2.69 6,6s-2.69,6 -6,6z"/>
24+
</vector>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2019 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.tableofcontents;
18+
19+
import android.content.Context;
20+
import android.content.SharedPreferences;
21+
22+
class DarkThemePreferencesRepository {
23+
24+
private static final String PREFERENCES_NAME = "dark_theme_preferences";
25+
private static final String KEY_DARK_THEME_ENABLED = "dark_theme_enabled";
26+
27+
private final Context context;
28+
29+
DarkThemePreferencesRepository(Context context) {
30+
this.context = context;
31+
}
32+
33+
boolean isDarkThemeEnabled() {
34+
return getSharedPreferences().getBoolean(KEY_DARK_THEME_ENABLED, false);
35+
}
36+
37+
void saveDarkThemeEnabled(boolean enabled) {
38+
getSharedPreferences().edit().putBoolean(KEY_DARK_THEME_ENABLED, enabled).commit();
39+
}
40+
41+
private SharedPreferences getSharedPreferences() {
42+
return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
43+
}
44+
}

catalog/java/io/material/catalog/tableofcontents/TocFragment.java

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828
import androidx.core.content.ContextCompat;
2929
import androidx.core.math.MathUtils;
3030
import androidx.appcompat.app.AppCompatActivity;
31+
import androidx.appcompat.app.AppCompatDelegate;
3132
import androidx.recyclerview.widget.GridLayoutManager;
3233
import androidx.recyclerview.widget.RecyclerView;
3334
import androidx.appcompat.widget.Toolbar;
3435
import android.util.DisplayMetrics;
3536
import android.view.LayoutInflater;
3637
import android.view.View;
3738
import android.view.ViewGroup;
39+
import android.widget.ImageButton;
3840
import dagger.android.support.DaggerFragment;
3941
import io.material.catalog.feature.FeatureDemo;
4042
import io.material.catalog.feature.FeatureDemoUtils;
@@ -54,9 +56,30 @@ public class TocFragment extends DaggerFragment {
5456
@Inject Set<FeatureDemo> featureDemos;
5557
@Inject TocResourceProvider tocResourceProvider;
5658

59+
private DarkThemePreferencesRepository darkThemePreferencesRepository;
5760
private AppBarLayout appBarLayout;
5861
private View gridTopDivider;
5962
private RecyclerView recyclerView;
63+
private ImageButton darkThemeToggle;
64+
65+
@Override
66+
public void onCreate(@Nullable Bundle bundle) {
67+
super.onCreate(bundle);
68+
69+
darkThemePreferencesRepository = new DarkThemePreferencesRepository(getContext());
70+
71+
String defaultDemo = FeatureDemoUtils.getDefaultDemo(getContext());
72+
if (!defaultDemo.isEmpty() && bundle == null) {
73+
for (FeatureDemo demo : featureDemos) {
74+
Fragment fragment = demo.createFragment();
75+
String key = fragment.getClass().getName();
76+
if (key.equals(defaultDemo)) {
77+
FeatureDemoUtils.startFragment(getActivity(), fragment, "fragment_content");
78+
return;
79+
}
80+
}
81+
}
82+
}
6083

6184
@Nullable
6285
@Override
@@ -76,6 +99,7 @@ public View onCreateView(
7699
appBarLayout = view.findViewById(R.id.cat_toc_app_bar_layout);
77100
gridTopDivider = view.findViewById(R.id.cat_toc_grid_top_divider);
78101
recyclerView = view.findViewById(R.id.cat_toc_grid);
102+
darkThemeToggle = view.findViewById(R.id.cat_toc_dark_theme_toggle);
79103

80104
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
81105
addGridTopDividerVisibilityListener();
@@ -105,6 +129,8 @@ public View onCreateView(
105129
TocAdapter tocAdapter = new TocAdapter(getActivity(), featureList);
106130
recyclerView.setAdapter(tocAdapter);
107131

132+
initDarkThemeToggle();
133+
108134
return view;
109135
}
110136

@@ -115,22 +141,6 @@ public void onDestroyView() {
115141
((AppCompatActivity) getActivity()).setSupportActionBar(null);
116142
}
117143

118-
@Override
119-
public void onCreate(@Nullable Bundle bundle) {
120-
super.onCreate(bundle);
121-
String defaultDemo = FeatureDemoUtils.getDefaultDemo(getContext());
122-
if (!defaultDemo.isEmpty() && bundle == null) {
123-
for (FeatureDemo demo : featureDemos) {
124-
Fragment fragment = demo.createFragment();
125-
String key = fragment.getClass().getName();
126-
if (key.equals(defaultDemo)) {
127-
FeatureDemoUtils.startFragment(getActivity(), fragment, "fragment_content");
128-
return;
129-
}
130-
}
131-
}
132-
}
133-
134144
private void addGridTopDividerVisibilityListener() {
135145
appBarLayout.addOnOffsetChangedListener(
136146
new OnOffsetChangedListener() {
@@ -154,4 +164,28 @@ private int calculateGridSpanCount() {
154164
int gridSpanCount = displayWidth / itemSize;
155165
return MathUtils.clamp(gridSpanCount, GRID_SPAN_COUNT_MIN, GRID_SPAN_COUNT_MAX);
156166
}
167+
168+
private void initDarkThemeToggle() {
169+
boolean darkThemeEnabled = darkThemePreferencesRepository.isDarkThemeEnabled();
170+
darkThemeToggle.setImageResource(
171+
darkThemeEnabled
172+
? R.drawable.ic_night_on_vd_theme_24px
173+
: R.drawable.ic_night_off_vd_theme_24px);
174+
ensureDefaultNightMode(
175+
darkThemeEnabled ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
176+
darkThemeToggle.setOnClickListener(v -> toggleNightMode());
177+
}
178+
179+
private void ensureDefaultNightMode(int mode) {
180+
if (AppCompatDelegate.getDefaultNightMode() != mode) {
181+
AppCompatDelegate.setDefaultNightMode(mode);
182+
}
183+
}
184+
185+
private void toggleNightMode() {
186+
boolean newDarkThemeEnabled = !darkThemePreferencesRepository.isDarkThemeEnabled();
187+
darkThemePreferencesRepository.saveDarkThemeEnabled(newDarkThemeEnabled);
188+
AppCompatDelegate.setDefaultNightMode(
189+
newDarkThemeEnabled ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
190+
}
157191
}

catalog/java/io/material/catalog/application/theme/res/values-night/colors.xml renamed to catalog/java/io/material/catalog/tableofcontents/res/drawable/ic_dark_theme_toggle.xml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17-
<resources>
18-
<color name="cat_toc_title_text_color">@color/design_dark_default_color_on_surface</color>
19-
</resources>
17+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<item
20+
android:drawable="@drawable/ic_night_on_vd_theme_24px"
21+
android:state_selected="true"/>
22+
23+
<item
24+
android:drawable="@drawable/ic_night_off_vd_theme_24px"/>
25+
26+
</selector>

catalog/java/io/material/catalog/tableofcontents/res/layout/cat_toc_fragment.xml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,27 @@
2626
<com.google.android.material.appbar.AppBarLayout
2727
android:id="@+id/cat_toc_app_bar_layout"
2828
android:layout_width="match_parent"
29-
android:layout_height="@dimen/cat_toc_tall_toolbar_height">
29+
android:layout_height="@dimen/cat_toc_tall_toolbar_height"
30+
android:theme="@style/ThemeOverlay.Catalog.AppBarLayout">
3031

3132
<com.google.android.material.appbar.CollapsingToolbarLayout
3233
android:layout_width="match_parent"
3334
android:layout_height="match_parent"
3435
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
3536
app:titleEnabled="false">
3637

37-
<FrameLayout
38-
android:id="@+id/content"
39-
android:layout_width="wrap_content"
40-
android:layout_height="wrap_content"
41-
android:layout_gravity="center"
42-
app:layout_collapseMode="parallax"/>
43-
4438
<androidx.appcompat.widget.Toolbar
4539
android:id="@+id/toolbar"
4640
android:layout_width="match_parent"
4741
android:layout_height="wrap_content"
4842
app:layout_collapseMode="pin"/>
43+
44+
<FrameLayout
45+
android:id="@+id/content"
46+
android:layout_width="match_parent"
47+
android:layout_height="wrap_content"
48+
android:layout_gravity="center_vertical"
49+
app:layout_collapseMode="parallax"/>
4950
</com.google.android.material.appbar.CollapsingToolbarLayout>
5051
</com.google.android.material.appbar.AppBarLayout>
5152

catalog/java/io/material/catalog/tableofcontents/res/layout/cat_toc_header.xml

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,33 @@
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
17+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
1818
xmlns:app="http://schemas.android.com/apk/res-auto"
19-
android:layout_width="wrap_content"
19+
android:layout_width="match_parent"
2020
android:layout_height="wrap_content"
21-
android:gravity="center_vertical"
22-
android:orientation="horizontal">
23-
<ImageView
24-
android:layout_width="wrap_content"
25-
android:layout_height="wrap_content"
26-
android:layout_marginEnd="4dp"
27-
android:contentDescription="@null"
28-
android:importantForAccessibility="no"
29-
app:srcCompat="@drawable/ic_logo_components_48px"/>
30-
<TextView
21+
android:theme="@style/ThemeOverlay.Catalog.AppBarLayout">
22+
23+
<LinearLayout
3124
android:layout_width="wrap_content"
3225
android:layout_height="wrap_content"
33-
android:includeFontPadding="false"
34-
android:text="@string/cat_toc_title"
35-
android:textAppearance="?attr/textAppearanceHeadline6"
36-
android:textColor="@color/cat_toc_title_text_color"/>
37-
</LinearLayout>
26+
android:layout_gravity="center"
27+
android:gravity="center"
28+
android:orientation="horizontal">
29+
<ImageView
30+
android:layout_width="wrap_content"
31+
android:layout_height="wrap_content"
32+
android:layout_marginEnd="4dp"
33+
android:contentDescription="@null"
34+
android:importantForAccessibility="no"
35+
app:srcCompat="@drawable/ic_logo_components_48px"/>
36+
<TextView
37+
android:layout_width="wrap_content"
38+
android:layout_height="wrap_content"
39+
android:includeFontPadding="false"
40+
android:text="@string/cat_toc_title"
41+
android:textAppearance="?attr/textAppearanceHeadline6"/>
42+
</LinearLayout>
43+
44+
<ImageButton
45+
style="@style/Widget.Catalog.ImageButton.DarkThemeToggle"/>
46+
</FrameLayout>

0 commit comments

Comments
 (0)