Skip to content

Commit

Permalink
[Badge][NavigationRail] Add new attribute for vertical offset when fo…
Browse files Browse the repository at this point in the history
…nt is large

PiperOrigin-RevId: 542366571
  • Loading branch information
imhappi authored and raajkumars committed Jun 26, 2023
1 parent 29d8742 commit 2362f4b
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 21 deletions.
31 changes: 16 additions & 15 deletions docs/components/BadgeDrawable.md
Expand Up @@ -90,21 +90,22 @@ center, use `setHorizontalOffset(int)` or `setVerticalOffset(int)`

### `BadgeDrawable` Attributes

| Feature | Relevant attributes |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Color | `app:backgroundColor` <br> `app:badgeTextColor` |
| Width | `app:badgeWidth` <br> `app:badgeWithTextWidth` |
| Height | `app:badgeHeight` <br> `app:badgeWithTextHeight` |
| Shape | `app:badgeShapeAppearance` <br> `app:badgeShapeAppearanceOverlay` <br> `app:badgeWithTextShapeAppearance` <br> `app:badgeWithTextShapeAppearanceOverlay` |
| Label | `app:badgeText` (for text) <br> `app:number` (for numbers) |
| Label Length | `app:maxCharacterCount` (for all text) <br> `app:maxNumber` (for numbers only) |
| Label Text Color | `app:badgeTextColor` |
| Label Text Appearance | `app:badgeTextAppearance` |
| Badge Gravity | `app:badgeGravity` |
| Offset Alignment | `app:offsetAlignmentMode` |
| Horizontal Padding | `app:badgeWidePadding` |
| Vertical Padding | `app:badgeVerticalPadding` |
| Auto Adjust | `app:autoAdjustToWithinGrandparentBounds` |
| Feature | Relevant attributes |
|----------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Color | `app:backgroundColor` <br> `app:badgeTextColor` |
| Width | `app:badgeWidth` <br> `app:badgeWithTextWidth` |
| Height | `app:badgeHeight` <br> `app:badgeWithTextHeight` |
| Shape | `app:badgeShapeAppearance` <br> `app:badgeShapeAppearanceOverlay` <br> `app:badgeWithTextShapeAppearance` <br> `app:badgeWithTextShapeAppearanceOverlay` |
| Label | `app:badgeText` (for text) <br> `app:number` (for numbers) |
| Label Length | `app:maxCharacterCount` (for all text) <br> `app:maxNumber` (for numbers only) |
| Label Text Color | `app:badgeTextColor` |
| Label Text Appearance | `app:badgeTextAppearance` |
| Badge Gravity | `app:badgeGravity` |
| Offset Alignment | `app:offsetAlignmentMode` |
| Horizontal Padding | `app:badgeWidePadding` |
| Vertical Padding | `app:badgeVerticalPadding` |
| Large Font Vertical Offset| `app:largeFontVerticalOffsetAdjustment` |
| Auto Adjust | `app:autoAdjustToWithinGrandparentBounds` |

**Note:** If both `app:badgeText` and `app:number` are specified, the badge label will be `app:badgeText`.

Expand Down
48 changes: 44 additions & 4 deletions lib/java/com/google/android/material/badge/BadgeDrawable.java
Expand Up @@ -47,9 +47,11 @@
import androidx.annotation.StyleRes;
import androidx.annotation.XmlRes;
import androidx.core.view.ViewCompat;
import com.google.android.material.animation.AnimationUtils;
import com.google.android.material.internal.TextDrawableHelper;
import com.google.android.material.internal.TextDrawableHelper.TextDrawableDelegate;
import com.google.android.material.internal.ThemeEnforcement;
import com.google.android.material.resources.MaterialResources;
import com.google.android.material.resources.TextAppearance;
import com.google.android.material.shape.MaterialShapeDrawable;
import com.google.android.material.shape.ShapeAppearanceModel;
Expand Down Expand Up @@ -187,6 +189,9 @@ public class BadgeDrawable extends Drawable implements TextDrawableDelegate {
/** A value to indicate that badge content should not be truncated. */
public static final int BADGE_CONTENT_NOT_TRUNCATED = -2;

/** The font scale threshold to changing the vertical offset of the badge. **/
private static final float FONT_SCALE_THRESHOLD = .3F;

@NonNull private final WeakReference<Context> contextRef;
@NonNull private final MaterialShapeDrawable shapeDrawable;
@NonNull private final TextDrawableHelper textDrawableHelper;
Expand Down Expand Up @@ -1009,6 +1014,29 @@ public int getVerticalOffsetWithText() {
return state.getVerticalOffsetWithText();
}

/**
* Sets how much (in pixels) to vertically move this badge away the center of its anchor when this
* badge has text and the font scale is at max size. This is in conjunction with the vertical
* offset with text.
*
* @param px how much to move the badge's vertical offset away from the center by when the font is
* large.
*/
public void setLargeFontVerticalOffsetAdjustment(@Px int px) {
state.setLargeFontVerticalOffsetAdjustment(px);
updateCenterAndBounds();
}

/**
* Returns how much (in pixels) this badge is being vertically moved away the center of its
* anchor when the badge has text and the font scale is at max. Note that this is not the total
* vertical offset.
*/
@Px
public int getLargeFontVerticalOffsetAdjustment() {
return state.getLargeFontVerticalOffsetAdjustment();
}

/**
* Sets how much (in pixels) more (in addition to {@code savedState.verticalOffset}) to vertically
* move this badge towards the center of its anchor. Currently used to adjust the placement of
Expand Down Expand Up @@ -1165,10 +1193,22 @@ private void updateCenterAndBounds() {
}

private int getTotalVerticalOffsetForState() {
int vOffset =
hasBadgeContent()
? state.getVerticalOffsetWithText()
: state.getVerticalOffsetWithoutText();
int vOffset = state.getVerticalOffsetWithoutText();
if (hasBadgeContent()) {
vOffset = state.getVerticalOffsetWithText();
Context context = contextRef.get();
if (context != null) {
float progress =
AnimationUtils.lerp(0F, 1F,
FONT_SCALE_THRESHOLD, 1F, MaterialResources.getFontScale(context) - 1F);
vOffset =
AnimationUtils.lerp(
vOffset, vOffset - state.getLargeFontVerticalOffsetAdjustment(), progress);
}
}



// If the offset alignment mode is at the edge of the anchor, we want to move the badge
// so that its origin is at the edge.
if (state.offsetAlignmentMode == OFFSET_ALIGNMENT_MODE_EDGE) {
Expand Down
23 changes: 22 additions & 1 deletion lib/java/com/google/android/material/badge/BadgeState.java
Expand Up @@ -264,9 +264,15 @@ public final class BadgeState {
currentState.verticalOffsetWithText =
storedState.verticalOffsetWithText == null
? a.getDimensionPixelOffset(
R.styleable.Badge_verticalOffsetWithText, currentState.verticalOffsetWithoutText)
R.styleable.Badge_verticalOffsetWithText, currentState.verticalOffsetWithoutText)
: storedState.verticalOffsetWithText;

currentState.largeFontVerticalOffsetAdjustment =
storedState.largeFontVerticalOffsetAdjustment == null
? a.getDimensionPixelOffset(
R.styleable.Badge_largeFontVerticalOffsetAdjustment, 0)
: storedState.largeFontVerticalOffsetAdjustment;

currentState.additionalHorizontalOffset =
storedState.additionalHorizontalOffset == null ? 0 : storedState.additionalHorizontalOffset;

Expand Down Expand Up @@ -521,6 +527,16 @@ void setVerticalOffsetWithText(@Dimension(unit = Dimension.PX) int offset) {
currentState.verticalOffsetWithText = offset;
}

@Dimension(unit = Dimension.PX)
int getLargeFontVerticalOffsetAdjustment() {
return currentState.largeFontVerticalOffsetAdjustment;
}

void setLargeFontVerticalOffsetAdjustment(@Dimension(unit = Dimension.PX) int offsetAdjustment) {
overridingState.largeFontVerticalOffsetAdjustment = offsetAdjustment;
currentState.largeFontVerticalOffsetAdjustment = offsetAdjustment;
}

@Dimension(unit = Dimension.PX)
int getAdditionalHorizontalOffset() {
return currentState.additionalHorizontalOffset;
Expand Down Expand Up @@ -662,6 +678,9 @@ public static final class State implements Parcelable {
@Dimension(unit = Dimension.PX)
private Integer additionalVerticalOffset;

@Dimension(unit = Dimension.PX)
private Integer largeFontVerticalOffsetAdjustment;

private Boolean autoAdjustToWithinGrandparentBounds;

public State() {}
Expand Down Expand Up @@ -690,6 +709,7 @@ public State() {}
verticalOffsetWithoutText = (Integer) in.readSerializable();
horizontalOffsetWithText = (Integer) in.readSerializable();
verticalOffsetWithText = (Integer) in.readSerializable();
largeFontVerticalOffsetAdjustment = (Integer) in.readSerializable();
additionalHorizontalOffset = (Integer) in.readSerializable();
additionalVerticalOffset = (Integer) in.readSerializable();
isVisible = (Boolean) in.readSerializable();
Expand Down Expand Up @@ -744,6 +764,7 @@ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeSerializable(verticalOffsetWithoutText);
dest.writeSerializable(horizontalOffsetWithText);
dest.writeSerializable(verticalOffsetWithText);
dest.writeSerializable(largeFontVerticalOffsetAdjustment);
dest.writeSerializable(additionalHorizontalOffset);
dest.writeSerializable(additionalVerticalOffset);
dest.writeSerializable(isVisible);
Expand Down
Expand Up @@ -28,6 +28,7 @@
<public name="badgeVerticalPadding" type="attr"/>
<public name="horizontalOffset" type="attr"/>
<public name="verticalOffset" type="attr"/>
<public name="largeFontVerticalOffsetAdjustment" type="attr"/>
<public name="offsetAlignmentMode" type="attr"/>
<public name="badgeWidth" type="attr"/>
<public name="badgeWithTextWidth" type="attr"/>
Expand Down
Expand Up @@ -92,6 +92,11 @@
badge has text. If this is not defined, it will default to
verticalOffset's value. -->
<attr name="verticalOffsetWithText" format="dimension"/>
<!-- How much to move the verticalOffsetWithText away from the center by
when the badge has text and the font is large. When the font is large,
we may want to shift the badge away from the center for more readability. This
attribute determines how much to shift the normal vertical offset by. -->
<attr name="largeFontVerticalOffsetAdjustment" format="dimension"/>
<!-- Automatically move the badge so it is within the anchor view's
grandparent's bounds. -->
<attr name="autoAdjustToWithinGrandparentBounds" format="boolean"/>
Expand Down
Expand Up @@ -42,5 +42,6 @@

<dimen name="m3_badge_offset">6dp</dimen>
<dimen name="m3_badge_with_text_offset">12dp</dimen>
<dimen name="m3_large_text_vertical_offset_adjustment">4dp</dimen>
<dimen name="m3_badge_with_text_vertical_padding">2dp</dimen>
</resources>
Expand Up @@ -93,7 +93,11 @@
</style>

<style name="ThemeOverlay.Material3.NavigationRailView" parent="">
<item name="badgeStyle">@style/Widget.Material3.Badge.AdjustToBounds</item>
<item name="badgeStyle">@style/Widget.Material3.NavigationRailView.Badge</item>
</style>

<style name="Widget.Material3.NavigationRailView.Badge" parent="Widget.Material3.Badge.AdjustToBounds">
<item name="largeFontVerticalOffsetAdjustment">@dimen/m3_large_text_vertical_offset_adjustment</item>
</style>

</resources>

0 comments on commit 2362f4b

Please sign in to comment.