Loading core/java/com/android/internal/widget/NotificationProgressBar.java 0 → 100644 +222 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.widget; import android.app.Notification.ProgressStyle; import android.content.Context; import android.util.AttributeSet; import android.widget.ProgressBar; import android.widget.RemoteViews; import androidx.annotation.ColorInt; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.NotificationProgressDrawable.Part; import com.android.internal.widget.NotificationProgressDrawable.Point; import com.android.internal.widget.NotificationProgressDrawable.Segment; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; /** * NotificationProgressBar extends the capabilities of ProgressBar by adding functionalities to * represent Notification ProgressStyle progress, such as for ridesharing and navigation. */ @RemoteViews.RemoteView public class NotificationProgressBar extends ProgressBar { public NotificationProgressBar(Context context) { this(context, null); } public NotificationProgressBar(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.progressBarStyle); } public NotificationProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public NotificationProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * Processes the ProgressStyle data and convert to list of {@code * NotificationProgressDrawable.Part}. */ @VisibleForTesting public static List<Part> processAndConvertToDrawableParts( List<ProgressStyle.Segment> segments, List<ProgressStyle.Point> points, int progress, boolean isStyledByProgress ) { if (segments.isEmpty()) { throw new IllegalArgumentException("List of segments shouldn't be empty"); } for (ProgressStyle.Segment segment : segments) { final int length = segment.getLength(); if (length <= 0) { throw new IllegalArgumentException("Invalid segment length : " + length); } } final int progressMax = segments.stream().mapToInt(ProgressStyle.Segment::getLength).sum(); if (progress < 0 || progress > progressMax) { throw new IllegalArgumentException("Invalid progress : " + progress); } for (ProgressStyle.Point point : points) { final int pos = point.getPosition(); if (pos <= 0 || pos >= progressMax) { throw new IllegalArgumentException("Invalid Point position : " + pos); } } final Map<Integer, ProgressStyle.Segment> startToSegmentMap = generateStartToSegmentMap( segments); final Map<Integer, ProgressStyle.Point> positionToPointMap = generatePositionToPointMap( points); final SortedSet<Integer> sortedPos = generateSortedPositionSet(startToSegmentMap, positionToPointMap, progress, isStyledByProgress); final Map<Integer, ProgressStyle.Segment> startToSplitSegmentMap = splitSegmentsByPointsAndProgress( startToSegmentMap, sortedPos, progressMax); return convertToDrawableParts(startToSplitSegmentMap, positionToPointMap, sortedPos, progress, progressMax, isStyledByProgress); } // Any segment with a point on it gets split by the point. // If isStyledByProgress is true, also split the segment with the progress value in its range. private static Map<Integer, ProgressStyle.Segment> splitSegmentsByPointsAndProgress( Map<Integer, ProgressStyle.Segment> startToSegmentMap, SortedSet<Integer> sortedPos, int progressMax) { int prevSegStart = 0; for (Integer pos : sortedPos) { if (pos == 0 || pos == progressMax) continue; if (startToSegmentMap.containsKey(pos)) { prevSegStart = pos; continue; } final ProgressStyle.Segment prevSeg = startToSegmentMap.get(prevSegStart); final ProgressStyle.Segment leftSeg = new ProgressStyle.Segment( pos - prevSegStart).setColor( prevSeg.getColor()); final ProgressStyle.Segment rightSeg = new ProgressStyle.Segment( prevSegStart + prevSeg.getLength() - pos).setColor(prevSeg.getColor()); startToSegmentMap.put(prevSegStart, leftSeg); startToSegmentMap.put(pos, rightSeg); prevSegStart = pos; } return startToSegmentMap; } private static List<Part> convertToDrawableParts( Map<Integer, ProgressStyle.Segment> startToSegmentMap, Map<Integer, ProgressStyle.Point> positionToPointMap, SortedSet<Integer> sortedPos, int progress, int progressMax, boolean isStyledByProgress ) { List<Part> parts = new ArrayList<>(); boolean styleRemainingParts = false; for (Integer pos : sortedPos) { if (positionToPointMap.containsKey(pos)) { final ProgressStyle.Point point = positionToPointMap.get(pos); final int color = maybeGetFadedColor(point.getColor(), styleRemainingParts); parts.add(new Point(null, color, styleRemainingParts)); } // We want the Point at the current progress to be filled (not faded), but a Segment // starting at this progress to be faded. if (isStyledByProgress && !styleRemainingParts && pos == progress) { styleRemainingParts = true; } if (startToSegmentMap.containsKey(pos)) { final ProgressStyle.Segment seg = startToSegmentMap.get(pos); final int color = maybeGetFadedColor(seg.getColor(), styleRemainingParts); parts.add(new Segment( (float) seg.getLength() / progressMax, color, styleRemainingParts)); } } return parts; } @ColorInt private static int maybeGetFadedColor(@ColorInt int color, boolean fade) { if (!fade) return color; return NotificationProgressDrawable.getFadedColor(color); } private static Map<Integer, ProgressStyle.Segment> generateStartToSegmentMap( List<ProgressStyle.Segment> segments) { final Map<Integer, ProgressStyle.Segment> startToSegmentMap = new HashMap<>(); int currentStart = 0; // Initial start position is 0 for (ProgressStyle.Segment segment : segments) { // Use the current start position as the key, and the segment as the value startToSegmentMap.put(currentStart, segment); // Update the start position for the next segment currentStart += segment.getLength(); } return startToSegmentMap; } private static Map<Integer, ProgressStyle.Point> generatePositionToPointMap( List<ProgressStyle.Point> points) { final Map<Integer, ProgressStyle.Point> positionToPointMap = new HashMap<>(); for (ProgressStyle.Point point : points) { positionToPointMap.put(point.getPosition(), point); } return positionToPointMap; } private static SortedSet<Integer> generateSortedPositionSet( Map<Integer, ProgressStyle.Segment> startToSegmentMap, Map<Integer, ProgressStyle.Point> positionToPointMap, int progress, boolean isStyledByProgress) { final SortedSet<Integer> sortedPos = new TreeSet<>(startToSegmentMap.keySet()); sortedPos.addAll(positionToPointMap.keySet()); if (isStyledByProgress) { sortedPos.add(progress); } return sortedPos; } } core/java/com/android/internal/widget/NotificationProgressDrawable.java +88 −9 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; /** * This is used by NotificationProgressBar for displaying a custom background. It composes of Loading Loading @@ -126,7 +127,7 @@ public final class NotificationProgressDrawable extends Drawable { * @see #setStroke(int, int, float, float) */ public void setStrokeDefaultColor(@ColorInt int color) { mState.mStrokeColor = color; mState.setStrokeColor(color); } /** Loading @@ -138,7 +139,7 @@ public final class NotificationProgressDrawable extends Drawable { * @see #mutate() */ public void setPointRectDefaultColor(@ColorInt int color) { mState.mPointRectColor = color; mState.setPointRectColor(color); } private void setStrokeInternal(int width, float dashWidth, float dashGap) { Loading Loading @@ -194,7 +195,7 @@ public final class NotificationProgressDrawable extends Drawable { mStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor : mState.mStrokeColor); mDashedStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor : mState.mStrokeColor); : mState.mFadedStrokeColor); // Leave space for the rounded line cap which extends beyond start/end. final float capWidth = mStrokePaint.getStrokeWidth() / 2F; Loading @@ -220,7 +221,8 @@ public final class NotificationProgressDrawable extends Drawable { mPointRectF.inset(inset, inset); mFillPaint.setColor(point.mColor != Color.TRANSPARENT ? point.mColor : mState.mPointRectColor); : (point.mFaded ? mState.mFadedPointRectColor : mState.mPointRectColor)); canvas.drawRoundRect(mPointRectF, cornerRadius, cornerRadius, mFillPaint); } Loading Loading @@ -424,8 +426,9 @@ public final class NotificationProgressDrawable extends Drawable { state.mPointRectCornerRadius = a.getDimension( R.styleable.NotificationProgressDrawablePoints_cornerRadius, state.mPointRectCornerRadius); state.mPointRectColor = a.getColor(R.styleable.NotificationProgressDrawablePoints_color, final int color = a.getColor(R.styleable.NotificationProgressDrawablePoints_color, state.mPointRectColor); setPointRectDefaultColor(color); } static int resolveDensity(@Nullable Resources r, int parentDensity) { Loading Loading @@ -478,7 +481,6 @@ public final class NotificationProgressDrawable extends Drawable { * {@link Point} with zero length. */ public interface Part { } /** Loading Loading @@ -521,6 +523,24 @@ public final class NotificationProgressDrawable extends Drawable { return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", dashed=" + this.mDashed + ')'; } // Needed for unit tests @Override public boolean equals(@Nullable Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; Segment that = (Segment) other; if (Float.compare(this.mFraction, that.mFraction) != 0) return false; if (this.mColor != that.mColor) return false; return this.mDashed == that.mDashed; } @Override public int hashCode() { return Objects.hash(mFraction, mColor, mDashed); } } /** Loading @@ -532,14 +552,21 @@ public final class NotificationProgressDrawable extends Drawable { @Nullable private final Drawable mIcon; @ColorInt private final int mColor; private final boolean mFaded; public Point(@Nullable Drawable icon) { this(icon, Color.TRANSPARENT); this(icon, Color.TRANSPARENT, false); } public Point(@Nullable Drawable icon, @ColorInt int color) { this(icon, color, false); } public Point(@Nullable Drawable icon, @ColorInt int color, boolean faded) { mIcon = icon; mColor = color; mFaded = faded; } @Nullable Loading @@ -547,9 +574,37 @@ public final class NotificationProgressDrawable extends Drawable { return this.mIcon; } public int getColor() { return this.mColor; } public boolean getFaded() { return this.mFaded; } @Override public String toString() { return "Point(icon=" + this.mIcon + ", color=" + this.mColor + ')'; return "Point(icon=" + this.mIcon + ", color=" + this.mColor + ", faded=" + this.mFaded + ")"; } // Needed for unit tests. @Override public boolean equals(@Nullable Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; Point that = (Point) other; if (!Objects.equals(this.mIcon, that.mIcon)) return false; if (this.mColor != that.mColor) return false; return this.mFaded == that.mFaded; } @Override public int hashCode() { return Objects.hash(mIcon, mColor, mFaded); } } Loading @@ -576,12 +631,14 @@ public final class NotificationProgressDrawable extends Drawable { float mSegPointGap = 0.0f; int mStrokeWidth = 0; int mStrokeColor; int mFadedStrokeColor; float mStrokeDashWidth = 0.0f; float mStrokeDashGap = 0.0f; float mPointRadius; float mPointRectInset; float mPointRectCornerRadius; int mPointRectColor; int mFadedPointRectColor; int[] mThemeAttrs; int[] mThemeAttrsSegments; Loading @@ -595,6 +652,7 @@ public final class NotificationProgressDrawable extends Drawable { State(@NonNull State orig, @Nullable Resources res) { mChangingConfigurations = orig.mChangingConfigurations; mStrokeColor = orig.mStrokeColor; mFadedStrokeColor = orig.mFadedStrokeColor; mStrokeWidth = orig.mStrokeWidth; mStrokeDashWidth = orig.mStrokeDashWidth; mStrokeDashGap = orig.mStrokeDashGap; Loading @@ -602,6 +660,7 @@ public final class NotificationProgressDrawable extends Drawable { mPointRectInset = orig.mPointRectInset; mPointRectCornerRadius = orig.mPointRectCornerRadius; mPointRectColor = orig.mPointRectColor; mFadedPointRectColor = orig.mFadedPointRectColor; mThemeAttrs = orig.mThemeAttrs; mThemeAttrsSegments = orig.mThemeAttrsSegments; Loading Loading @@ -683,10 +742,30 @@ public final class NotificationProgressDrawable extends Drawable { public void setStroke(int width, int color, float dashWidth, float dashGap) { mStrokeWidth = width; mStrokeColor = color; mStrokeDashWidth = dashWidth; mStrokeDashGap = dashGap; setStrokeColor(color); } public void setStrokeColor(int color) { mStrokeColor = color; mFadedStrokeColor = getFadedColor(color); } public void setPointRectColor(int color) { mPointRectColor = color; mFadedPointRectColor = getFadedColor(color); } } /** * Get a color with an opacity that's 50% of the input color. */ @ColorInt static int getFadedColor(@ColorInt int color) { return Color.argb(Color.alpha(color) / 2, Color.red(color), Color.green(color), Color.blue(color)); } @Override Loading core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java 0 → 100644 +302 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/com/android/internal/widget/NotificationProgressBar.java 0 → 100644 +222 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.widget; import android.app.Notification.ProgressStyle; import android.content.Context; import android.util.AttributeSet; import android.widget.ProgressBar; import android.widget.RemoteViews; import androidx.annotation.ColorInt; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.NotificationProgressDrawable.Part; import com.android.internal.widget.NotificationProgressDrawable.Point; import com.android.internal.widget.NotificationProgressDrawable.Segment; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; /** * NotificationProgressBar extends the capabilities of ProgressBar by adding functionalities to * represent Notification ProgressStyle progress, such as for ridesharing and navigation. */ @RemoteViews.RemoteView public class NotificationProgressBar extends ProgressBar { public NotificationProgressBar(Context context) { this(context, null); } public NotificationProgressBar(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.progressBarStyle); } public NotificationProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public NotificationProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * Processes the ProgressStyle data and convert to list of {@code * NotificationProgressDrawable.Part}. */ @VisibleForTesting public static List<Part> processAndConvertToDrawableParts( List<ProgressStyle.Segment> segments, List<ProgressStyle.Point> points, int progress, boolean isStyledByProgress ) { if (segments.isEmpty()) { throw new IllegalArgumentException("List of segments shouldn't be empty"); } for (ProgressStyle.Segment segment : segments) { final int length = segment.getLength(); if (length <= 0) { throw new IllegalArgumentException("Invalid segment length : " + length); } } final int progressMax = segments.stream().mapToInt(ProgressStyle.Segment::getLength).sum(); if (progress < 0 || progress > progressMax) { throw new IllegalArgumentException("Invalid progress : " + progress); } for (ProgressStyle.Point point : points) { final int pos = point.getPosition(); if (pos <= 0 || pos >= progressMax) { throw new IllegalArgumentException("Invalid Point position : " + pos); } } final Map<Integer, ProgressStyle.Segment> startToSegmentMap = generateStartToSegmentMap( segments); final Map<Integer, ProgressStyle.Point> positionToPointMap = generatePositionToPointMap( points); final SortedSet<Integer> sortedPos = generateSortedPositionSet(startToSegmentMap, positionToPointMap, progress, isStyledByProgress); final Map<Integer, ProgressStyle.Segment> startToSplitSegmentMap = splitSegmentsByPointsAndProgress( startToSegmentMap, sortedPos, progressMax); return convertToDrawableParts(startToSplitSegmentMap, positionToPointMap, sortedPos, progress, progressMax, isStyledByProgress); } // Any segment with a point on it gets split by the point. // If isStyledByProgress is true, also split the segment with the progress value in its range. private static Map<Integer, ProgressStyle.Segment> splitSegmentsByPointsAndProgress( Map<Integer, ProgressStyle.Segment> startToSegmentMap, SortedSet<Integer> sortedPos, int progressMax) { int prevSegStart = 0; for (Integer pos : sortedPos) { if (pos == 0 || pos == progressMax) continue; if (startToSegmentMap.containsKey(pos)) { prevSegStart = pos; continue; } final ProgressStyle.Segment prevSeg = startToSegmentMap.get(prevSegStart); final ProgressStyle.Segment leftSeg = new ProgressStyle.Segment( pos - prevSegStart).setColor( prevSeg.getColor()); final ProgressStyle.Segment rightSeg = new ProgressStyle.Segment( prevSegStart + prevSeg.getLength() - pos).setColor(prevSeg.getColor()); startToSegmentMap.put(prevSegStart, leftSeg); startToSegmentMap.put(pos, rightSeg); prevSegStart = pos; } return startToSegmentMap; } private static List<Part> convertToDrawableParts( Map<Integer, ProgressStyle.Segment> startToSegmentMap, Map<Integer, ProgressStyle.Point> positionToPointMap, SortedSet<Integer> sortedPos, int progress, int progressMax, boolean isStyledByProgress ) { List<Part> parts = new ArrayList<>(); boolean styleRemainingParts = false; for (Integer pos : sortedPos) { if (positionToPointMap.containsKey(pos)) { final ProgressStyle.Point point = positionToPointMap.get(pos); final int color = maybeGetFadedColor(point.getColor(), styleRemainingParts); parts.add(new Point(null, color, styleRemainingParts)); } // We want the Point at the current progress to be filled (not faded), but a Segment // starting at this progress to be faded. if (isStyledByProgress && !styleRemainingParts && pos == progress) { styleRemainingParts = true; } if (startToSegmentMap.containsKey(pos)) { final ProgressStyle.Segment seg = startToSegmentMap.get(pos); final int color = maybeGetFadedColor(seg.getColor(), styleRemainingParts); parts.add(new Segment( (float) seg.getLength() / progressMax, color, styleRemainingParts)); } } return parts; } @ColorInt private static int maybeGetFadedColor(@ColorInt int color, boolean fade) { if (!fade) return color; return NotificationProgressDrawable.getFadedColor(color); } private static Map<Integer, ProgressStyle.Segment> generateStartToSegmentMap( List<ProgressStyle.Segment> segments) { final Map<Integer, ProgressStyle.Segment> startToSegmentMap = new HashMap<>(); int currentStart = 0; // Initial start position is 0 for (ProgressStyle.Segment segment : segments) { // Use the current start position as the key, and the segment as the value startToSegmentMap.put(currentStart, segment); // Update the start position for the next segment currentStart += segment.getLength(); } return startToSegmentMap; } private static Map<Integer, ProgressStyle.Point> generatePositionToPointMap( List<ProgressStyle.Point> points) { final Map<Integer, ProgressStyle.Point> positionToPointMap = new HashMap<>(); for (ProgressStyle.Point point : points) { positionToPointMap.put(point.getPosition(), point); } return positionToPointMap; } private static SortedSet<Integer> generateSortedPositionSet( Map<Integer, ProgressStyle.Segment> startToSegmentMap, Map<Integer, ProgressStyle.Point> positionToPointMap, int progress, boolean isStyledByProgress) { final SortedSet<Integer> sortedPos = new TreeSet<>(startToSegmentMap.keySet()); sortedPos.addAll(positionToPointMap.keySet()); if (isStyledByProgress) { sortedPos.add(progress); } return sortedPos; } }
core/java/com/android/internal/widget/NotificationProgressDrawable.java +88 −9 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; /** * This is used by NotificationProgressBar for displaying a custom background. It composes of Loading Loading @@ -126,7 +127,7 @@ public final class NotificationProgressDrawable extends Drawable { * @see #setStroke(int, int, float, float) */ public void setStrokeDefaultColor(@ColorInt int color) { mState.mStrokeColor = color; mState.setStrokeColor(color); } /** Loading @@ -138,7 +139,7 @@ public final class NotificationProgressDrawable extends Drawable { * @see #mutate() */ public void setPointRectDefaultColor(@ColorInt int color) { mState.mPointRectColor = color; mState.setPointRectColor(color); } private void setStrokeInternal(int width, float dashWidth, float dashGap) { Loading Loading @@ -194,7 +195,7 @@ public final class NotificationProgressDrawable extends Drawable { mStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor : mState.mStrokeColor); mDashedStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor : mState.mStrokeColor); : mState.mFadedStrokeColor); // Leave space for the rounded line cap which extends beyond start/end. final float capWidth = mStrokePaint.getStrokeWidth() / 2F; Loading @@ -220,7 +221,8 @@ public final class NotificationProgressDrawable extends Drawable { mPointRectF.inset(inset, inset); mFillPaint.setColor(point.mColor != Color.TRANSPARENT ? point.mColor : mState.mPointRectColor); : (point.mFaded ? mState.mFadedPointRectColor : mState.mPointRectColor)); canvas.drawRoundRect(mPointRectF, cornerRadius, cornerRadius, mFillPaint); } Loading Loading @@ -424,8 +426,9 @@ public final class NotificationProgressDrawable extends Drawable { state.mPointRectCornerRadius = a.getDimension( R.styleable.NotificationProgressDrawablePoints_cornerRadius, state.mPointRectCornerRadius); state.mPointRectColor = a.getColor(R.styleable.NotificationProgressDrawablePoints_color, final int color = a.getColor(R.styleable.NotificationProgressDrawablePoints_color, state.mPointRectColor); setPointRectDefaultColor(color); } static int resolveDensity(@Nullable Resources r, int parentDensity) { Loading Loading @@ -478,7 +481,6 @@ public final class NotificationProgressDrawable extends Drawable { * {@link Point} with zero length. */ public interface Part { } /** Loading Loading @@ -521,6 +523,24 @@ public final class NotificationProgressDrawable extends Drawable { return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", dashed=" + this.mDashed + ')'; } // Needed for unit tests @Override public boolean equals(@Nullable Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; Segment that = (Segment) other; if (Float.compare(this.mFraction, that.mFraction) != 0) return false; if (this.mColor != that.mColor) return false; return this.mDashed == that.mDashed; } @Override public int hashCode() { return Objects.hash(mFraction, mColor, mDashed); } } /** Loading @@ -532,14 +552,21 @@ public final class NotificationProgressDrawable extends Drawable { @Nullable private final Drawable mIcon; @ColorInt private final int mColor; private final boolean mFaded; public Point(@Nullable Drawable icon) { this(icon, Color.TRANSPARENT); this(icon, Color.TRANSPARENT, false); } public Point(@Nullable Drawable icon, @ColorInt int color) { this(icon, color, false); } public Point(@Nullable Drawable icon, @ColorInt int color, boolean faded) { mIcon = icon; mColor = color; mFaded = faded; } @Nullable Loading @@ -547,9 +574,37 @@ public final class NotificationProgressDrawable extends Drawable { return this.mIcon; } public int getColor() { return this.mColor; } public boolean getFaded() { return this.mFaded; } @Override public String toString() { return "Point(icon=" + this.mIcon + ", color=" + this.mColor + ')'; return "Point(icon=" + this.mIcon + ", color=" + this.mColor + ", faded=" + this.mFaded + ")"; } // Needed for unit tests. @Override public boolean equals(@Nullable Object other) { if (this == other) return true; if (other == null || getClass() != other.getClass()) return false; Point that = (Point) other; if (!Objects.equals(this.mIcon, that.mIcon)) return false; if (this.mColor != that.mColor) return false; return this.mFaded == that.mFaded; } @Override public int hashCode() { return Objects.hash(mIcon, mColor, mFaded); } } Loading @@ -576,12 +631,14 @@ public final class NotificationProgressDrawable extends Drawable { float mSegPointGap = 0.0f; int mStrokeWidth = 0; int mStrokeColor; int mFadedStrokeColor; float mStrokeDashWidth = 0.0f; float mStrokeDashGap = 0.0f; float mPointRadius; float mPointRectInset; float mPointRectCornerRadius; int mPointRectColor; int mFadedPointRectColor; int[] mThemeAttrs; int[] mThemeAttrsSegments; Loading @@ -595,6 +652,7 @@ public final class NotificationProgressDrawable extends Drawable { State(@NonNull State orig, @Nullable Resources res) { mChangingConfigurations = orig.mChangingConfigurations; mStrokeColor = orig.mStrokeColor; mFadedStrokeColor = orig.mFadedStrokeColor; mStrokeWidth = orig.mStrokeWidth; mStrokeDashWidth = orig.mStrokeDashWidth; mStrokeDashGap = orig.mStrokeDashGap; Loading @@ -602,6 +660,7 @@ public final class NotificationProgressDrawable extends Drawable { mPointRectInset = orig.mPointRectInset; mPointRectCornerRadius = orig.mPointRectCornerRadius; mPointRectColor = orig.mPointRectColor; mFadedPointRectColor = orig.mFadedPointRectColor; mThemeAttrs = orig.mThemeAttrs; mThemeAttrsSegments = orig.mThemeAttrsSegments; Loading Loading @@ -683,10 +742,30 @@ public final class NotificationProgressDrawable extends Drawable { public void setStroke(int width, int color, float dashWidth, float dashGap) { mStrokeWidth = width; mStrokeColor = color; mStrokeDashWidth = dashWidth; mStrokeDashGap = dashGap; setStrokeColor(color); } public void setStrokeColor(int color) { mStrokeColor = color; mFadedStrokeColor = getFadedColor(color); } public void setPointRectColor(int color) { mPointRectColor = color; mFadedPointRectColor = getFadedColor(color); } } /** * Get a color with an opacity that's 50% of the input color. */ @ColorInt static int getFadedColor(@ColorInt int color) { return Color.argb(Color.alpha(color) / 2, Color.red(color), Color.green(color), Color.blue(color)); } @Override Loading
core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java 0 → 100644 +302 −0 File added.Preview size limit exceeded, changes collapsed. Show changes