Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b3d3af3 authored by Xiaowen Lei's avatar Xiaowen Lei
Browse files

Implement ProgressStyle indeterminate animation in GM3 style.

Animation per GM3 spec + updated stroke widths for ProgressStyle.

Mostly implemented via an AVD xml (despite its limitations). Registered
an AnimationCallback in NotificationProgressBar.java - this is necessary
to loop the "sequentially" AminatorSet defined in the xml.

Flag: android.app.api_rich_ongoing
Fix: 375239156
Test: Post ProgressStyle indeterminate notifs via test app
Change-Id: I3c02bbe003ca01e75b45cb7b946413d3e6cdc573
parent 014ffc85
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.graphics.drawable.LayerDrawable;
@@ -66,6 +68,8 @@ public final class NotificationProgressBar extends ProgressBar implements
    private static final boolean DEBUG = false;
    private static final float FADED_OPACITY = 0.5f;

    private Animatable2.AnimationCallback mIndeterminateAnimationCallback = null;

    private NotificationProgressDrawable mNotificationProgressDrawable;
    private final Rect mProgressDrawableBounds = new Rect();

@@ -150,6 +154,38 @@ public final class NotificationProgressBar extends ProgressBar implements
                0);
    }

    @Override
    public void setIndeterminateDrawable(Drawable d) {
        final Drawable oldDrawable = getIndeterminateDrawable();
        if (oldDrawable != d) {
            if (mIndeterminateAnimationCallback != null) {
                ((AnimatedVectorDrawable) oldDrawable).unregisterAnimationCallback(
                        mIndeterminateAnimationCallback);
                mIndeterminateAnimationCallback = null;
            }
            if (d instanceof AnimatedVectorDrawable) {
                mIndeterminateAnimationCallback = new Animatable2.AnimationCallback() {
                    @Override
                    public void onAnimationEnd(Drawable drawable) {
                        super.onAnimationEnd(drawable);

                        if (shouldLoopIndeterminateAnimation()) {
                            ((AnimatedVectorDrawable) drawable).start();
                        }
                    }
                };
                ((AnimatedVectorDrawable) d).registerAnimationCallback(
                        mIndeterminateAnimationCallback);
            }
        }

        super.setIndeterminateDrawable(d);
    }

    private boolean shouldLoopIndeterminateAnimation() {
        return isIndeterminate() && isAttachedToWindow() && isAggregatedVisible();
    }

    /**
     * Setter for the notification progress model.
     *
+167 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2025 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.
-->

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:drawable="@drawable/vector_notification_progress_indeterminate_horizontal">
    <target android:name="track_behind">
        <aapt:attr name="android:animation">
            <set android:ordering="sequentially">
                <objectAnimator
                    android:duration="800"
                    android:propertyName="trimPathEnd"
                    android:startOffset="400"
                    android:valueFrom="0"
                    android:valueTo="0.51"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,0.15 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="200"
                    android:propertyName="trimPathEnd"
                    android:valueFrom="0.51"
                    android:valueTo="0.98"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="100"
                    android:propertyName="trimPathEnd"
                    android:valueFrom="0.98"
                    android:valueTo="1"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.5 0.833,0.833 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
            </set>
        </aapt:attr>
    </target>
    <target android:name="progress">
        <aapt:attr name="android:animation">
            <set android:ordering="sequentially">
                <objectAnimator
                    android:duration="200"
                    android:propertyName="trimPathStart"
                    android:startOffset="200"
                    android:valueFrom="0"
                    android:valueTo="0.02"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.963,0.8 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="800"
                    android:propertyName="trimPathStart"
                    android:valueFrom="0.02"
                    android:valueTo="0.53"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,0.15 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="200"
                    android:propertyName="trimPathStart"
                    android:valueFrom="0.53"
                    android:valueTo="1"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.2,1 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
            </set>
        </aapt:attr>
    </target>
    <target android:name="progress">
        <aapt:attr name="android:animation">
            <set android:ordering="sequentially">
                <objectAnimator
                    android:duration="200"
                    android:propertyName="trimPathEnd"
                    android:startOffset="200"
                    android:valueFrom="0"
                    android:valueTo="0.024"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.963,0.834 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="800"
                    android:propertyName="trimPathEnd"
                    android:valueFrom="0.024"
                    android:valueTo="0.98"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,0.15 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="30"
                    android:propertyName="trimPathEnd"
                    android:valueFrom="0.98"
                    android:valueTo="1"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
            </set>
        </aapt:attr>
    </target>
    <target android:name="track_ahead">
        <aapt:attr name="android:animation">
            <set android:ordering="sequentially">
                <objectAnimator
                    android:duration="200"
                    android:propertyName="trimPathStart"
                    android:valueFrom="0"
                    android:valueTo="0.02"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="200"
                    android:propertyName="trimPathStart"
                    android:valueFrom="0.02"
                    android:valueTo="0.044000000000000004"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.963,0.834 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
                <objectAnimator
                    android:duration="800"
                    android:propertyName="trimPathStart"
                    android:valueFrom="0.044000000000000004"
                    android:valueTo="1"
                    android:valueType="floatType">
                    <aapt:attr name="android:interpolator">
                        <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,0.15 1.0,1.0" />
                    </aapt:attr>
                </objectAnimator>
            </set>
        </aapt:attr>
    </target>
</animated-vector>
 No newline at end of file
+59 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2025 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.
-->

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="300dp"
    android:height="20dp"
    android:viewportHeight="16"
    android:viewportWidth="300">
    <group
        android:name="root"
        android:translateX="150"
        android:translateY="8">
        <path
            android:name="track_ahead"
            android:pathData="M -147,0.0 L 147,0.0"
            android:strokeAlpha="0.5"
            android:strokeColor="?attr/colorControlActivated"
            android:strokeLineCap="round"
            android:strokeLineJoin="round"
            android:strokeWidth="2"
            android:trimPathEnd="1"
            android:trimPathOffset="0"
            android:trimPathStart="0" />
        <path
            android:name="progress"
            android:pathData="M -147,0.0 L 147,0.0"
            android:strokeColor="?attr/colorControlActivated"
            android:strokeLineCap="round"
            android:strokeLineJoin="round"
            android:strokeWidth="6"
            android:trimPathEnd="0"
            android:trimPathOffset="0"
            android:trimPathStart="0" />
        <path
            android:name="track_behind"
            android:pathData="M -147,0.0 L 147,0.0"
            android:strokeAlpha="0.5"
            android:strokeColor="?attr/colorControlActivated"
            android:strokeLineCap="round"
            android:strokeLineJoin="round"
            android:strokeWidth="2"
            android:trimPathEnd="0"
            android:trimPathOffset="0"
            android:trimPathStart="0" />
    </group>
</vector>
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ please see styles_device_defaults.xml.
        <item name="segPointGap">@dimen/notification_progress_segPoint_gap</item>
        <item name="progressDrawable">@drawable/notification_progress</item>
        <item name="trackerHeight">@dimen/notification_progress_tracker_height</item>
        <item name="indeterminateDrawable">@drawable/notification_progress_indeterminate_horizontal_material</item>
    </style>

    <style name="Widget.Material.Notification.Text" parent="Widget.Material.Light.TextView">