Skip to content

Commit 1fd228b

Browse files
imhappidrchen
authored andcommitted
[DockedToolbar] Adding inset padding attributes
PiperOrigin-RevId: 726578762
1 parent 8c263bb commit 1fd228b

File tree

5 files changed

+139
-55
lines changed

5 files changed

+139
-55
lines changed

lib/java/com/google/android/material/dockedtoolbar/DockedToolbarLayout.java

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,21 @@
2323
import android.content.res.ColorStateList;
2424
import androidx.appcompat.widget.TintTypedArray;
2525
import android.util.AttributeSet;
26+
import android.view.Gravity;
2627
import android.view.View;
28+
import android.view.ViewGroup;
2729
import android.widget.FrameLayout;
2830
import androidx.annotation.AttrRes;
2931
import androidx.annotation.ColorInt;
3032
import androidx.annotation.NonNull;
3133
import androidx.annotation.Nullable;
3234
import androidx.annotation.StyleRes;
35+
import androidx.coordinatorlayout.widget.CoordinatorLayout;
36+
import androidx.core.graphics.Insets;
37+
import androidx.core.view.WindowInsetsCompat;
3338
import com.google.android.material.internal.ThemeEnforcement;
39+
import com.google.android.material.internal.ViewUtils;
40+
import com.google.android.material.internal.ViewUtils.RelativePadding;
3441
import com.google.android.material.shape.MaterialShapeDrawable;
3542
import com.google.android.material.shape.ShapeAppearanceModel;
3643

@@ -47,6 +54,8 @@ public class DockedToolbarLayout extends FrameLayout {
4754

4855
private static final String TAG = DockedToolbarLayout.class.getSimpleName();
4956
private static final int DEF_STYLE_RES = R.style.Widget_Material3_DockedToolbar;
57+
private Boolean paddingTopSystemWindowInsets;
58+
private Boolean paddingBottomSystemWindowInsets;
5059

5160
public DockedToolbarLayout(@NonNull Context context) {
5261
this(context, null);
@@ -88,8 +97,98 @@ public DockedToolbarLayout(
8897

8998
setBackground(materialShapeDrawable);
9099
}
91-
100+
101+
// Reading out if we are handling inset padding, so we can apply it to the content.
102+
if (attributes.hasValue(R.styleable.DockedToolbar_paddingTopSystemWindowInsets)) {
103+
paddingTopSystemWindowInsets =
104+
attributes.getBoolean(R.styleable.DockedToolbar_paddingTopSystemWindowInsets, true);
105+
}
106+
if (attributes.hasValue(R.styleable.DockedToolbar_paddingBottomSystemWindowInsets)) {
107+
paddingBottomSystemWindowInsets =
108+
attributes.getBoolean(R.styleable.DockedToolbar_paddingBottomSystemWindowInsets, true);
109+
}
110+
111+
ViewUtils.doOnApplyWindowInsets(
112+
this,
113+
new ViewUtils.OnApplyWindowInsetsListener() {
114+
@NonNull
115+
@Override
116+
public WindowInsetsCompat onApplyWindowInsets(
117+
View view,
118+
@NonNull WindowInsetsCompat insets,
119+
@NonNull RelativePadding initialPadding) {
120+
if (paddingTopSystemWindowInsets != null
121+
&& paddingBottomSystemWindowInsets != null
122+
&& !paddingTopSystemWindowInsets
123+
&& !paddingBottomSystemWindowInsets) {
124+
return insets;
125+
}
126+
127+
Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
128+
Insets cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout());
129+
int bottomInset = systemBarInsets.bottom + cutoutInsets.bottom;
130+
int topInset = systemBarInsets.top + cutoutInsets.top;
131+
int bottomPadding = 0;
132+
int topPadding = 0;
133+
134+
ViewGroup.LayoutParams lp = view.getLayoutParams();
135+
// If the inset flags are not explicitly set, and the toolbar is inside a
136+
// CoordinatorLayout or a FrameLayout, we can use the gravity
137+
// to ascertain what padding should be automatically added.
138+
if (hasGravity(lp, Gravity.TOP) && paddingTopSystemWindowInsets == null && getFitsSystemWindows()) {
139+
topPadding = topInset;
140+
}
141+
if (hasGravity(lp, Gravity.BOTTOM) && paddingBottomSystemWindowInsets == null && getFitsSystemWindows()) {
142+
bottomPadding = bottomInset;
143+
}
144+
145+
// If paddingTopSystemWindowInsets or paddingBottomSystemWindowInsets is explicitly
146+
// set, then insets should always be applied to the padding.
147+
if (paddingBottomSystemWindowInsets != null) {
148+
bottomPadding = paddingBottomSystemWindowInsets ? bottomInset : 0;
149+
}
150+
if (paddingTopSystemWindowInsets != null) {
151+
topPadding = paddingTopSystemWindowInsets ? topInset : 0;
152+
}
153+
initialPadding.top += topPadding;
154+
initialPadding.bottom += bottomPadding;
155+
initialPadding.applyToView(view);
156+
157+
return insets;
158+
}
159+
});
160+
92161
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
93162
attributes.recycle();
94163
}
164+
165+
private boolean hasGravity(ViewGroup.LayoutParams lp, int gravity) {
166+
if (lp instanceof CoordinatorLayout.LayoutParams) {
167+
return (((CoordinatorLayout.LayoutParams) lp).gravity & gravity) == gravity;
168+
} else if (lp instanceof FrameLayout.LayoutParams) {
169+
return (((FrameLayout.LayoutParams) lp).gravity & gravity) == gravity;
170+
}
171+
return false;
172+
}
173+
174+
@Override
175+
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
176+
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
177+
if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) {
178+
int childCount = getChildCount();
179+
int newHeight =
180+
Math.max(
181+
getMeasuredHeight(),
182+
getSuggestedMinimumHeight() + getPaddingTop() + getPaddingBottom());
183+
184+
for (int i = 0; i < childCount; i++) {
185+
measureChild(
186+
getChildAt(i),
187+
widthMeasureSpec,
188+
MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
189+
}
190+
191+
setMeasuredDimension(getMeasuredWidth(), newHeight);
192+
}
193+
}
95194
}

lib/java/com/google/android/material/dockedtoolbar/res/values/attrs.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,9 @@
2121
<declare-styleable name="DockedToolbar">
2222
<!-- Color of the docked toolbar container. -->
2323
<attr name="backgroundTint"/>
24+
<!-- Whether or not to add top padding to account for system insets. -->
25+
<attr name="paddingTopSystemWindowInsets"/>
26+
<!-- Whether or not to add bottom padding to account for system insets. -->
27+
<attr name="paddingBottomSystemWindowInsets"/>
2428
</declare-styleable>
2529
</resources>

lib/java/com/google/android/material/dockedtoolbar/res/values/styles.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<item name="shapeAppearance">@style/ShapeAppearance.M3.Comp.Toolbar.Docked.Container.Shape</item>
2424
<item name="android:paddingStart">@dimen/m3_comp_toolbar_docked_container_leading_space</item>
2525
<item name="android:paddingEnd">@dimen/m3_comp_toolbar_docked_container_trailing_space</item>
26+
<item name="android:fitsSystemWindows">true</item>
2627
</style>
2728

2829
<!-- Style for Docked Toolbar. -->

lib/java/com/google/android/material/floatingtoolbar/FloatingToolbarLayout.java

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@
1919
import com.google.android.material.R;
2020

2121
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
22-
import static java.lang.Math.max;
2322

2423
import android.content.Context;
2524
import android.content.res.ColorStateList;
2625
import androidx.appcompat.widget.TintTypedArray;
2726
import android.util.AttributeSet;
28-
import android.util.DisplayMetrics;
2927
import android.util.Log;
3028
import android.view.View;
3129
import android.view.ViewGroup;
@@ -62,50 +60,6 @@ public class FloatingToolbarLayout extends FrameLayout {
6260
private boolean marginRightSystemWindowInsets;
6361
private boolean marginBottomSystemWindowInsets;
6462

65-
private int topInset = 0;
66-
private int leftInset = 0;
67-
private int rightInset = 0;
68-
private int bottomInset = 0;
69-
70-
private final Runnable insetsRunnable =
71-
() -> {
72-
ViewGroup.LayoutParams lp = getLayoutParams();
73-
if (!(lp instanceof MarginLayoutParams)) {
74-
Log.w(TAG, "Unable to update margins because layout params are not MarginLayoutParams");
75-
return;
76-
}
77-
78-
int[] coords = new int[2];
79-
getLocationInWindow(coords);
80-
int x = coords[0];
81-
int y = coords[1];
82-
83-
DisplayMetrics displayMetrics = new DisplayMetrics();
84-
if (getDisplay() == null) {
85-
return;
86-
}
87-
getDisplay().getMetrics(displayMetrics);
88-
89-
MarginLayoutParams marginLp = (MarginLayoutParams) lp;
90-
91-
if (marginLeftSystemWindowInsets && x < leftInset) {
92-
marginLp.leftMargin = max(leftInset, marginLp.leftMargin);
93-
}
94-
95-
if (marginRightSystemWindowInsets && x + getWidth() > displayMetrics.widthPixels - rightInset) {
96-
marginLp.rightMargin = max(rightInset, marginLp.rightMargin);
97-
}
98-
99-
if (marginTopSystemWindowInsets && y < topInset) {
100-
marginLp.topMargin = max(topInset, marginLp.topMargin);
101-
}
102-
103-
if (marginBottomSystemWindowInsets && y + getHeight() > displayMetrics.heightPixels - bottomInset) {
104-
marginLp.bottomMargin = max(bottomInset, marginLp.bottomMargin);
105-
}
106-
requestLayout();
107-
};
108-
10963
public FloatingToolbarLayout(@NonNull Context context) {
11064
this(context, null);
11165
}
@@ -149,7 +103,8 @@ public FloatingToolbarLayout(
149103

150104
// Reading out if we are handling inset margins, so we can apply it to the content.
151105
marginLeftSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginLeftSystemWindowInsets, true);
152-
marginTopSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginTopSystemWindowInsets, true);
106+
// Top-aligned floating toolbars are not recommended, so a top inset margin is turned off by default
107+
marginTopSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginTopSystemWindowInsets, false);
153108
marginRightSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginRightSystemWindowInsets, true);
154109
marginBottomSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginBottomSystemWindowInsets, true);
155110

@@ -165,12 +120,37 @@ public WindowInsetsCompat onApplyWindowInsets(
165120
return insets;
166121
}
167122
Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
168-
bottomInset = systemBarInsets.bottom;
169-
topInset = systemBarInsets.top;
170-
rightInset = systemBarInsets.right;
171-
leftInset = systemBarInsets.left;
172-
v.removeCallbacks(insetsRunnable);
173-
v.post(insetsRunnable);
123+
Insets cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout());
124+
int bottomInset = systemBarInsets.bottom + cutoutInsets.bottom;
125+
int topInset = systemBarInsets.top + cutoutInsets.top;
126+
int rightInset = systemBarInsets.right + cutoutInsets.right;
127+
int leftInset = systemBarInsets.left + cutoutInsets.left;
128+
129+
ViewGroup.LayoutParams lp = getLayoutParams();
130+
if (!(lp instanceof MarginLayoutParams)) {
131+
Log.w(TAG, "Unable to update margins because layout params are not MarginLayoutParams");
132+
return insets;
133+
}
134+
135+
MarginLayoutParams marginLp = (MarginLayoutParams) lp;
136+
137+
if (marginLeftSystemWindowInsets) {
138+
marginLp.leftMargin += leftInset;
139+
}
140+
141+
if (marginRightSystemWindowInsets) {
142+
marginLp.rightMargin += rightInset;
143+
}
144+
145+
if (marginTopSystemWindowInsets) {
146+
marginLp.topMargin += topInset;
147+
}
148+
149+
if (marginBottomSystemWindowInsets) {
150+
marginLp.bottomMargin += bottomInset;
151+
}
152+
153+
requestLayout();
174154
return insets;
175155
}
176156
});

lib/java/com/google/android/material/floatingtoolbar/res/values/styles.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<item name="backgroundTint">@macro/m3_comp_toolbar_floating_standard_container_color</item>
2424
<item name="shapeAppearance">@style/ShapeAppearance.M3.Comp.Toolbar.Floating.Container.Shape</item>
2525
<item name="marginLeftSystemWindowInsets">true</item>
26-
<item name="marginTopSystemWindowInsets">true</item>
26+
<item name="marginTopSystemWindowInsets">false</item>
2727
<item name="marginRightSystemWindowInsets">true</item>
2828
<item name="marginBottomSystemWindowInsets">true</item>
2929
</style>

0 commit comments

Comments
 (0)