Skip to content

Commit 8499b83

Browse files
imhappipekingme
authored andcommittedMar 21, 2023
[BadgeDrawable] Add padding in between top and bottom edges of badge and text
PiperOrigin-RevId: 518370027
1 parent 2aa1cf3 commit 8499b83

File tree

6 files changed

+59
-13
lines changed

6 files changed

+59
-13
lines changed
 

‎lib/java/com/google/android/material/badge/BadgeDrawable.java

+15-3
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ public void clearNumber() {
533533
}
534534

535535
private void onNumberUpdated() {
536-
textDrawableHelper.setTextWidthDirty(true);
536+
textDrawableHelper.setTextSizeDirty(true);
537537
onBadgeShapeAppearanceUpdated();
538538
updateCenterAndBounds();
539539
invalidateSelf();
@@ -564,7 +564,7 @@ public void setMaxCharacterCount(int maxCharacterCount) {
564564

565565
private void onMaxCharacterCountUpdated() {
566566
updateMaxBadgeNumber();
567-
textDrawableHelper.setTextWidthDirty(true);
567+
textDrawableHelper.setTextSizeDirty(true);
568568
updateCenterAndBounds();
569569
invalidateSelf();
570570
}
@@ -1017,8 +1017,20 @@ private void calculateCenterAndBounds(@NonNull Rect anchorRect, @NonNull View an
10171017
halfBadgeWidth =
10181018
Math.round(!hasNumber() ? state.badgeWidth / 2 : state.badgeWithTextWidth / 2);
10191019
}
1020+
String badgeText = getBadgeText();
1021+
// If the badge has a number, we want to make sure that the badge is at least tall/wide
1022+
// enough to encompass the text with padding.
1023+
if (hasNumber()) {
1024+
halfBadgeHeight =
1025+
Math.max(
1026+
halfBadgeHeight,
1027+
textDrawableHelper.getTextHeight(badgeText) / 2f + state.badgeVerticalPadding);
1028+
1029+
// If the badge has text, it should at least have the same width as it does height
1030+
halfBadgeWidth = Math.max(halfBadgeWidth, halfBadgeHeight);
1031+
}
1032+
10201033
if (getNumber() > MAX_CIRCULAR_BADGE_NUMBER_COUNT) {
1021-
String badgeText = getBadgeText();
10221034
halfBadgeWidth =
10231035
Math.max(
10241036
halfBadgeWidth,

‎lib/java/com/google/android/material/badge/BadgeState.java

+5
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public final class BadgeState {
7777
final float badgeWithTextWidth;
7878
final float badgeWithTextHeight;
7979
final float badgeWidePadding;
80+
final float badgeVerticalPadding;
8081
final int horizontalInset;
8182
final int horizontalInsetWithText;
8283

@@ -105,6 +106,10 @@ public final class BadgeState {
105106
a.getDimensionPixelSize(
106107
R.styleable.Badge_badgeWidePadding,
107108
res.getDimensionPixelSize(R.dimen.mtrl_badge_long_text_horizontal_padding));
109+
badgeVerticalPadding =
110+
a.getDimension(
111+
R.styleable.Badge_badgeVerticalPadding,
112+
res.getDimension(R.dimen.m3_badge_with_text_vertical_padding));
108113
horizontalInset =
109114
context
110115
.getResources()

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

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
<attr name="badgeRadius" format="dimension"/>
2727
<!-- Start and end padding for a badge that is oblong due to long text. -->
2828
<attr name="badgeWidePadding" format="dimension"/>
29+
<!-- Top and bottom padding for a badge that is tall due to large text. -->
30+
<attr name="badgeVerticalPadding" format="dimension"/>
2931
<!-- Radius of a badge with text. Deprecated, use badgeWithTextWidth and badgeWithTextHeight
3032
instead. If set, will override badge with text's width/height. -->
3133
<attr name="badgeWithTextRadius" format="dimension"/>

‎lib/java/com/google/android/material/badge/res/values/dimens.xml

+1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@
4242

4343
<dimen name="m3_badge_offset">6dp</dimen>
4444
<dimen name="m3_badge_with_text_offset">12dp</dimen>
45+
<dimen name="m3_badge_with_text_vertical_padding">2dp</dimen>
4546
</resources>

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

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<item name="verticalOffsetWithText">@dimen/m3_badge_with_text_offset</item>
6969
<item name="badgeTextAppearance">@macro/m3_comp_badge_large_label_text_type</item>
7070
<item name="badgeWithTextShapeAppearance">@style/ShapeAppearance.M3.Comp.Badge.Shape</item>
71+
<item name="badgeVerticalPadding">@dimen/m3_badge_with_text_vertical_padding</item>
7172
</style>
7273

7374
</resources>

‎lib/java/com/google/android/material/internal/TextDrawableHelper.java

+35-10
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void onFontRetrieved(@NonNull Typeface typeface, boolean fontResolvedSync
4747
if (fontResolvedSynchronously) {
4848
return;
4949
}
50-
textWidthDirty = true;
50+
textSizeDirty = true;
5151
TextDrawableDelegate textDrawableDelegate = delegate.get();
5252
if (textDrawableDelegate != null) {
5353
textDrawableDelegate.onTextSizeChange();
@@ -56,7 +56,7 @@ public void onFontRetrieved(@NonNull Typeface typeface, boolean fontResolvedSync
5656

5757
@Override
5858
public void onFontRetrievalFailed(int reason) {
59-
textWidthDirty = true;
59+
textSizeDirty = true;
6060
// Use fallback font.
6161
TextDrawableDelegate textDrawableDelegate = delegate.get();
6262
if (textDrawableDelegate != null) {
@@ -66,7 +66,8 @@ public void onFontRetrievalFailed(int reason) {
6666
};
6767

6868
private float textWidth;
69-
private boolean textWidthDirty = true;
69+
private float textHeight;
70+
private boolean textSizeDirty = true;
7071
@Nullable private WeakReference<TextDrawableDelegate> delegate = new WeakReference<>(null);
7172
@Nullable private TextAppearance textAppearance;
7273

@@ -88,21 +89,29 @@ public TextPaint getTextPaint() {
8889
}
8990

9091
public void setTextWidthDirty(boolean dirty) {
91-
textWidthDirty = dirty;
92+
textSizeDirty = dirty;
9293
}
9394

9495
public boolean isTextWidthDirty() {
95-
return textWidthDirty;
96+
return textSizeDirty;
97+
}
98+
99+
public void setTextSizeDirty(boolean dirty) {
100+
textSizeDirty = dirty;
101+
}
102+
103+
private void refreshTextDimens(String text) {
104+
textWidth = calculateTextWidth(text);
105+
textHeight = calculateTextHeight(text);
106+
textSizeDirty = false;
96107
}
97108

98109
/** Returns the visual width of the {@code text} based on its current text appearance. */
99110
public float getTextWidth(String text) {
100-
if (!textWidthDirty) {
111+
if (!textSizeDirty) {
101112
return textWidth;
102113
}
103-
104-
textWidth = calculateTextWidth(text);
105-
textWidthDirty = false;
114+
refreshTextDimens(text);
106115
return textWidth;
107116
}
108117

@@ -113,6 +122,22 @@ private float calculateTextWidth(@Nullable CharSequence charSequence) {
113122
return textPaint.measureText(charSequence, 0, charSequence.length());
114123
}
115124

125+
/** Returns the visual height of the {@code text} based on its current text appearance. */
126+
public float getTextHeight(@Nullable String text) {
127+
if (!textSizeDirty) {
128+
return textHeight;
129+
}
130+
refreshTextDimens(text);
131+
return textHeight;
132+
}
133+
134+
private float calculateTextHeight(@Nullable String str) {
135+
if (str == null) {
136+
return 0f;
137+
}
138+
return Math.abs(textPaint.getFontMetrics().ascent);
139+
}
140+
116141
/**
117142
* Returns the text appearance.
118143
*
@@ -141,7 +166,7 @@ public void setTextAppearance(@Nullable TextAppearance textAppearance, Context c
141166
textPaint.drawableState = textDrawableDelegate.getState();
142167
}
143168
textAppearance.updateDrawState(context, textPaint, fontCallback);
144-
textWidthDirty = true;
169+
textSizeDirty = true;
145170
}
146171

147172
TextDrawableDelegate textDrawableDelegate = delegate.get();

0 commit comments

Comments
 (0)
Please sign in to comment.