summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Xiaowen Lei <xilei@google.com> 2025-01-02 18:34:47 +0000
committer Xiaowen Lei <xilei@google.com> 2025-01-08 07:55:56 +0000
commitef7cce266ca0592f7f7cef61c63e2eea56552393 (patch)
tree56108b33c703ceacd5cc45e3c8d257f16ab84caf
parentddd8f08c0d6d59ae2c30db925f54dd0a9659736b (diff)
Stretch and rescale segments to satisfy minimum width requirement.
The same function also returns the location of the progress on the rescaled progress bar, which is used to calculate the tracker position. The fallback option (for when it's impossible to satisfy the segment minimum width) will be implemented in a separate CL following this one. Flag: android.app.api_rich_ongoing Bug: 372908709 Bug: 383566179 Bug: 383564913 Test: NotificationProgressBarTest Test: Post ProgressStyle notifs via test app Test: patch ag/30006048 and run ProgressStyleNotificationScreenshotTest Change-Id: Ieb551182a9823d7231db345fcdf4a8d09ad4acaa
-rw-r--r--core/java/com/android/internal/widget/NotificationProgressBar.java209
-rw-r--r--core/java/com/android/internal/widget/NotificationProgressDrawable.java46
-rw-r--r--core/res/res/drawable/notification_progress.xml1
-rw-r--r--core/res/res/values/attrs.xml7
-rw-r--r--core/res/res/values/dimens.xml2
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java412
7 files changed, 581 insertions, 97 deletions
diff --git a/core/java/com/android/internal/widget/NotificationProgressBar.java b/core/java/com/android/internal/widget/NotificationProgressBar.java
index d8001d82b3e9..f0b54937546b 100644
--- a/core/java/com/android/internal/widget/NotificationProgressBar.java
+++ b/core/java/com/android/internal/widget/NotificationProgressBar.java
@@ -32,6 +32,7 @@ import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.view.RemotableViewMethod;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
@@ -67,6 +68,7 @@ public final class NotificationProgressBar extends ProgressBar implements
@Nullable
private List<Part> mParts = null;
+ // List of drawable parts before segment splitting by process.
@Nullable
private List<NotificationProgressDrawable.Part> mProgressDrawableParts = null;
@@ -81,7 +83,13 @@ public final class NotificationProgressBar extends ProgressBar implements
private final Matrix mMatrix = new Matrix();
private Matrix mTrackerDrawMatrix = null;
- private float mScale = 0;
+ private float mProgressFraction = 0;
+ /**
+ * The location of progress on the stretched and rescaled progress bar, in fraction. Used for
+ * calculating the tracker position. If stretching and rescaling is not needed, ==
+ * mProgressFraction.
+ */
+ private float mAdjustedProgressFraction = 0;
/** Indicates whether mTrackerPos needs to be recalculated before the tracker is drawn. */
private boolean mTrackerPosIsDirty = false;
@@ -143,6 +151,10 @@ public final class NotificationProgressBar extends ProgressBar implements
final int indeterminateColor = mProgressModel.getIndeterminateColor();
setIndeterminateTintList(ColorStateList.valueOf(indeterminateColor));
} else {
+ // TODO: b/372908709 - maybe don't rerun the entire calculation every time the
+ // progress model is updated? For example, if the segments and parts aren't changed,
+ // there is no need to call `processAndConvertToViewParts` again.
+
final int progress = mProgressModel.getProgress();
final int progressMax = mProgressModel.getProgressMax();
@@ -342,10 +354,10 @@ public final class NotificationProgressBar extends ProgressBar implements
}
private void onMaybeVisualProgressChanged() {
- float scale = getScale();
- if (mScale == scale) return;
+ float progressFraction = getProgressFraction();
+ if (mProgressFraction == progressFraction) return;
- mScale = scale;
+ mProgressFraction = progressFraction;
mTrackerPosIsDirty = true;
invalidate();
}
@@ -427,12 +439,21 @@ public final class NotificationProgressBar extends ProgressBar implements
mNotificationProgressDrawable.getSegSegGap(),
mNotificationProgressDrawable.getSegPointGap(),
mNotificationProgressDrawable.getPointRadius(),
- mHasTrackerIcon,
- getScale() * width,
- mProgressModel.isStyledByProgress());
+ mHasTrackerIcon
+ );
+ Pair<List<NotificationProgressDrawable.Part>, Float> p = maybeStretchAndRescaleSegments(
+ mParts,
+ mProgressDrawableParts,
+ mNotificationProgressDrawable.getSegmentMinWidth(),
+ mNotificationProgressDrawable.getPointRadius(),
+ getProgressFraction(),
+ width,
+ mProgressModel.isStyledByProgress(),
+ mHasTrackerIcon ? 0F : mNotificationProgressDrawable.getSegSegGap());
Log.d(TAG, "Updating NotificationProgressDrawable parts");
- mNotificationProgressDrawable.setParts(mProgressDrawableParts);
+ mNotificationProgressDrawable.setParts(p.first);
+ mAdjustedProgressFraction = p.second / width;
}
private void updateTrackerAndBarPos(int w, int h) {
@@ -465,11 +486,11 @@ public final class NotificationProgressBar extends ProgressBar implements
}
if (tracker != null) {
- setTrackerPos(w, tracker, mScale, trackerOffsetY);
+ setTrackerPos(w, tracker, mAdjustedProgressFraction, trackerOffsetY);
}
}
- private float getScale() {
+ private float getProgressFraction() {
int min = getMin();
int max = getMax();
int range = max - min;
@@ -481,17 +502,17 @@ public final class NotificationProgressBar extends ProgressBar implements
*
* @param w Width of the view, including padding
* @param tracker Drawable used for the tracker
- * @param scale Current progress between 0 and 1
+ * @param progressFraction Current progress between 0 and 1
* @param offsetY Vertical offset for centering. If set to
* {@link Integer#MIN_VALUE}, the current offset will be used.
*/
- private void setTrackerPos(int w, Drawable tracker, float scale, int offsetY) {
+ private void setTrackerPos(int w, Drawable tracker, float progressFraction, int offsetY) {
int available = w - mPaddingLeft - mPaddingRight;
final int trackerWidth = tracker.getIntrinsicWidth();
final int trackerHeight = tracker.getIntrinsicHeight();
available -= ((mTrackerHeight <= 0) ? trackerWidth : mTrackerWidth);
- final int trackerPos = (int) (scale * available + 0.5f);
+ final int trackerPos = (int) (progressFraction * available + 0.5f);
final int top, bottom;
if (offsetY == Integer.MIN_VALUE) {
@@ -545,7 +566,7 @@ public final class NotificationProgressBar extends ProgressBar implements
if (mTracker == null) return;
if (mTrackerPosIsDirty) {
- setTrackerPos(getWidth(), mTracker, mScale, Integer.MIN_VALUE);
+ setTrackerPos(getWidth(), mTracker, mAdjustedProgressFraction, Integer.MIN_VALUE);
}
final int saveCount = canvas.save();
@@ -594,7 +615,7 @@ public final class NotificationProgressBar extends ProgressBar implements
final Drawable tracker = mTracker;
if (tracker != null) {
- setTrackerPos(getWidth(), tracker, mScale, Integer.MIN_VALUE);
+ setTrackerPos(getWidth(), tracker, mAdjustedProgressFraction, Integer.MIN_VALUE);
// Since we draw translated, the drawable's bounds that it signals
// for invalidation won't be the actual bounds we want invalidated,
@@ -776,9 +797,7 @@ public final class NotificationProgressBar extends ProgressBar implements
float segSegGap,
float segPointGap,
float pointRadius,
- boolean hasTrackerIcon,
- float progressX,
- boolean isStyledByProgress
+ boolean hasTrackerIcon
) {
List<NotificationProgressDrawable.Part> drawableParts = new ArrayList<>();
@@ -826,12 +845,7 @@ public final class NotificationProgressBar extends ProgressBar implements
}
}
- return maybeSplitDrawableSegmentsByProgress(
- isStyledByProgress,
- parts,
- drawableParts,
- progressX,
- hasTrackerIcon ? 0F : segSegGap);
+ return drawableParts;
}
private static float getSegStartOffset(Part prevPart, float pointRadius, float segPointGap,
@@ -859,33 +873,148 @@ public final class NotificationProgressBar extends ProgressBar implements
return segPointGap + pointRadius + pointOffset;
}
- // If isStyledByProgress is true, also split the segment with the progress value in its range.
- private static List<NotificationProgressDrawable.Part> maybeSplitDrawableSegmentsByProgress(
+ /**
+ * Processes the list of {@code NotificationProgressBar.Part} data and convert to a pair of:
+ * - list of {@code NotificationProgressDrawable.Part}.
+ * - location of progress on the stretched and rescaled progress bar.
+ */
+ @VisibleForTesting
+ public static Pair<List<NotificationProgressDrawable.Part>, Float>
+ maybeStretchAndRescaleSegments(
+ List<Part> parts,
+ List<NotificationProgressDrawable.Part> drawableParts,
+ float segmentMinWidth,
+ float pointRadius,
+ float progressFraction,
+ float totalWidth,
boolean isStyledByProgress,
+ float progressGap
+ ) {
+ final List<NotificationProgressDrawable.Segment> drawableSegments = drawableParts
+ .stream()
+ .filter(NotificationProgressDrawable.Segment.class::isInstance)
+ .map(NotificationProgressDrawable.Segment.class::cast)
+ .toList();
+ float totalExcessWidth = 0;
+ float totalPositiveExcessWidth = 0;
+ for (NotificationProgressDrawable.Segment drawableSegment : drawableSegments) {
+ final float excessWidth = drawableSegment.getWidth() - segmentMinWidth;
+ totalExcessWidth += excessWidth;
+ if (excessWidth > 0) totalPositiveExcessWidth += excessWidth;
+ }
+
+ // All drawable segments are above minimum width. No need to stretch and rescale.
+ if (totalExcessWidth == totalPositiveExcessWidth) {
+ return maybeSplitDrawableSegmentsByProgress(
+ parts,
+ drawableParts,
+ progressFraction,
+ totalWidth,
+ isStyledByProgress,
+ progressGap);
+ }
+
+ if (totalExcessWidth < 0) {
+ // TODO: b/372908709 - throw an error so that the caller can catch and go to fallback
+ // option. (instead of return.)
+ Log.w(TAG, "Not enough width to satisfy the minimum width for segments.");
+ return maybeSplitDrawableSegmentsByProgress(
+ parts,
+ drawableParts,
+ progressFraction,
+ totalWidth,
+ isStyledByProgress,
+ progressGap);
+ }
+
+ final int nParts = drawableParts.size();
+ float startOffset = 0;
+ for (int iPart = 0; iPart < nParts; iPart++) {
+ final NotificationProgressDrawable.Part drawablePart = drawableParts.get(iPart);
+ if (drawablePart instanceof NotificationProgressDrawable.Segment drawableSegment) {
+ final float origDrawableSegmentWidth = drawableSegment.getWidth();
+
+ float drawableSegmentWidth = segmentMinWidth;
+ // Allocate the totalExcessWidth to the segments above minimum, proportionally to
+ // their initial excessWidth.
+ if (origDrawableSegmentWidth > segmentMinWidth) {
+ drawableSegmentWidth +=
+ totalExcessWidth * (origDrawableSegmentWidth - segmentMinWidth)
+ / totalPositiveExcessWidth;
+ }
+
+ final float widthDiff = drawableSegmentWidth - drawableSegment.getWidth();
+
+ // Adjust drawable segments to new widths
+ drawableSegment.setStart(drawableSegment.getStart() + startOffset);
+ drawableSegment.setEnd(
+ drawableSegment.getStart() + origDrawableSegmentWidth + widthDiff);
+
+ // Also adjust view segments to new width. (For view segments, only start is
+ // needed?)
+ // Check that segments and drawableSegments are of the same size?
+ final Segment segment = (Segment) parts.get(iPart);
+ final float origSegmentWidth = segment.getWidth();
+ segment.mStart = segment.mStart + startOffset;
+ segment.mEnd = segment.mStart + origSegmentWidth + widthDiff;
+
+ // Increase startOffset for the subsequent segments.
+ startOffset += widthDiff;
+ } else if (drawablePart instanceof NotificationProgressDrawable.Point drawablePoint) {
+ drawablePoint.setStart(drawablePoint.getStart() + startOffset);
+ drawablePoint.setEnd(drawablePoint.getStart() + 2 * pointRadius);
+ }
+ }
+
+ return maybeSplitDrawableSegmentsByProgress(
+ parts,
+ drawableParts,
+ progressFraction,
+ totalWidth,
+ isStyledByProgress,
+ progressGap);
+ }
+
+ // Find the location of progress on the stretched and rescaled progress bar.
+ // If isStyledByProgress is true, also split the segment with the progress value in its range.
+ private static Pair<List<NotificationProgressDrawable.Part>, Float>
+ maybeSplitDrawableSegmentsByProgress(
// Needed to get the original segment start and end positions in pixels.
List<Part> parts,
List<NotificationProgressDrawable.Part> drawableParts,
- float progressX,
+ float progressFraction,
+ float totalWidth,
+ boolean isStyledByProgress,
float progressGap
) {
- if (!isStyledByProgress) return drawableParts;
+ if (progressFraction == 1) return new Pair<>(drawableParts, totalWidth);
int iPartFirstSegmentToStyle = -1;
int iPartSegmentToSplit = -1;
+ float rescaledProgressX = 0;
+ float startFraction = 0;
final int nParts = parts.size();
for (int iPart = 0; iPart < nParts; iPart++) {
final Part part = parts.get(iPart);
if (!(part instanceof Segment)) continue;
final Segment segment = (Segment) part;
- if (segment.mStart == progressX) {
+ if (startFraction == progressFraction) {
iPartFirstSegmentToStyle = iPart;
+ rescaledProgressX = segment.mStart;
break;
- } else if (segment.mStart < progressX && progressX < segment.mEnd) {
+ } else if (startFraction < progressFraction
+ && progressFraction < startFraction + segment.mFraction) {
iPartSegmentToSplit = iPart;
+ rescaledProgressX =
+ segment.mStart + (progressFraction - startFraction) / segment.mFraction
+ * segment.getWidth();
break;
}
+ startFraction += segment.mFraction;
}
+ if (!isStyledByProgress) return new Pair<>(drawableParts, rescaledProgressX);
+
List<NotificationProgressDrawable.Part> splitDrawableParts = new ArrayList<>();
boolean styleRemainingParts = false;
for (int iPart = 0; iPart < nParts; iPart++) {
@@ -899,22 +1028,23 @@ public final class NotificationProgressBar extends ProgressBar implements
if (iPart == iPartFirstSegmentToStyle) styleRemainingParts = true;
if (drawablePart instanceof NotificationProgressDrawable.Segment drawableSegment) {
if (iPart == iPartSegmentToSplit) {
- if (progressX <= drawableSegment.getStart()) {
+ if (rescaledProgressX <= drawableSegment.getStart()) {
styleRemainingParts = true;
final int color = maybeGetFadedColor(drawableSegment.getColor(), true);
splitDrawableParts.add(
new NotificationProgressDrawable.Segment(drawableSegment.getStart(),
drawableSegment.getEnd(),
color, true));
- } else if (drawableSegment.getStart() < progressX
- && progressX < drawableSegment.getEnd()) {
+ } else if (drawableSegment.getStart() < rescaledProgressX
+ && rescaledProgressX < drawableSegment.getEnd()) {
splitDrawableParts.add(
new NotificationProgressDrawable.Segment(drawableSegment.getStart(),
- progressX - progressGap,
+ rescaledProgressX - progressGap,
drawableSegment.getColor()));
final int color = maybeGetFadedColor(drawableSegment.getColor(), true);
- splitDrawableParts.add(new NotificationProgressDrawable.Segment(progressX,
- drawableSegment.getEnd(), color, true));
+ splitDrawableParts.add(
+ new NotificationProgressDrawable.Segment(rescaledProgressX,
+ drawableSegment.getEnd(), color, true));
styleRemainingParts = true;
} else {
splitDrawableParts.add(
@@ -934,7 +1064,7 @@ public final class NotificationProgressBar extends ProgressBar implements
}
}
- return splitDrawableParts;
+ return new Pair<>(splitDrawableParts, rescaledProgressX);
}
/**
@@ -984,6 +1114,11 @@ public final class NotificationProgressBar extends ProgressBar implements
mFaded = faded;
}
+ /** Returns the calculated drawing width of the part */
+ public float getWidth() {
+ return mEnd - mStart;
+ }
+
@Override
public String toString() {
return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", faded="
diff --git a/core/java/com/android/internal/widget/NotificationProgressDrawable.java b/core/java/com/android/internal/widget/NotificationProgressDrawable.java
index 3327b942c8e3..ef0a5d5cdec2 100644
--- a/core/java/com/android/internal/widget/NotificationProgressDrawable.java
+++ b/core/java/com/android/internal/widget/NotificationProgressDrawable.java
@@ -95,6 +95,13 @@ public final class NotificationProgressDrawable extends Drawable {
}
/**
+ * Returns the gap between a segment and a point.
+ */
+ public float getSegmentMinWidth() {
+ return mState.mSegmentMinWidth;
+ }
+
+ /**
* Returns the radius for the points.
*/
public float getPointRadius() {
@@ -322,6 +329,8 @@ public final class NotificationProgressDrawable extends Drawable {
// Extract the theme attributes, if any.
state.mThemeAttrsSegments = a.extractThemeAttrs();
+ state.mSegmentMinWidth = a.getDimension(
+ R.styleable.NotificationProgressDrawableSegments_minWidth, state.mSegmentMinWidth);
state.mSegmentHeight = a.getDimension(
R.styleable.NotificationProgressDrawableSegments_height, state.mSegmentHeight);
state.mFadedSegmentHeight = a.getDimension(
@@ -408,10 +417,12 @@ public final class NotificationProgressDrawable extends Drawable {
* varying drawing width, or a {@link Point} with zero length and fixed size for drawing.
*/
public abstract static class Part {
- /** Start position for drawing (in pixels). */
- protected final float mStart;
- /** End position for drawing (in pixels). */
- protected final float mEnd;
+ // TODO: b/372908709 - maybe rename start/end to left/right, to be consistent with the
+ // bounds rect.
+ /** Start position for drawing (in pixels) */
+ protected float mStart;
+ /** End position for drawing (in pixels) */
+ protected float mEnd;
/** Drawing color. */
@ColorInt protected final int mColor;
@@ -425,10 +436,23 @@ public final class NotificationProgressDrawable extends Drawable {
return this.mStart;
}
+ public void setStart(float start) {
+ mStart = start;
+ }
+
public float getEnd() {
return this.mEnd;
}
+ public void setEnd(float end) {
+ mEnd = end;
+ }
+
+ /** Returns the calculated drawing width of the part */
+ public float getWidth() {
+ return mEnd - mStart;
+ }
+
public int getColor() {
return this.mColor;
}
@@ -537,6 +561,7 @@ public final class NotificationProgressDrawable extends Drawable {
int mChangingConfigurations;
float mSegSegGap = 0.0f;
float mSegPointGap = 0.0f;
+ float mSegmentMinWidth = 0.0f;
float mSegmentHeight;
float mFadedSegmentHeight;
float mSegmentCornerRadius;
@@ -558,6 +583,7 @@ public final class NotificationProgressDrawable extends Drawable {
mChangingConfigurations = orig.mChangingConfigurations;
mSegSegGap = orig.mSegSegGap;
mSegPointGap = orig.mSegPointGap;
+ mSegmentMinWidth = orig.mSegmentMinWidth;
mSegmentHeight = orig.mSegmentHeight;
mFadedSegmentHeight = orig.mFadedSegmentHeight;
mSegmentCornerRadius = orig.mSegmentCornerRadius;
@@ -576,6 +602,18 @@ public final class NotificationProgressDrawable extends Drawable {
}
private void applyDensityScaling(int sourceDensity, int targetDensity) {
+ if (mSegSegGap > 0) {
+ mSegSegGap = scaleFromDensity(
+ mSegSegGap, sourceDensity, targetDensity);
+ }
+ if (mSegPointGap > 0) {
+ mSegPointGap = scaleFromDensity(
+ mSegPointGap, sourceDensity, targetDensity);
+ }
+ if (mSegmentMinWidth > 0) {
+ mSegmentMinWidth = scaleFromDensity(
+ mSegmentMinWidth, sourceDensity, targetDensity);
+ }
if (mSegmentHeight > 0) {
mSegmentHeight = scaleFromDensity(
mSegmentHeight, sourceDensity, targetDensity);
diff --git a/core/res/res/drawable/notification_progress.xml b/core/res/res/drawable/notification_progress.xml
index 5d272fb00e34..ff5450ee106f 100644
--- a/core/res/res/drawable/notification_progress.xml
+++ b/core/res/res/drawable/notification_progress.xml
@@ -24,6 +24,7 @@
android:segPointGap="@dimen/notification_progress_segPoint_gap">
<segments
android:color="?attr/colorProgressBackgroundNormal"
+ android:minWidth="@dimen/notification_progress_segments_min_width"
android:height="@dimen/notification_progress_segments_height"
android:fadedHeight="@dimen/notification_progress_segments_faded_height"
android:cornerRadius="@dimen/notification_progress_segments_corner_radius"/>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 02207f8c7ea4..8372aecf0d27 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7584,6 +7584,13 @@
<!-- Used to config the segments of a NotificationProgressDrawable. -->
<!-- @hide internal use only -->
<declare-styleable name="NotificationProgressDrawableSegments">
+ <!-- TODO: b/372908709 - maybe move this to NotificationProgressBar, because that's the only
+ place this is used actually. Same for NotificationProgressDrawable.segSegGap/segPointGap
+ above. -->
+ <!-- Minimum required drawing width. The drawing width refers to the width after
+ the original segments have been adjusted for the neighboring Points and gaps. This is
+ enforced by stretching the segments that are too short. -->
+ <attr name="minWidth" format="dimension" />
<!-- Height of the solid segments. -->
<attr name="height" />
<!-- Height of the faded segments. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2adb79118ed9..593618b086c5 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -888,6 +888,8 @@
<dimen name="notification_progress_segSeg_gap">4dp</dimen>
<!-- The gap between a segment and a point in the notification progress bar -->
<dimen name="notification_progress_segPoint_gap">4dp</dimen>
+ <!-- The minimum required drawing width of the notification progress bar segments -->
+ <dimen name="notification_progress_segments_min_width">16dp</dimen>
<!-- The height of the notification progress bar segments -->
<dimen name="notification_progress_segments_height">6dp</dimen>
<!-- The height of the notification progress bar faded segments -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a18f923d625b..3e8e7f6fbc6e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3939,6 +3939,7 @@
<java-symbol type="dimen" name="notification_progress_tracker_height" />
<java-symbol type="dimen" name="notification_progress_segSeg_gap" />
<java-symbol type="dimen" name="notification_progress_segPoint_gap" />
+ <java-symbol type="dimen" name="notification_progress_segments_min_width" />
<java-symbol type="dimen" name="notification_progress_segments_height" />
<java-symbol type="dimen" name="notification_progress_segments_faded_height" />
<java-symbol type="dimen" name="notification_progress_segments_corner_radius" />
diff --git a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
index 6a74b4451308..f105ec305eab 100644
--- a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.Notification.ProgressStyle;
import android.graphics.Color;
+import android.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -109,9 +110,6 @@ public class NotificationProgressBarTest {
List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
progress, progressMax);
- // Colors with 40% opacity
- int fadedRed = 0x66FF0000;
-
List<Part> expectedParts = new ArrayList<>(List.of(new Segment(1f, Color.RED)));
assertThat(parts).isEqualTo(expectedParts);
@@ -121,17 +119,32 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- float progressX = 0;
- boolean isStyledByProgress = true;
+
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
- List.of(new NotificationProgressDrawable.Segment(0, 300, fadedRed, true)));
+ List.of(new NotificationProgressDrawable.Segment(0, 300, Color.RED)));
assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ // Colors with 40% opacity
+ int fadedRed = 0x66FF0000;
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Segment(0, 300, fadedRed, true)));
+
+ assertThat(p.second).isEqualTo(0);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
@Test
@@ -154,17 +167,27 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- float progressX = 300;
- boolean isStyledByProgress = true;
+
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
List.of(new NotificationProgressDrawable.Segment(0, 300, Color.RED)));
assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ assertThat(p.second).isEqualTo(300);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
@Test(expected = IllegalArgumentException.class)
@@ -217,9 +240,6 @@ public class NotificationProgressBarTest {
List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(
segments, points, progress, progressMax);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
-
List<Part> expectedParts = new ArrayList<>(List.of(
new Segment(0.50f, Color.RED),
new Segment(0.50f, Color.GREEN)));
@@ -231,19 +251,34 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- float progressX = 180;
- boolean isStyledByProgress = true;
+
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
List.of(new NotificationProgressDrawable.Segment(0, 146, Color.RED),
+ new NotificationProgressDrawable.Segment(150, 300, Color.GREEN)));
+
+ assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ // Colors with 40% opacity
+ int fadedGreen = 0x6600FF00;
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Segment(0, 146, Color.RED),
new NotificationProgressDrawable.Segment(150, 180, Color.GREEN),
new NotificationProgressDrawable.Segment(180, 300, fadedGreen, true)));
- assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+ assertThat(p.second).isEqualTo(180);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
@Test
@@ -257,9 +292,6 @@ public class NotificationProgressBarTest {
List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
progress, progressMax);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
-
List<Part> expectedParts = new ArrayList<>(List.of(
new Segment(0.50f, Color.RED),
new Segment(0.50f, Color.GREEN)));
@@ -271,19 +303,34 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = false;
- float progressX = 180;
- boolean isStyledByProgress = true;
+
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
List.of(new NotificationProgressDrawable.Segment(0, 146, Color.RED),
+ new NotificationProgressDrawable.Segment(150, 300, Color.GREEN)));
+
+ assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ // Colors with 40% opacity
+ int fadedGreen = 0x6600FF00;
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Segment(0, 146, Color.RED),
new NotificationProgressDrawable.Segment(150, 176, Color.GREEN),
new NotificationProgressDrawable.Segment(180, 300, fadedGreen, true)));
- assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+ assertThat(p.second).isEqualTo(180);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
@Test
@@ -298,9 +345,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- // Colors with 40% opacity
- int fadedBlue = 0x660000FF;
- int fadedYellow = 0x66FFFF00;
+ List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
+ progress, progressMax);
List<Part> expectedParts = new ArrayList<>(List.of(
new Segment(0.15f, Color.BLUE),
@@ -313,9 +359,6 @@ public class NotificationProgressBarTest {
new Point(Color.YELLOW),
new Segment(0.25f, Color.BLUE)));
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
-
assertThat(parts).isEqualTo(expectedParts);
float drawableWidth = 300;
@@ -323,12 +366,11 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- float progressX = 180;
- boolean isStyledByProgress = true;
+
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
List.of(new NotificationProgressDrawable.Segment(0, 35, Color.BLUE),
@@ -337,11 +379,38 @@ public class NotificationProgressBarTest {
new NotificationProgressDrawable.Point(69, 81, Color.BLUE),
new NotificationProgressDrawable.Segment(85, 170, Color.BLUE),
new NotificationProgressDrawable.Point(174, 186, Color.BLUE),
- new NotificationProgressDrawable.Segment(190, 215, fadedBlue, true),
- new NotificationProgressDrawable.Point(219, 231, fadedYellow),
- new NotificationProgressDrawable.Segment(235, 300, fadedBlue, true)));
+ new NotificationProgressDrawable.Segment(190, 215, Color.BLUE),
+ new NotificationProgressDrawable.Point(219, 231, Color.YELLOW),
+ new NotificationProgressDrawable.Segment(235, 300, Color.BLUE)));
assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ // Colors with 40% opacity
+ int fadedBlue = 0x660000FF;
+ int fadedYellow = 0x66FFFF00;
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Segment(0, 34.219177F, Color.BLUE),
+ new NotificationProgressDrawable.Point(38.219177F, 50.219177F, Color.RED),
+ new NotificationProgressDrawable.Segment(54.219177F, 70.21918F, Color.BLUE),
+ new NotificationProgressDrawable.Point(74.21918F, 86.21918F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(90.21918F, 172.38356F, Color.BLUE),
+ new NotificationProgressDrawable.Point(176.38356F, 188.38356F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(192.38356F, 217.0137F, fadedBlue,
+ true),
+ new NotificationProgressDrawable.Point(221.0137F, 233.0137F, fadedYellow),
+ new NotificationProgressDrawable.Segment(237.0137F, 300F, fadedBlue,
+ true)));
+
+ assertThat(p.second).isEqualTo(182.38356F);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
@Test
@@ -360,10 +429,6 @@ public class NotificationProgressBarTest {
List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
progress, progressMax);
- // Colors with 40% opacity
- int fadedGreen = 0x6600FF00;
- int fadedYellow = 0x66FFFF00;
-
List<Part> expectedParts = new ArrayList<>(List.of(
new Segment(0.15f, Color.RED),
new Point(Color.RED),
@@ -383,12 +448,10 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- float progressX = 180;
- boolean isStyledByProgress = true;
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
List.of(new NotificationProgressDrawable.Segment(0, 35, Color.RED),
@@ -398,11 +461,41 @@ public class NotificationProgressBarTest {
new NotificationProgressDrawable.Segment(85, 146, Color.RED),
new NotificationProgressDrawable.Segment(150, 170, Color.GREEN),
new NotificationProgressDrawable.Point(174, 186, Color.BLUE),
- new NotificationProgressDrawable.Segment(190, 215, fadedGreen, true),
- new NotificationProgressDrawable.Point(219, 231, fadedYellow),
- new NotificationProgressDrawable.Segment(235, 300, fadedGreen, true)));
+ new NotificationProgressDrawable.Segment(190, 215, Color.GREEN),
+ new NotificationProgressDrawable.Point(219, 231, Color.YELLOW),
+ new NotificationProgressDrawable.Segment(235, 300, Color.GREEN)));
assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ // Colors with 40% opacity
+ int fadedGreen = 0x6600FF00;
+ int fadedYellow = 0x66FFFF00;
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Segment(0, 34.095238F, Color.RED),
+ new NotificationProgressDrawable.Point(38.095238F, 50.095238F, Color.RED),
+ new NotificationProgressDrawable.Segment(54.095238F, 70.09524F, Color.RED),
+ new NotificationProgressDrawable.Point(74.09524F, 86.09524F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(90.09524F, 148.9524F, Color.RED),
+ new NotificationProgressDrawable.Segment(152.95238F, 172.7619F,
+ Color.GREEN),
+ new NotificationProgressDrawable.Point(176.7619F, 188.7619F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(192.7619F, 217.33333F,
+ fadedGreen, true),
+ new NotificationProgressDrawable.Point(221.33333F, 233.33333F,
+ fadedYellow),
+ new NotificationProgressDrawable.Segment(237.33333F, 299.99997F,
+ fadedGreen, true)));
+
+ assertThat(p.second).isEqualTo(182.7619F);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
@Test
@@ -437,12 +530,11 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- float progressX = 180;
- boolean isStyledByProgress = false;
+
List<NotificationProgressDrawable.Part> drawableParts =
NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
- segSegGap, segPointGap, pointRadius, hasTrackerIcon, progressX,
- isStyledByProgress);
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
List.of(new NotificationProgressDrawable.Segment(0, 35, Color.RED),
@@ -455,5 +547,213 @@ public class NotificationProgressBarTest {
new NotificationProgressDrawable.Segment(235, 300, Color.GREEN)));
assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = false;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 300,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Segment(0, 34.296295F, Color.RED),
+ new NotificationProgressDrawable.Point(38.296295F, 50.296295F, Color.RED),
+ new NotificationProgressDrawable.Segment(54.296295F, 70.296295F, Color.RED),
+ new NotificationProgressDrawable.Point(74.296295F, 86.296295F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(90.296295F, 149.62962F, Color.RED),
+ new NotificationProgressDrawable.Segment(153.62962F, 216.8148F,
+ Color.GREEN),
+ new NotificationProgressDrawable.Point(220.81482F, 232.81482F,
+ Color.YELLOW),
+ new NotificationProgressDrawable.Segment(236.81482F, 300, Color.GREEN)));
+
+ assertThat(p.second).isEqualTo(182.9037F);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
+ }
+
+ // The only difference from the `zeroWidthDrawableSegment` test below is the longer
+ // segmentMinWidth (= 16dp).
+ @Test
+ public void maybeStretchAndRescaleSegments_negativeWidthDrawableSegment() {
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(200).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(300).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(400).setColor(Color.BLUE));
+ List<ProgressStyle.Point> points = new ArrayList<>();
+ points.add(new ProgressStyle.Point(0).setColor(Color.BLUE));
+ int progress = 1000;
+ int progressMax = 1000;
+
+ List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(
+ segments, points, progress, progressMax);
+
+ List<Part> expectedParts = new ArrayList<>(List.of(
+ new Point(Color.BLUE),
+ new Segment(0.1f, Color.BLUE),
+ new Segment(0.2f, Color.BLUE),
+ new Segment(0.3f, Color.BLUE),
+ new Segment(0.4f, Color.BLUE)));
+
+ assertThat(parts).isEqualTo(expectedParts);
+
+ float drawableWidth = 200;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+ List<NotificationProgressDrawable.Part> drawableParts =
+ NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
+
+ List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Point(0, 12, Color.BLUE),
+ new NotificationProgressDrawable.Segment(16, 16, Color.BLUE),
+ new NotificationProgressDrawable.Segment(20, 56, Color.BLUE),
+ new NotificationProgressDrawable.Segment(60, 116, Color.BLUE),
+ new NotificationProgressDrawable.Segment(120, 200, Color.BLUE)));
+
+ assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 200,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Point(0, 12, Color.BLUE),
+ new NotificationProgressDrawable.Segment(16, 32, Color.BLUE),
+ new NotificationProgressDrawable.Segment(36, 69.41936F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(73.41936F, 124.25807F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(128.25807F, 200, Color.BLUE)));
+
+ assertThat(p.second).isEqualTo(200);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
+ }
+
+ // The only difference from the `negativeWidthDrawableSegment` test above is the shorter
+ // segmentMinWidth (= 10dp).
+ @Test
+ public void maybeStretchAndRescaleSegments_zeroWidthDrawableSegment() {
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(200).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(300).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(400).setColor(Color.BLUE));
+ List<ProgressStyle.Point> points = new ArrayList<>();
+ points.add(new ProgressStyle.Point(0).setColor(Color.BLUE));
+ int progress = 1000;
+ int progressMax = 1000;
+
+ List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(
+ segments, points, progress, progressMax);
+
+ List<Part> expectedParts = new ArrayList<>(List.of(
+ new Point(Color.BLUE),
+ new Segment(0.1f, Color.BLUE),
+ new Segment(0.2f, Color.BLUE),
+ new Segment(0.3f, Color.BLUE),
+ new Segment(0.4f, Color.BLUE)));
+
+ assertThat(parts).isEqualTo(expectedParts);
+
+ float drawableWidth = 200;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+ List<NotificationProgressDrawable.Part> drawableParts =
+ NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
+
+ List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Point(0, 12, Color.BLUE),
+ new NotificationProgressDrawable.Segment(16, 16, Color.BLUE),
+ new NotificationProgressDrawable.Segment(20, 56, Color.BLUE),
+ new NotificationProgressDrawable.Segment(60, 116, Color.BLUE),
+ new NotificationProgressDrawable.Segment(120, 200, Color.BLUE)));
+
+ assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 10;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 200,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Point(0, 12, Color.BLUE),
+ new NotificationProgressDrawable.Segment(16, 26, Color.BLUE),
+ new NotificationProgressDrawable.Segment(30, 64.169014F, Color.BLUE),
+ new NotificationProgressDrawable.Segment(68.169014F, 120.92958F,
+ Color.BLUE),
+ new NotificationProgressDrawable.Segment(124.92958F, 200, Color.BLUE)));
+
+ assertThat(p.second).isEqualTo(200);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
+ }
+
+ @Test
+ public void maybeStretchAndRescaleSegments_noStretchingNecessary() {
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(200).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(300).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(400).setColor(Color.BLUE));
+ List<ProgressStyle.Point> points = new ArrayList<>();
+ points.add(new ProgressStyle.Point(0).setColor(Color.BLUE));
+ int progress = 1000;
+ int progressMax = 1000;
+
+ List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(
+ segments, points, progress, progressMax);
+
+ List<Part> expectedParts = new ArrayList<>(List.of(
+ new Point(Color.BLUE),
+ new Segment(0.2f, Color.BLUE),
+ new Segment(0.1f, Color.BLUE),
+ new Segment(0.3f, Color.BLUE),
+ new Segment(0.4f, Color.BLUE)));
+
+ assertThat(parts).isEqualTo(expectedParts);
+
+ float drawableWidth = 200;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+
+ List<NotificationProgressDrawable.Part> drawableParts =
+ NotificationProgressBar.processAndConvertToDrawableParts(parts, drawableWidth,
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon
+ );
+
+ List<NotificationProgressDrawable.Part> expectedDrawableParts = new ArrayList<>(
+ List.of(new NotificationProgressDrawable.Point(0, 12, Color.BLUE),
+ new NotificationProgressDrawable.Segment(16, 36, Color.BLUE),
+ new NotificationProgressDrawable.Segment(40, 56, Color.BLUE),
+ new NotificationProgressDrawable.Segment(60, 116, Color.BLUE),
+ new NotificationProgressDrawable.Segment(120, 200, Color.BLUE)));
+
+ assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 10;
+ boolean isStyledByProgress = true;
+
+ Pair<List<NotificationProgressDrawable.Part>, Float> p =
+ NotificationProgressBar.maybeStretchAndRescaleSegments(parts, drawableParts,
+ segmentMinWidth, pointRadius, (float) progress / progressMax, 200,
+ isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ assertThat(p.second).isEqualTo(200);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
}
}