Merge "Add Play/Pause Icon & Background Animations" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4c07041a1b
@@ -14,13 +14,78 @@
|
|||||||
~ See the License for the specific language governing permissions and
|
~ See the License for the specific language governing permissions and
|
||||||
~ limitations under the License
|
~ limitations under the License
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="14dp"
|
xmlns:aapt="http://schemas.android.com/aapt">
|
||||||
android:height="16dp"
|
<aapt:attr name="android:drawable">
|
||||||
android:viewportWidth="14"
|
<vector android:height="24dp"
|
||||||
android:viewportHeight="16">
|
android:width="24dp"
|
||||||
<path
|
android:viewportHeight="24"
|
||||||
android:pathData="M9.1818,15.6363H13.5455V0.3635H9.1818V15.6363ZM0.4546,15.6363H4.8182V0.3635H0.4546V15.6363Z"
|
android:viewportWidth="24">
|
||||||
android:fillColor="#FFFFFF"
|
<group android:name="_R_G">
|
||||||
android:fillType="evenOdd"/>
|
<group android:name="_R_G_L_1_G"
|
||||||
|
android:translateX="12"
|
||||||
|
android:translateY="12.125">
|
||||||
|
<path android:name="_R_G_L_1_G_D_0_P_0"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData=" M-6 7 C-6,7 -2,7 -2,7 C-2,7 -2,-7 -2,-7 C-2,-7 -6,-7 -6,-7 C-6,-7 -6,7 -6,7c "/>
|
||||||
|
</group>
|
||||||
|
<group android:name="_R_G_L_0_G"
|
||||||
|
android:translateX="12"
|
||||||
|
android:translateY="12.125">
|
||||||
|
<path android:name="_R_G_L_0_G_D_0_P_0"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData=" M2 7 C2,7 6,7 6,7 C6,7 6,-0.12 6,-0.12 C6,-0.12 6,-7 6,-7 C6,-7 2,-7 2,-7 C2,-7 2,7 2,7c "/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group android:name="time_group"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
</aapt:attr>
|
||||||
|
<target android:name="_R_G_L_1_G_D_0_P_0">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="pathData"
|
||||||
|
android:duration="333"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="M-6 7 C-6,7 -2,7 -2,7 C-2,7 -2,-7 -2,-7 C-2,-7 -6,-7 -6,-7 C-6,-7 -6,7 -6,7c "
|
||||||
|
android:valueTo="M-6 7 C-6,7 -2,3.94 -2,3.94 C-2,3.94 -2,-4.37 -2,-4.37 C-2,-4.37 -6,-7 -6,-7 C-6,-7 -6,7 -6,7c "
|
||||||
|
android:valueType="pathType">
|
||||||
|
<aapt:attr name="android:interpolator">
|
||||||
|
<pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/>
|
||||||
|
</aapt:attr>
|
||||||
|
</objectAnimator>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
<target android:name="_R_G_L_0_G_D_0_P_0">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="pathData"
|
||||||
|
android:duration="333"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="M2 7 C2,7 6,7 6,7 C6,7 6,-0.12 6,-0.12 C6,-0.12 6,-7 6,-7 C6,-7 2,-7 2,-7 C2,-7 2,7 2,7c "
|
||||||
|
android:valueTo="M-5.62 7 C-5.62,7 -4.75,7 -4.75,7 C-4.75,7 6,-0.12 6,-0.12 C6,-0.12 -4.44,-7 -4.44,-7 C-4.44,-7 -5.62,-7 -5.62,-7 C-5.62,-7 -5.62,7 -5.62,7c "
|
||||||
|
android:valueType="pathType">
|
||||||
|
<aapt:attr name="android:interpolator">
|
||||||
|
<pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/>
|
||||||
|
</aapt:attr>
|
||||||
|
</objectAnimator>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
<target android:name="time_group">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="translateX"
|
||||||
|
android:duration="517"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="0"
|
||||||
|
android:valueTo="1"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
</animated-vector>
|
||||||
73
packages/SystemUI/res/drawable/ic_media_pause_container.xml
Normal file
73
packages/SystemUI/res/drawable/ic_media_pause_container.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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">
|
||||||
|
<aapt:attr name="android:drawable">
|
||||||
|
<vector android:height="48dp"
|
||||||
|
android:width="48dp"
|
||||||
|
android:viewportHeight="48"
|
||||||
|
android:viewportWidth="48">
|
||||||
|
<group android:name="_R_G">
|
||||||
|
<group android:name="_R_G_L_1_G"
|
||||||
|
android:translateX="24"
|
||||||
|
android:translateY="24"
|
||||||
|
android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5"/>
|
||||||
|
<group android:name="_R_G_L_0_G"
|
||||||
|
android:translateX="24"
|
||||||
|
android:translateY="24"
|
||||||
|
android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5">
|
||||||
|
<path android:name="_R_G_L_0_G_D_0_P_0"
|
||||||
|
android:fillColor="#ffddb3"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData=" M48 -16 C48,-16 48,16 48,16 C48,33.67 33.67,48 16,48 C16,48 -16,48 -16,48 C-33.67,48 -48,33.67 -48,16 C-48,16 -48,-16 -48,-16 C-48,-33.67 -33.67,-48 -16,-48 C-16,-48 16,-48 16,-48 C33.67,-48 48,-33.67 48,-16c "/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group android:name="time_group"/>
|
||||||
|
</vector>
|
||||||
|
</aapt:attr>
|
||||||
|
<target android:name="_R_G_L_0_G_D_0_P_0">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="pathData"
|
||||||
|
android:duration="500"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="M48 -16 C48,-16 48,16 48,16 C48,33.67 33.67,48 16,48 C16,48 -16,48 -16,48 C-33.67,48 -48,33.67 -48,16 C-48,16 -48,-16 -48,-16 C-48,-33.67 -33.67,-48 -16,-48 C-16,-48 16,-48 16,-48 C33.67,-48 48,-33.67 48,-16c "
|
||||||
|
android:valueTo="M48 0.25 C48,0.25 48,0 48,0 C47.75,26 31.25,48 0,48 C0,48 0,48 0,48 C-30,48 -48,25.75 -48,-0.25 C-48,-0.25 -48,-0.25 -48,-0.25 C-47.75,-23.5 -32.25,-47.75 0.5,-48 C0.5,-48 0.5,-48 0.5,-48 C28,-47.75 47.75,-29.75 48,0.25c "
|
||||||
|
android:valueType="pathType">
|
||||||
|
<aapt:attr name="android:interpolator">
|
||||||
|
<pathInterpolator android:pathData="M 0.0,0.0 c0.526,0 0,1 1.0,1.0"/>
|
||||||
|
</aapt:attr>
|
||||||
|
</objectAnimator>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
<target android:name="time_group">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="translateX"
|
||||||
|
android:duration="517"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="0"
|
||||||
|
android:valueTo="1"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
</animated-vector>
|
||||||
@@ -14,13 +14,78 @@
|
|||||||
~ See the License for the specific language governing permissions and
|
~ See the License for the specific language governing permissions and
|
||||||
~ limitations under the License
|
~ limitations under the License
|
||||||
-->
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt">
|
||||||
|
<aapt:attr name="android:drawable">
|
||||||
|
<vector android:height="24dp"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:viewportHeight="24"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24">
|
||||||
android:viewportHeight="24">
|
<group android:name="_R_G">
|
||||||
<path
|
<group android:name="_R_G_L_1_G"
|
||||||
android:pathData="M20,12L6,21V3L20,12ZM15.26,12L8.55,7.68V16.32L15.26,12Z"
|
android:translateX="12"
|
||||||
android:fillColor="#FFFFFF"
|
android:translateY="12.125">
|
||||||
android:fillType="evenOdd"/>
|
<path android:name="_R_G_L_1_G_D_0_P_0"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData=" M-6 7 C-6,7 -2,3.94 -2,3.94 C-2,3.94 -2,-4.37 -2,-4.37 C-2,-4.37 -6,-7 -6,-7 C-6,-7 -6,7 -6,7c "/>
|
||||||
|
</group>
|
||||||
|
<group android:name="_R_G_L_0_G"
|
||||||
|
android:translateX="12"
|
||||||
|
android:translateY="12.125">
|
||||||
|
<path android:name="_R_G_L_0_G_D_0_P_0"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData=" M-5.62 7 C-5.62,7 -4.75,7 -4.75,7 C-4.75,7 6,-0.12 6,-0.12 C6,-0.12 -4.44,-7 -4.44,-7 C-4.44,-7 -5.62,-7 -5.62,-7 C-5.62,-7 -5.62,7 -5.62,7c "/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group android:name="time_group"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
</aapt:attr>
|
||||||
|
<target android:name="_R_G_L_1_G_D_0_P_0">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="pathData"
|
||||||
|
android:duration="333"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="M-6 7 C-6,7 -2,3.94 -2,3.94 C-2,3.94 -2,-4.37 -2,-4.37 C-2,-4.37 -6,-7 -6,-7 C-6,-7 -6,7 -6,7c "
|
||||||
|
android:valueTo="M-6 7 C-6,7 -2,7 -2,7 C-2,7 -2,-7 -2,-7 C-2,-7 -6,-7 -6,-7 C-6,-7 -6,7 -6,7c "
|
||||||
|
android:valueType="pathType">
|
||||||
|
<aapt:attr name="android:interpolator">
|
||||||
|
<pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/>
|
||||||
|
</aapt:attr>
|
||||||
|
</objectAnimator>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
<target android:name="_R_G_L_0_G_D_0_P_0">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="pathData"
|
||||||
|
android:duration="333"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="M-5.62 7 C-5.62,7 -4.75,7 -4.75,7 C-4.75,7 6,-0.12 6,-0.12 C6,-0.12 -4.44,-7 -4.44,-7 C-4.44,-7 -5.62,-7 -5.62,-7 C-5.62,-7 -5.62,7 -5.62,7c "
|
||||||
|
android:valueTo="M2 7 C2,7 6,7 6,7 C6,7 6,-0.12 6,-0.12 C6,-0.12 6,-7 6,-7 C6,-7 2,-7 2,-7 C2,-7 2,7 2,7c "
|
||||||
|
android:valueType="pathType">
|
||||||
|
<aapt:attr name="android:interpolator">
|
||||||
|
<pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/>
|
||||||
|
</aapt:attr>
|
||||||
|
</objectAnimator>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
<target android:name="time_group">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="translateX"
|
||||||
|
android:duration="517"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="0"
|
||||||
|
android:valueTo="1"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
</animated-vector>
|
||||||
68
packages/SystemUI/res/drawable/ic_media_play_container.xml
Normal file
68
packages/SystemUI/res/drawable/ic_media_play_container.xml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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">
|
||||||
|
<aapt:attr name="android:drawable">
|
||||||
|
<vector android:height="48dp"
|
||||||
|
android:width="48dp"
|
||||||
|
android:viewportHeight="48"
|
||||||
|
android:viewportWidth="48">
|
||||||
|
<group android:name="_R_G">
|
||||||
|
<group android:name="_R_G_L_0_G"
|
||||||
|
android:translateX="24"
|
||||||
|
android:translateY="24"
|
||||||
|
android:scaleX="0.5"
|
||||||
|
android:scaleY="0.5">
|
||||||
|
<path android:name="_R_G_L_0_G_D_0_P_0"
|
||||||
|
android:fillColor="#ffddb3"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData=" M48 0.25 C48,0.25 48,0 48,0 C47.75,26 31.25,48 0,48 C0,48 0,48 0,48 C-30,48 -48,25.75 -48,-0.25 C-48,-0.25 -48,-0.25 -48,-0.25 C-47.75,-23.5 -32.25,-47.75 0.5,-48 C0.5,-48 0.5,-48 0.5,-48 C28,-47.75 47.75,-29.75 48,0.25c "/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group android:name="time_group"/>
|
||||||
|
</vector>
|
||||||
|
</aapt:attr>
|
||||||
|
<target android:name="_R_G_L_0_G_D_0_P_0">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="pathData"
|
||||||
|
android:duration="500"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="M48 0.25 C48,0.25 48,0 48,0 C47.75,26 31.25,48 0,48 C0,48 0,48 0,48 C-30,48 -48,25.75 -48,-0.25 C-48,-0.25 -48,-0.25 -48,-0.25 C-47.75,-23.5 -32.25,-47.75 0.5,-48 C0.5,-48 0.5,-48 0.5,-48 C28,-47.75 47.75,-29.75 48,0.25c "
|
||||||
|
android:valueTo="M48 -16 C48,-16 48,16 48,16 C48,33.67 33.67,48 16,48 C16,48 -16,48 -16,48 C-33.67,48 -48,33.67 -48,16 C-48,16 -48,-16 -48,-16 C-48,-33.67 -33.67,-48 -16,-48 C-16,-48 16,-48 16,-48 C33.67,-48 48,-33.67 48,-16c "
|
||||||
|
android:valueType="pathType">
|
||||||
|
<aapt:attr name="android:interpolator">
|
||||||
|
<pathInterpolator android:pathData="M 0.0,0.0 c0.518,0 0,1 1.0,1.0"/>
|
||||||
|
</aapt:attr>
|
||||||
|
</objectAnimator>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
<target android:name="time_group">
|
||||||
|
<aapt:attr name="android:animation">
|
||||||
|
<set android:ordering="together">
|
||||||
|
<objectAnimator android:propertyName="translateX"
|
||||||
|
android:duration="517"
|
||||||
|
android:startOffset="0"
|
||||||
|
android:valueFrom="0"
|
||||||
|
android:valueTo="1"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
</set>
|
||||||
|
</aapt:attr>
|
||||||
|
</target>
|
||||||
|
</animated-vector>
|
||||||
@@ -145,8 +145,7 @@
|
|||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="@dimen/qs_media_padding"
|
android:layout_marginStart="@dimen/qs_media_padding"
|
||||||
android:layout_marginEnd="@dimen/qs_media_padding"
|
android:layout_marginEnd="@dimen/qs_media_padding" />
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- See comment in media_session_collapsed.xml for how these barriers are used -->
|
<!-- See comment in media_session_collapsed.xml for how these barriers are used -->
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
@@ -184,7 +183,7 @@
|
|||||||
<!-- Button visibility will be controlled in code -->
|
<!-- Button visibility will be controlled in code -->
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/actionPrev"
|
android:id="@+id/actionPrev"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="4dp"
|
android:layout_marginStart="4dp"
|
||||||
@@ -211,7 +210,7 @@
|
|||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/actionNext"
|
android:id="@+id/actionNext"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="0dp"
|
android:layout_marginStart="0dp"
|
||||||
@@ -221,7 +220,7 @@
|
|||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/action0"
|
android:id="@+id/action0"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
||||||
@@ -231,7 +230,7 @@
|
|||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/action1"
|
android:id="@+id/action1"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
||||||
@@ -241,7 +240,7 @@
|
|||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/action2"
|
android:id="@+id/action2"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
||||||
@@ -251,7 +250,7 @@
|
|||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/action3"
|
android:id="@+id/action3"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
||||||
@@ -261,7 +260,7 @@
|
|||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/action4"
|
android:id="@+id/action4"
|
||||||
style="@style/MediaPlayer.SessionAction"
|
style="@style/MediaPlayer.SessionAction.Secondary"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
android:layout_marginStart="@dimen/qs_media_action_spacing"
|
||||||
|
|||||||
@@ -616,7 +616,6 @@
|
|||||||
parent="@android:style/Widget.Material.Button.Borderless.Small">
|
parent="@android:style/Widget.Material.Button.Borderless.Small">
|
||||||
<item name="android:background">@drawable/qs_media_light_source</item>
|
<item name="android:background">@drawable/qs_media_light_source</item>
|
||||||
<item name="android:tint">?android:attr/textColorPrimary</item>
|
<item name="android:tint">?android:attr/textColorPrimary</item>
|
||||||
<item name="android:stateListAnimator">@anim/media_button_state_list_animator</item>
|
|
||||||
<item name="android:paddingTop">12dp</item>
|
<item name="android:paddingTop">12dp</item>
|
||||||
<item name="android:paddingStart">12dp</item>
|
<item name="android:paddingStart">12dp</item>
|
||||||
<item name="android:paddingEnd">12dp</item>
|
<item name="android:paddingEnd">12dp</item>
|
||||||
@@ -629,6 +628,10 @@
|
|||||||
<item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
|
<item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="MediaPlayer.SessionAction.Secondary" parent="MediaPlayer.SessionAction">
|
||||||
|
<item name="android:stateListAnimator">@anim/media_button_state_list_animator</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="MediaPlayer.OutlineButton">
|
<style name="MediaPlayer.OutlineButton">
|
||||||
<item name="android:background">@drawable/qs_media_outline_button</item>
|
<item name="android:background">@drawable/qs_media_outline_button</item>
|
||||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
|||||||
@@ -30,13 +30,14 @@ import android.content.res.ColorStateList;
|
|||||||
import android.graphics.ColorMatrix;
|
import android.graphics.ColorMatrix;
|
||||||
import android.graphics.ColorMatrixColorFilter;
|
import android.graphics.ColorMatrixColorFilter;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Animatable;
|
||||||
|
import android.graphics.drawable.Animatable2;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.media.session.MediaController;
|
import android.media.session.MediaController;
|
||||||
import android.media.session.MediaSession;
|
import android.media.session.MediaSession;
|
||||||
import android.media.session.PlaybackState;
|
import android.media.session.PlaybackState;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.text.Layout;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -67,6 +68,7 @@ import com.android.systemui.util.animation.TransitionLayout;
|
|||||||
import com.android.systemui.util.time.SystemClock;
|
import com.android.systemui.util.time.SystemClock;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
@@ -637,9 +639,34 @@ public class MediaControlPanel {
|
|||||||
|
|
||||||
private void setSemanticButton(final ImageButton button, MediaAction mediaAction,
|
private void setSemanticButton(final ImageButton button, MediaAction mediaAction,
|
||||||
ConstraintSet collapsedSet, ConstraintSet expandedSet, boolean showInCompact) {
|
ConstraintSet collapsedSet, ConstraintSet expandedSet, boolean showInCompact) {
|
||||||
|
AnimationBindHandler animHandler;
|
||||||
|
if (button.getTag() == null) {
|
||||||
|
animHandler = new AnimationBindHandler();
|
||||||
|
button.setTag(animHandler);
|
||||||
|
} else {
|
||||||
|
animHandler = (AnimationBindHandler) button.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
animHandler.tryExecute(() -> {
|
||||||
|
bindSemanticButton(animHandler, button, mediaAction,
|
||||||
|
collapsedSet, expandedSet, showInCompact);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindSemanticButton(final AnimationBindHandler animHandler,
|
||||||
|
final ImageButton button, MediaAction mediaAction, ConstraintSet collapsedSet,
|
||||||
|
ConstraintSet expandedSet, boolean showInCompact) {
|
||||||
|
|
||||||
|
animHandler.unregisterAll();
|
||||||
if (mediaAction != null) {
|
if (mediaAction != null) {
|
||||||
button.setImageIcon(mediaAction.getIcon());
|
final Drawable icon = mediaAction.getIcon();
|
||||||
|
button.setImageDrawable(icon);
|
||||||
button.setContentDescription(mediaAction.getContentDescription());
|
button.setContentDescription(mediaAction.getContentDescription());
|
||||||
|
final Drawable bgDrawable = mediaAction.getBackground();
|
||||||
|
button.setBackground(bgDrawable);
|
||||||
|
|
||||||
|
animHandler.tryRegister(icon);
|
||||||
|
animHandler.tryRegister(bgDrawable);
|
||||||
|
|
||||||
Runnable action = mediaAction.getAction();
|
Runnable action = mediaAction.getAction();
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
@@ -651,19 +678,75 @@ public class MediaControlPanel {
|
|||||||
logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
|
logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
|
||||||
/* isRecommendationCard */ false);
|
/* isRecommendationCard */ false);
|
||||||
action.run();
|
action.run();
|
||||||
|
|
||||||
|
if (icon instanceof Animatable) {
|
||||||
|
((Animatable) icon).start();
|
||||||
|
}
|
||||||
|
if (bgDrawable instanceof Animatable) {
|
||||||
|
((Animatable) bgDrawable).start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
button.setImageIcon(null);
|
button.setImageDrawable(null);
|
||||||
button.setContentDescription(null);
|
button.setContentDescription(null);
|
||||||
button.setEnabled(false);
|
button.setEnabled(false);
|
||||||
|
button.setBackground(mContext.getDrawable(R.drawable.qs_media_round_button_background));
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisibleAndAlpha(collapsedSet, button.getId(), mediaAction != null && showInCompact);
|
setVisibleAndAlpha(collapsedSet, button.getId(), mediaAction != null && showInCompact);
|
||||||
setVisibleAndAlpha(expandedSet, button.getId(), mediaAction != null);
|
setVisibleAndAlpha(expandedSet, button.getId(), mediaAction != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class AnimationBindHandler extends Animatable2.AnimationCallback {
|
||||||
|
private ArrayList<Runnable> mOnAnimationsComplete = new ArrayList<>();
|
||||||
|
private ArrayList<Animatable2> mRegistrations = new ArrayList<>();
|
||||||
|
|
||||||
|
public void tryRegister(Drawable drawable) {
|
||||||
|
if (drawable instanceof Animatable2) {
|
||||||
|
Animatable2 anim = (Animatable2) drawable;
|
||||||
|
anim.registerAnimationCallback(this);
|
||||||
|
mRegistrations.add(anim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregisterAll() {
|
||||||
|
for (Animatable2 anim : mRegistrations) {
|
||||||
|
anim.unregisterAnimationCallback(this);
|
||||||
|
}
|
||||||
|
mRegistrations.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAnimationRunning() {
|
||||||
|
for (Animatable2 anim : mRegistrations) {
|
||||||
|
if (anim.isRunning()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryExecute(Runnable action) {
|
||||||
|
if (isAnimationRunning()) {
|
||||||
|
mOnAnimationsComplete.add(action);
|
||||||
|
} else {
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Drawable drawable) {
|
||||||
|
super.onAnimationEnd(drawable);
|
||||||
|
if (!isAnimationRunning()) {
|
||||||
|
for (Runnable action : mOnAnimationsComplete) {
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
mOnAnimationsComplete.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ActivityLaunchAnimator.Controller buildLaunchAnimatorController(
|
private ActivityLaunchAnimator.Controller buildLaunchAnimatorController(
|
||||||
TransitionLayout player) {
|
TransitionLayout player) {
|
||||||
|
|||||||
@@ -170,9 +170,10 @@ data class MediaButton(
|
|||||||
|
|
||||||
/** State of a media action. */
|
/** State of a media action. */
|
||||||
data class MediaAction(
|
data class MediaAction(
|
||||||
val icon: Icon?,
|
val icon: Drawable?,
|
||||||
val action: Runnable?,
|
val action: Runnable?,
|
||||||
val contentDescription: CharSequence?
|
val contentDescription: CharSequence?,
|
||||||
|
val background: Drawable?
|
||||||
)
|
)
|
||||||
|
|
||||||
/** State of the media device. */
|
/** State of the media device. */
|
||||||
|
|||||||
@@ -695,11 +695,12 @@ class MediaDataManager(
|
|||||||
Icon.createWithResource(sbn.packageName, action.getIcon()!!.getResId())
|
Icon.createWithResource(sbn.packageName, action.getIcon()!!.getResId())
|
||||||
} else {
|
} else {
|
||||||
action.getIcon()
|
action.getIcon()
|
||||||
}.setTint(themeText)
|
}.setTint(themeText).loadDrawable(context)
|
||||||
val mediaAction = MediaAction(
|
val mediaAction = MediaAction(
|
||||||
mediaActionIcon,
|
mediaActionIcon,
|
||||||
runnable,
|
runnable,
|
||||||
action.title)
|
action.title,
|
||||||
|
context.getDrawable(R.drawable.qs_media_round_button_background))
|
||||||
actionIcons.add(mediaAction)
|
actionIcons.add(mediaAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,30 +790,34 @@ class MediaDataManager(
|
|||||||
return when (action) {
|
return when (action) {
|
||||||
PlaybackState.ACTION_PLAY -> {
|
PlaybackState.ACTION_PLAY -> {
|
||||||
MediaAction(
|
MediaAction(
|
||||||
Icon.createWithResource(context, R.drawable.ic_media_play),
|
context.getDrawable(R.drawable.ic_media_play),
|
||||||
{ controller.transportControls.play() },
|
{ controller.transportControls.play() },
|
||||||
context.getString(R.string.controls_media_button_play)
|
context.getString(R.string.controls_media_button_play),
|
||||||
|
context.getDrawable(R.drawable.ic_media_play_container)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PlaybackState.ACTION_PAUSE -> {
|
PlaybackState.ACTION_PAUSE -> {
|
||||||
MediaAction(
|
MediaAction(
|
||||||
Icon.createWithResource(context, R.drawable.ic_media_pause),
|
context.getDrawable(R.drawable.ic_media_pause),
|
||||||
{ controller.transportControls.pause() },
|
{ controller.transportControls.pause() },
|
||||||
context.getString(R.string.controls_media_button_pause)
|
context.getString(R.string.controls_media_button_pause),
|
||||||
|
context.getDrawable(R.drawable.ic_media_pause_container)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PlaybackState.ACTION_SKIP_TO_PREVIOUS -> {
|
PlaybackState.ACTION_SKIP_TO_PREVIOUS -> {
|
||||||
MediaAction(
|
MediaAction(
|
||||||
Icon.createWithResource(context, R.drawable.ic_media_prev),
|
context.getDrawable(R.drawable.ic_media_prev),
|
||||||
{ controller.transportControls.skipToPrevious() },
|
{ controller.transportControls.skipToPrevious() },
|
||||||
context.getString(R.string.controls_media_button_prev)
|
context.getString(R.string.controls_media_button_prev),
|
||||||
|
context.getDrawable(R.drawable.qs_media_round_button_background)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PlaybackState.ACTION_SKIP_TO_NEXT -> {
|
PlaybackState.ACTION_SKIP_TO_NEXT -> {
|
||||||
MediaAction(
|
MediaAction(
|
||||||
Icon.createWithResource(context, R.drawable.ic_media_next),
|
context.getDrawable(R.drawable.ic_media_next),
|
||||||
{ controller.transportControls.skipToNext() },
|
{ controller.transportControls.skipToNext() },
|
||||||
context.getString(R.string.controls_media_button_next)
|
context.getString(R.string.controls_media_button_next),
|
||||||
|
context.getDrawable(R.drawable.qs_media_round_button_background)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
@@ -835,9 +840,10 @@ class MediaDataManager(
|
|||||||
|
|
||||||
val it = state.customActions[index]
|
val it = state.customActions[index]
|
||||||
return MediaAction(
|
return MediaAction(
|
||||||
Icon.createWithResource(packageName, it.icon),
|
Icon.createWithResource(packageName, it.icon).loadDrawable(context),
|
||||||
{ controller.transportControls.sendCustomAction(it, it.extras) },
|
{ controller.transportControls.sendCustomAction(it, it.extras) },
|
||||||
it.name
|
it.name,
|
||||||
|
context.getDrawable(R.drawable.ic_media_pause_container)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,9 +906,11 @@ class MediaDataManager(
|
|||||||
|
|
||||||
private fun getResumeMediaAction(action: Runnable): MediaAction {
|
private fun getResumeMediaAction(action: Runnable): MediaAction {
|
||||||
return MediaAction(
|
return MediaAction(
|
||||||
Icon.createWithResource(context, R.drawable.ic_media_play).setTint(themeText),
|
Icon.createWithResource(context, R.drawable.ic_media_play)
|
||||||
|
.setTint(themeText).loadDrawable(context),
|
||||||
action,
|
action,
|
||||||
context.getString(R.string.controls_media_resume)
|
context.getString(R.string.controls_media_resume),
|
||||||
|
context.getDrawable(R.drawable.ic_media_play_container)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ package com.android.systemui.media
|
|||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.Animatable2
|
||||||
|
import android.graphics.drawable.AnimatedVectorDrawable
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.graphics.drawable.Icon
|
|
||||||
import android.graphics.drawable.RippleDrawable
|
import android.graphics.drawable.RippleDrawable
|
||||||
import android.media.MediaMetadata
|
import android.media.MediaMetadata
|
||||||
import android.media.session.MediaSession
|
import android.media.session.MediaSession
|
||||||
@@ -60,6 +61,7 @@ import org.junit.runner.RunWith
|
|||||||
import org.mockito.ArgumentCaptor
|
import org.mockito.ArgumentCaptor
|
||||||
import org.mockito.ArgumentMatchers.anyLong
|
import org.mockito.ArgumentMatchers.anyLong
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.any
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.times
|
import org.mockito.Mockito.times
|
||||||
@@ -290,15 +292,15 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun bindSemanticActions() {
|
fun bindSemanticActions() {
|
||||||
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
|
val icon = context.getDrawable(android.R.drawable.ic_media_play)
|
||||||
|
val bg = context.getDrawable(R.drawable.qs_media_round_button_background)
|
||||||
val semanticActions = MediaButton(
|
val semanticActions = MediaButton(
|
||||||
playOrPause = MediaAction(icon, Runnable {}, "play"),
|
playOrPause = MediaAction(icon, Runnable {}, "play", bg),
|
||||||
nextOrCustom = MediaAction(icon, Runnable {}, "next"),
|
nextOrCustom = MediaAction(icon, Runnable {}, "next", bg),
|
||||||
custom0 = MediaAction(icon, null, "custom 0"),
|
custom0 = MediaAction(icon, null, "custom 0", bg),
|
||||||
custom1 = MediaAction(icon, null, "custom 1")
|
custom1 = MediaAction(icon, null, "custom 1", bg)
|
||||||
)
|
)
|
||||||
val state = mediaData.copy(semanticActions = semanticActions)
|
val state = mediaData.copy(semanticActions = semanticActions)
|
||||||
|
|
||||||
player.attachPlayer(viewHolder)
|
player.attachPlayer(viewHolder)
|
||||||
player.bindPlayer(state, PACKAGE)
|
player.bindPlayer(state, PACKAGE)
|
||||||
|
|
||||||
@@ -338,10 +340,10 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
fun bind_seekBarDisabled_seekBarVisibilityIsSetToInvisible() {
|
fun bind_seekBarDisabled_seekBarVisibilityIsSetToInvisible() {
|
||||||
whenever(seekBarViewModel.getEnabled()).thenReturn(false)
|
whenever(seekBarViewModel.getEnabled()).thenReturn(false)
|
||||||
|
|
||||||
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
|
val icon = context.getDrawable(android.R.drawable.ic_media_play)
|
||||||
val semanticActions = MediaButton(
|
val semanticActions = MediaButton(
|
||||||
playOrPause = MediaAction(icon, Runnable {}, "play"),
|
playOrPause = MediaAction(icon, Runnable {}, "play", null),
|
||||||
nextOrCustom = MediaAction(icon, Runnable {}, "next")
|
nextOrCustom = MediaAction(icon, Runnable {}, "next", null)
|
||||||
)
|
)
|
||||||
val state = mediaData.copy(semanticActions = semanticActions)
|
val state = mediaData.copy(semanticActions = semanticActions)
|
||||||
|
|
||||||
@@ -365,13 +367,14 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun bindNotificationActions() {
|
fun bindNotificationActions() {
|
||||||
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
|
val icon = context.getDrawable(android.R.drawable.ic_media_play)
|
||||||
|
val bg = context.getDrawable(R.drawable.qs_media_round_button_background)
|
||||||
val actions = listOf(
|
val actions = listOf(
|
||||||
MediaAction(icon, Runnable {}, "previous"),
|
MediaAction(icon, Runnable {}, "previous", bg),
|
||||||
MediaAction(icon, Runnable {}, "play"),
|
MediaAction(icon, Runnable {}, "play", bg),
|
||||||
MediaAction(icon, null, "next"),
|
MediaAction(icon, null, "next", bg),
|
||||||
MediaAction(icon, null, "custom 0"),
|
MediaAction(icon, null, "custom 0", bg),
|
||||||
MediaAction(icon, Runnable {}, "custom 1")
|
MediaAction(icon, Runnable {}, "custom 1", bg)
|
||||||
)
|
)
|
||||||
val state = mediaData.copy(actions = actions,
|
val state = mediaData.copy(actions = actions,
|
||||||
actionsToShowInCompact = listOf(1, 2),
|
actionsToShowInCompact = listOf(1, 2),
|
||||||
@@ -412,6 +415,72 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
verify(collapsedSet).setVisibility(R.id.action4, ConstraintSet.GONE)
|
verify(collapsedSet).setVisibility(R.id.action4, ConstraintSet.GONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun bindAnimatedSemanticActions() {
|
||||||
|
val mockAvd0 = mock(AnimatedVectorDrawable::class.java)
|
||||||
|
val mockAvd1 = mock(AnimatedVectorDrawable::class.java)
|
||||||
|
val mockAvd2 = mock(AnimatedVectorDrawable::class.java)
|
||||||
|
whenever(mockAvd0.mutate()).thenReturn(mockAvd0)
|
||||||
|
whenever(mockAvd1.mutate()).thenReturn(mockAvd1)
|
||||||
|
whenever(mockAvd2.mutate()).thenReturn(mockAvd2)
|
||||||
|
|
||||||
|
val icon = context.getDrawable(R.drawable.ic_media_play)
|
||||||
|
val bg = context.getDrawable(R.drawable.ic_media_play_container)
|
||||||
|
val semanticActions0 = MediaButton(
|
||||||
|
playOrPause = MediaAction(mockAvd0, Runnable {}, "play", null))
|
||||||
|
val semanticActions1 = MediaButton(
|
||||||
|
playOrPause = MediaAction(mockAvd1, Runnable {}, "pause", null))
|
||||||
|
val semanticActions2 = MediaButton(
|
||||||
|
playOrPause = MediaAction(mockAvd2, Runnable {}, "loading", null))
|
||||||
|
val state0 = mediaData.copy(semanticActions = semanticActions0)
|
||||||
|
val state1 = mediaData.copy(semanticActions = semanticActions1)
|
||||||
|
val state2 = mediaData.copy(semanticActions = semanticActions2)
|
||||||
|
|
||||||
|
player.attachPlayer(viewHolder)
|
||||||
|
player.bindPlayer(state0, PACKAGE)
|
||||||
|
|
||||||
|
// Validate first binding
|
||||||
|
assertThat(actionPlayPause.isEnabled()).isTrue()
|
||||||
|
assertThat(actionPlayPause.contentDescription).isEqualTo("play")
|
||||||
|
verify(collapsedSet).setVisibility(R.id.actionPlayPause, ConstraintSet.VISIBLE)
|
||||||
|
assertThat(actionPlayPause.hasOnClickListeners()).isTrue()
|
||||||
|
|
||||||
|
// Trigger animation & update mock
|
||||||
|
actionPlayPause.performClick()
|
||||||
|
verify(mockAvd0, times(1)).start()
|
||||||
|
whenever(mockAvd0.isRunning()).thenReturn(true)
|
||||||
|
|
||||||
|
// Validate states no longer bind
|
||||||
|
player.bindPlayer(state1, PACKAGE)
|
||||||
|
player.bindPlayer(state2, PACKAGE)
|
||||||
|
assertThat(actionPlayPause.contentDescription).isEqualTo("play")
|
||||||
|
|
||||||
|
// Complete animation and run callbacks
|
||||||
|
whenever(mockAvd0.isRunning()).thenReturn(false)
|
||||||
|
val captor = ArgumentCaptor.forClass(Animatable2.AnimationCallback::class.java)
|
||||||
|
verify(mockAvd0, times(1)).registerAnimationCallback(captor.capture())
|
||||||
|
verify(mockAvd1, never())
|
||||||
|
.registerAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
verify(mockAvd2, never())
|
||||||
|
.registerAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
captor.getValue().onAnimationEnd(mockAvd0)
|
||||||
|
|
||||||
|
// Validate correct state was bound
|
||||||
|
assertThat(actionPlayPause.contentDescription).isEqualTo("loading")
|
||||||
|
verify(mockAvd0, times(1))
|
||||||
|
.registerAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
verify(mockAvd1, times(1)
|
||||||
|
).registerAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
verify(mockAvd2, times(1))
|
||||||
|
.registerAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
verify(mockAvd0, times(1))
|
||||||
|
.unregisterAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
verify(mockAvd1, times(1))
|
||||||
|
.unregisterAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
verify(mockAvd2, never())
|
||||||
|
.unregisterAnimationCallback(any(Animatable2.AnimationCallback::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun bindText() {
|
fun bindText() {
|
||||||
player.attachPlayer(viewHolder)
|
player.attachPlayer(viewHolder)
|
||||||
|
|||||||
Reference in New Issue
Block a user