1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package androidx.leanback.widget;
15 
16 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
17 
18 import android.animation.Animator;
19 import android.animation.ObjectAnimator;
20 import android.animation.ValueAnimator;
21 import android.content.Context;
22 import android.util.AttributeSet;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 import android.view.animation.LinearInterpolator;
26 import android.widget.ImageView;
27 import android.widget.LinearLayout;
28 
29 import androidx.annotation.RestrictTo;
30 import androidx.leanback.R;
31 
32 /**
33  * The view displaying 3 animated peak meters next to each other when a media item is playing.
34  */
35 @RestrictTo(LIBRARY_GROUP_PREFIX)
36 public class MediaNowPlayingView extends LinearLayout{
37 
38     private final ImageView mImage1;
39     private final ImageView mImage2;
40     private final ImageView mImage3;
41     private final ObjectAnimator mObjectAnimator1;
42     private final ObjectAnimator mObjectAnimator2;
43     private final ObjectAnimator mObjectAnimator3;
44     protected final LinearInterpolator mLinearInterpolator = new LinearInterpolator();
45 
MediaNowPlayingView(Context context, AttributeSet attrs)46     public MediaNowPlayingView(Context context, AttributeSet attrs) {
47         super(context, attrs);
48 
49         LayoutInflater.from(context).inflate(R.layout.lb_playback_now_playing_bars, this, true);
50         mImage1 = findViewById(R.id.bar1);
51         mImage2 = findViewById(R.id.bar2);
52         mImage3 = findViewById(R.id.bar3);
53 
54         mImage1.setPivotY(mImage1.getDrawable().getIntrinsicHeight());
55         mImage2.setPivotY(mImage2.getDrawable().getIntrinsicHeight());
56         mImage3.setPivotY(mImage3.getDrawable().getIntrinsicHeight());
57 
58         setDropScale(mImage1);
59         setDropScale(mImage2);
60         setDropScale(mImage3);
61 
62         mObjectAnimator1 = ObjectAnimator.ofFloat(mImage1, "scaleY", 5f / 12f, 3f / 12f, 5f / 12f,
63                 7f / 12f, 9f / 12f, 10f / 12f, 11f / 12f, 12f / 12f, 11f / 12f, 12f / 12f,
64                 10f / 12f, 8f / 12f, 6f / 12f, 4f / 12f, 2f / 12f, 4f / 12f, 6f / 12f, 7f / 12f,
65                 9f / 12f, 11f / 12f, 9f / 12f, 7f / 12f, 5f / 12f, 3f / 12f, 5f / 12f, 8f / 12f,
66                 5f / 12f, 3f / 12f, 4f / 12f, 5f / 12f);
67         mObjectAnimator1.setRepeatCount(ValueAnimator.INFINITE);
68         mObjectAnimator1.setDuration(2320);
69         mObjectAnimator1.setInterpolator(mLinearInterpolator);
70 
71         mObjectAnimator2 = ObjectAnimator.ofFloat(mImage2, "scaleY", 12f / 12f, 11f / 12f,
72                 10f / 12f, 11f / 12f, 12f / 12f, 11f / 12f, 9f / 12f, 7f / 12f, 9f / 12f, 11f / 12f,
73                 12f / 12f, 10f / 12f, 8f / 12f, 10f / 12f, 12f / 12f, 11f / 12f, 9f / 12f, 5f / 12f,
74                 3f / 12f, 5f / 12f, 8f / 12f, 10f / 12f, 12f / 12f, 10f / 12f, 9f / 12f, 8f / 12f,
75                 12f / 12f);
76         mObjectAnimator2.setRepeatCount(ValueAnimator.INFINITE);
77         mObjectAnimator2.setDuration(2080);
78         mObjectAnimator2.setInterpolator(mLinearInterpolator);
79 
80         mObjectAnimator3 = ObjectAnimator.ofFloat(mImage3, "scaleY", 8f / 12f, 9f / 12f, 10f / 12f,
81                 12f / 12f, 11f / 12f, 9f / 12f, 7f / 12f, 5f / 12f, 7f / 12f, 8f / 12f, 9f / 12f,
82                 12f / 12f, 11f / 12f, 12f / 12f, 9f / 12f, 7f / 12f, 9f / 12f, 11f / 12f, 12f / 12f,
83                 10f / 12f, 8f / 12f, 9f / 12f, 7f / 12f, 5f / 12f, 3f / 12f, 8f / 12f);
84         mObjectAnimator3.setRepeatCount(ValueAnimator.INFINITE);
85         mObjectAnimator3.setDuration(2000);
86         mObjectAnimator3.setInterpolator(mLinearInterpolator);
87     }
88 
setDropScale(View view)89     static void setDropScale(View view) {
90         view.setScaleY(1f / 12f);
91     }
92 
93     @Override
setVisibility(int visibility)94     public void setVisibility(int visibility) {
95         super.setVisibility(visibility);
96         if (visibility == View.GONE) {
97             stopAnimation();
98         } else {
99             startAnimation();
100         }
101     }
102 
103     @Override
onAttachedToWindow()104     protected void onAttachedToWindow() {
105         super.onAttachedToWindow();
106         if (getVisibility() == View.VISIBLE)
107             startAnimation();
108     }
109 
110     @Override
onDetachedFromWindow()111     protected void onDetachedFromWindow() {
112         super.onDetachedFromWindow();
113         stopAnimation();
114     }
115 
startAnimation()116     private void startAnimation() {
117         startAnimation(mObjectAnimator1);
118         startAnimation(mObjectAnimator2);
119         startAnimation(mObjectAnimator3);
120         mImage1.setVisibility(View.VISIBLE);
121         mImage2.setVisibility(View.VISIBLE);
122         mImage3.setVisibility(View.VISIBLE);
123     }
124 
stopAnimation()125     private void stopAnimation() {
126         stopAnimation(mObjectAnimator1, mImage1);
127         stopAnimation(mObjectAnimator2, mImage2);
128         stopAnimation(mObjectAnimator3, mImage3);
129         mImage1.setVisibility(View.GONE);
130         mImage2.setVisibility(View.GONE);
131         mImage3.setVisibility(View.GONE);
132     }
133 
startAnimation(Animator animator)134     private void startAnimation(Animator animator) {
135         if (!animator.isStarted()) {
136             animator.start();
137         }
138     }
139 
stopAnimation(Animator animator, View view)140     private void stopAnimation(Animator animator, View view) {
141         if (animator.isStarted()) {
142             animator.cancel();
143             setDropScale(view);
144         }
145     }
146 }
147