Skip to content

Commit 05f8c52

Browse files
imhappileticiarossi
authored andcommitted
[FloatingToolbar] Add inset handling
PiperOrigin-RevId: 712737242
1 parent f5b871a commit 05f8c52

File tree

6 files changed

+111
-4
lines changed

6 files changed

+111
-4
lines changed

docs/components/FloatingToolBar.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,14 @@ The following is an anatomy diagram for the navigation rail:
169169

170170
#### Container attributes
171171

172-
**Element** | **Attribute** | **Related methods** | **Default value**
173-
----------- | --------------------- | ------------------- | -----------------
174-
**Color** | `app:backgroundTint` | N/A | standard is `?attr/colorSurfaceContainer`, vibrant is `?attr/colorPrimaryContainer`
175-
**Shape** | `app:shapeAppearance` | N/A | `50% rounded`
172+
**Element** | **Attribute** | **Related methods** | **Default value**
173+
----------------------- | ------------------------------------ | ------------------- | -----------------
174+
**Color** | `app:backgroundTint` | N/A | standard is `?attr/colorSurfaceContainer`, vibrant is `?attr/colorPrimaryContainer`
175+
**Shape** | `app:shapeAppearance` | N/A | `50% rounded`
176+
**Left inset margin** | `app:marginLeftSystemWindowInsets` | N/A | `true`
177+
**Top inset margin** | `app:marginTopSystemWindowInsets` | N/A | `true`
178+
**Right inset margin** | `app:marginRightSystemWindowInsets` | N/A | `true`
179+
**Bottom inset margin** | `app:marginBottomSystemWindowInsets` | N/A | `true`
176180

177181
#### Styles
178182

@@ -184,6 +188,8 @@ The following is an anatomy diagram for the navigation rail:
184188
Standard style theme attribute: `?attr/floatingToolbarStyle`
185189
Vibrant style theme attribute: `?attr/floatingToolbarVibrantStyle`
186190

191+
Floating toolbar also provides specific styles for icon buttons, `Widget.Material3.FloatingToolbar.IconButton` and `Widget.Material3.FloatingToolbar.IconButton.Vibrant`.
192+
187193
See the full list of
188194
[styles](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/floatingtoolbar/res/values/styles.xml) and
189195
[floating toolbar attributes](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/floatingtoolbar/res/values/attrs.xml)

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

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,26 @@
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;
2223

2324
import android.content.Context;
2425
import android.content.res.ColorStateList;
2526
import androidx.appcompat.widget.TintTypedArray;
2627
import android.util.AttributeSet;
28+
import android.util.DisplayMetrics;
29+
import android.util.Log;
30+
import android.view.View;
31+
import android.view.ViewGroup;
2732
import android.widget.FrameLayout;
2833
import androidx.annotation.AttrRes;
2934
import androidx.annotation.ColorInt;
3035
import androidx.annotation.NonNull;
3136
import androidx.annotation.Nullable;
3237
import androidx.annotation.StyleRes;
3338
import androidx.coordinatorlayout.widget.CoordinatorLayout.AttachedBehavior;
39+
import androidx.core.graphics.Insets;
40+
import androidx.core.view.ViewCompat;
41+
import androidx.core.view.WindowInsetsCompat;
3442
import com.google.android.material.behavior.HideViewOnScrollBehavior;
3543
import com.google.android.material.internal.ThemeEnforcement;
3644
import com.google.android.material.shape.MaterialShapeDrawable;
@@ -47,9 +55,60 @@
4755
* {@link android.view.ViewGroup}.
4856
*/
4957
public class FloatingToolbarLayout extends FrameLayout implements AttachedBehavior {
58+
59+
private static final String TAG = FloatingToolbarLayout.class.getSimpleName();
5060
private static final int DEF_STYLE_RES = R.style.Widget_Material3_FloatingToolbar;
5161
@Nullable private Behavior behavior;
5262

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

153+
// Reading out if we are handling inset margins, so we can apply it to the content.
154+
marginLeftSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginLeftSystemWindowInsets, true);
155+
marginTopSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginTopSystemWindowInsets, true);
156+
marginRightSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginRightSystemWindowInsets, true);
157+
marginBottomSystemWindowInsets = attributes.getBoolean(R.styleable.FloatingToolbar_marginBottomSystemWindowInsets, true);
158+
159+
ViewCompat.setOnApplyWindowInsetsListener(
160+
this,
161+
new androidx.core.view.OnApplyWindowInsetsListener() {
162+
@NonNull
163+
@Override
164+
public WindowInsetsCompat onApplyWindowInsets(
165+
@NonNull View v, @NonNull WindowInsetsCompat insets) {
166+
if (!marginLeftSystemWindowInsets && !marginRightSystemWindowInsets
167+
&& !marginTopSystemWindowInsets && !marginBottomSystemWindowInsets) {
168+
return insets;
169+
}
170+
Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
171+
bottomInset = systemBarInsets.bottom;
172+
topInset = systemBarInsets.top;
173+
rightInset = systemBarInsets.right;
174+
leftInset = systemBarInsets.left;
175+
v.removeCallbacks(insetsRunnable);
176+
v.post(insetsRunnable);
177+
return insets;
178+
}
179+
});
180+
94181
attributes.recycle();
95182
}
96183

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,13 @@
2424
<declare-styleable name="FloatingToolbar">
2525
<!-- Color of the floating toolbar container. -->
2626
<attr name="backgroundTint"/>
27+
<!-- Whether or not to add additional top margin to handle the top inset. -->
28+
<attr name="marginTopSystemWindowInsets"/>
29+
<!-- Whether or not to add additional left margin to handle the left inset. -->
30+
<attr name="marginLeftSystemWindowInsets"/>
31+
<!-- Whether or not to add additional right margin to handle the top inset. -->
32+
<attr name="marginRightSystemWindowInsets"/>
33+
<!-- Whether or not to add additional bottom margin to handle the top inset. -->
34+
<attr name="marginBottomSystemWindowInsets"/>
2735
</declare-styleable>
2836
</resources>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
<item name="android:minWidth">@dimen/m3_comp_toolbar_floating_container_height</item>
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>
25+
<item name="marginLeftSystemWindowInsets">true</item>
26+
<item name="marginTopSystemWindowInsets">true</item>
27+
<item name="marginRightSystemWindowInsets">true</item>
28+
<item name="marginBottomSystemWindowInsets">true</item>
2529
</style>
2630

2731
<!-- Style for Floating Toolbar. -->

lib/java/com/google/android/material/internal/res-public/values/public.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@
2626
<public name="marginLeftSystemWindowInsets" type="attr"/>
2727
<public name="marginRightSystemWindowInsets" type="attr"/>
2828
<public name="marginTopSystemWindowInsets" type="attr"/>
29+
<public name="marginBottomSystemWindowInsets" type="attr"/>
2930
<public name="Widget.Design.ScrimInsetsFrameLayout" type="style"/>
3031
</resources>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<attr name="marginLeftSystemWindowInsets" format="boolean"/>
6464
<attr name="marginRightSystemWindowInsets" format="boolean"/>
6565
<attr name="marginTopSystemWindowInsets" format="boolean"/>
66+
<attr name="marginBottomSystemWindowInsets" format="boolean"/>
6667
</declare-styleable>
6768

6869
</resources>

0 commit comments

Comments
 (0)