Skip to content

Commit 249e6f5

Browse files
dsn5ftwcshi
authored andcommitted
Implement new MaterialToolbar class that provides support for Dark Theme elevation overlays, if not using AppBarLayout
PiperOrigin-RevId: 243054730
1 parent 574157e commit 249e6f5

12 files changed

Lines changed: 479 additions & 6 deletions

File tree

catalog/java/io/material/catalog/topappbar/TopAppBarFragment.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.material.catalog.feature.DemoLandingFragment;
3030
import io.material.catalog.feature.FeatureDemo;
3131
import java.util.ArrayList;
32+
import java.util.Arrays;
3233
import java.util.List;
3334

3435
/** A landing fragment that links to Top App Bar demos for the Catalog app. */
@@ -78,27 +79,34 @@ public Fragment createFragment() {
7879
return new TopAppBarCollapsingDemoFragment();
7980
}
8081
});
82+
additionalDemos.add(getToolbarDemo());
8183
additionalDemos.addAll(getActionBarDemos());
8284
return additionalDemos;
8385
}
8486

85-
public List<Demo> getActionBarDemos() {
86-
List<Demo> demos = new ArrayList<>();
87-
demos.add(
87+
protected Demo getToolbarDemo() {
88+
return new Demo(R.string.cat_topappbar_toolbar_title) {
89+
@Override
90+
public Fragment createFragment() {
91+
return new TopAppBarToolbarDemoFragment();
92+
}
93+
};
94+
}
95+
96+
protected List<Demo> getActionBarDemos() {
97+
return Arrays.asList(
8898
new Demo(R.string.cat_topappbar_action_bar_title) {
8999
@Override
90100
public Intent createActivityIntent() {
91101
return new Intent(getContext(), TopAppBarActionBarDemoActivity.class);
92102
}
93-
});
94-
demos.add(
103+
},
95104
new Demo(R.string.cat_topappbar_dark_action_bar_title) {
96105
@Override
97106
public Intent createActivityIntent() {
98107
return new Intent(getContext(), TopAppBarDarkActionBarDemoActivity.class);
99108
}
100109
});
101-
return demos;
102110
}
103111

104112
/** The Dagger module for {@link TopAppBarFragment} dependencies. */
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
17+
package io.material.catalog.topappbar;
18+
19+
import io.material.catalog.R;
20+
21+
import android.os.Bundle;
22+
import androidx.annotation.LayoutRes;
23+
import androidx.annotation.Nullable;
24+
import com.google.android.material.appbar.MaterialToolbar;
25+
import com.google.android.material.snackbar.Snackbar;
26+
import android.view.LayoutInflater;
27+
import android.view.View;
28+
import android.view.ViewGroup;
29+
import io.material.catalog.feature.DemoFragment;
30+
import io.material.catalog.feature.DemoUtils;
31+
import java.util.List;
32+
33+
/** A fragment that displays a Toolbar Top App Bar demo for the Catalog app. */
34+
public class TopAppBarToolbarDemoFragment extends DemoFragment {
35+
36+
@Override
37+
public View onCreateDemoView(
38+
LayoutInflater layoutInflater, @Nullable ViewGroup viewGroup, @Nullable Bundle bundle) {
39+
View view =
40+
layoutInflater.inflate(getToolbarLayoutResId(), viewGroup, /* attachToRoot= */ false);
41+
42+
List<MaterialToolbar> toolbars = DemoUtils.findViewsWithType(view, MaterialToolbar.class);
43+
for (MaterialToolbar toolbar : toolbars) {
44+
initToolbar(view, toolbar);
45+
}
46+
47+
return view;
48+
}
49+
50+
@LayoutRes
51+
protected int getToolbarLayoutResId() {
52+
return R.layout.cat_topappbar_toolbar_fragment;
53+
}
54+
55+
private void initToolbar(View view, MaterialToolbar toolbar) {
56+
toolbar.setNavigationIcon(R.drawable.ic_close_vd_theme_24px);
57+
toolbar.setNavigationOnClickListener(
58+
v -> showSnackbar(view, toolbar.getSubtitle() + " " + toolbar.getTitle()));
59+
toolbar.inflateMenu(R.menu.cat_topappbar_menu);
60+
toolbar.setOnMenuItemClickListener(
61+
menuItem -> {
62+
showSnackbar(view, menuItem.getTitle());
63+
return true;
64+
});
65+
}
66+
67+
private void showSnackbar(View view, CharSequence text) {
68+
Snackbar.make(view, text, Snackbar.LENGTH_SHORT).show();
69+
}
70+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2019 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<ScrollView
18+
xmlns:android="http://schemas.android.com/apk/res/android"
19+
xmlns:app="http://schemas.android.com/apk/res-auto"
20+
android:layout_width="match_parent"
21+
android:layout_height="match_parent">
22+
23+
<LinearLayout
24+
android:layout_width="match_parent"
25+
android:layout_height="wrap_content"
26+
android:paddingTop="32dp"
27+
android:paddingBottom="32dp"
28+
android:paddingLeft="16dp"
29+
android:paddingRight="16dp"
30+
android:clipToPadding="false"
31+
android:orientation="vertical">
32+
33+
<com.google.android.material.appbar.MaterialToolbar
34+
android:layout_width="match_parent"
35+
android:layout_height="wrap_content"
36+
app:subtitle="Default"
37+
app:title="Toolbar"/>
38+
39+
<com.google.android.material.appbar.MaterialToolbar
40+
style="@style/Widget.MaterialComponents.Toolbar.Primary"
41+
android:layout_width="match_parent"
42+
android:layout_height="wrap_content"
43+
android:layout_marginTop="32dp"
44+
app:subtitle="Primary"
45+
app:title="Toolbar"/>
46+
47+
<com.google.android.material.appbar.MaterialToolbar
48+
style="@style/Widget.MaterialComponents.Toolbar.Surface"
49+
android:layout_width="match_parent"
50+
android:layout_height="wrap_content"
51+
android:layout_marginTop="32dp"
52+
app:subtitle="Surface"
53+
app:title="Toolbar"/>
54+
55+
<com.google.android.material.appbar.MaterialToolbar
56+
style="@style/Widget.MaterialComponents.Toolbar.Surface"
57+
android:layout_width="match_parent"
58+
android:layout_height="wrap_content"
59+
android:layout_marginTop="32dp"
60+
android:elevation="@dimen/design_appbar_elevation"
61+
app:subtitle="Surface Elevated"
62+
app:title="Toolbar"/>
63+
</LinearLayout>
64+
</ScrollView>

catalog/java/io/material/catalog/topappbar/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<string name="cat_topappbar_scrolling_title">Scrolling Demo</string>
2222
<string name="cat_topappbar_scrolling_transparent_title">Scrolling Demo (transparent status bar)</string>
2323
<string name="cat_topappbar_collapsing_title">Collapsing Demo</string>
24+
<string name="cat_topappbar_toolbar_title" translatable="false">Toolbar Demo</string>
2425
<string name="cat_topappbar_action_bar_title">Action Bar Demo</string>
2526
<string name="cat_topappbar_dark_action_bar_title">Dark Action Bar Demo</string>
2627

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (C) 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 com.google.android.material.appbar;
18+
19+
import com.google.android.material.R;
20+
21+
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
22+
23+
import android.content.Context;
24+
import android.content.res.ColorStateList;
25+
import android.graphics.Color;
26+
import android.graphics.drawable.ColorDrawable;
27+
import android.graphics.drawable.Drawable;
28+
import android.os.Build.VERSION_CODES;
29+
import androidx.annotation.RequiresApi;
30+
import com.google.android.material.shape.MaterialShapeDrawable;
31+
import androidx.core.view.ViewCompat;
32+
import androidx.appcompat.widget.Toolbar;
33+
import android.util.AttributeSet;
34+
35+
/**
36+
* {@code MaterialToolbar} is a {@link Toolbar} that implements certain Material features, such as
37+
* elevation overlays for Dark Themes.
38+
*
39+
* <p>Regarding the Dark Theme elevation overlays, it's important to note that the Material {@link
40+
* AppBarLayout} component also provides elevation overlay support, and operates under the
41+
* assumption that the child {@code Toolbar} does not have a background. While a {@code
42+
* MaterialToolbar} with a transparent background can be used within an {@link AppBarLayout}, in
43+
* terms of elevation overlays its main value comes into play with the standalone {@code Toolbar}
44+
* case, when using the {@code Widget.MaterialComponents.Toolbar.Surface} style with elevation.
45+
*
46+
* <p>To get started with the {@code MaterialToolbar} component, use {@code
47+
* com.google.android.material.appbar.MaterialToolbar} in your layout XML instead of {@code
48+
* androidx.appcompat.widget.Toolbar} or {@code Toolbar}. E.g.,:
49+
*
50+
* <pre>
51+
* &lt;com.google.android.material.appbar.MaterialToolbar
52+
* android:layout_width=&quot;match_parent&quot;
53+
* android:layout_height=&quot;wrap_content&quot;/&gt;
54+
* </pre>
55+
*/
56+
public class MaterialToolbar extends Toolbar {
57+
58+
private static final int DEF_STYLE_RES = R.style.Widget_MaterialComponents_Toolbar;
59+
60+
public MaterialToolbar(Context context) {
61+
this(context, null);
62+
}
63+
64+
public MaterialToolbar(Context context, AttributeSet attrs) {
65+
this(context, attrs, R.attr.toolbarStyle);
66+
}
67+
68+
public MaterialToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
69+
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
70+
// Ensure we are using the correctly themed context rather than the context that was passed in.
71+
context = getContext();
72+
73+
initBackground(context);
74+
}
75+
76+
@RequiresApi(VERSION_CODES.LOLLIPOP)
77+
@Override
78+
public void setElevation(float elevation) {
79+
super.setElevation(elevation);
80+
if (getBackground() instanceof MaterialShapeDrawable) {
81+
((MaterialShapeDrawable) getBackground()).setElevation(elevation);
82+
}
83+
}
84+
85+
private void initBackground(Context context) {
86+
Drawable background = getBackground();
87+
if (background != null && !(background instanceof ColorDrawable)) {
88+
return;
89+
}
90+
MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
91+
int backgroundColor =
92+
background != null ? ((ColorDrawable) background).getColor() : Color.TRANSPARENT;
93+
materialShapeDrawable.setFillColor(ColorStateList.valueOf(backgroundColor));
94+
materialShapeDrawable.initializeElevationOverlay(context);
95+
materialShapeDrawable.setElevation(ViewCompat.getElevation(this));
96+
ViewCompat.setBackground(this, materialShapeDrawable);
97+
}
98+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 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+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
18+
xmlns:tools="http://schemas.android.com/tools"
19+
package="com.google.android.material.appbar">
20+
21+
<uses-sdk
22+
tools:overrideLibrary="androidx.test.core"/>
23+
24+
<application/>
25+
</manifest>

0 commit comments

Comments
 (0)