blob: 4491ebde742b90d12e16a6b2fc77ec76634e168d [file] [log] [blame]
Mady Mellor4b80b102016-01-22 08:03:58 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar;
18
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ValueAnimator;
22import android.content.Context;
23import android.util.AttributeSet;
24import android.view.View;
Mady Mellor4b80b102016-01-22 08:03:58 -080025import android.widget.FrameLayout;
26
27import com.android.systemui.Interpolators;
28import com.android.systemui.R;
29
30public class NotificationSettingsIconRow extends FrameLayout implements View.OnClickListener {
31
32 public interface SettingsIconRowListener {
33 /**
34 * Called when the gear behind a notification is touched.
35 */
36 public void onGearTouched(ExpandableNotificationRow row);
37 }
38
39 private ExpandableNotificationRow mParent;
40 private AlphaOptimizedImageView mGearIcon;
41 private float mHorizSpaceForGear;
42 private SettingsIconRowListener mListener;
43
44 private ValueAnimator mFadeAnimator;
45 private boolean mSettingsFadedIn = false;
46 private boolean mAnimating = false;
47 private boolean mOnLeft = true;
48
49 public NotificationSettingsIconRow(Context context) {
50 this(context, null);
51 }
52
53 public NotificationSettingsIconRow(Context context, AttributeSet attrs) {
54 this(context, attrs, 0);
55 }
56
57 public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr) {
58 this(context, attrs, defStyleAttr, 0);
59 }
60
61 public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr,
62 int defStyleRes) {
63 super(context, attrs);
64 }
65
66 @Override
67 protected void onFinishInflate() {
68 super.onFinishInflate();
69 mGearIcon = (AlphaOptimizedImageView) findViewById(R.id.gear_icon);
70 mGearIcon.setOnClickListener(this);
Mady Mellorf0625802016-02-11 18:03:48 -080071 setOnClickListener(this);
72 mHorizSpaceForGear =
73 getResources().getDimensionPixelOffset(R.dimen.notification_gear_width);
Mady Mellor4b80b102016-01-22 08:03:58 -080074 resetState();
75 }
76
77 public void setGearListener(SettingsIconRowListener listener) {
78 mListener = listener;
79 }
80
81 public void setNotificationRowParent(ExpandableNotificationRow parent) {
82 mParent = parent;
83 }
84
85 public ExpandableNotificationRow getNotificationParent() {
86 return mParent;
87 }
88
89 public void resetState() {
90 setGearAlpha(0f);
91 mAnimating = false;
92 setIconLocation(true /* on left */);
93 }
94
95 private void setGearAlpha(float alpha) {
96 if (alpha == 0) {
97 mSettingsFadedIn = false; // Can fade in again once it's gone.
98 mGearIcon.setVisibility(View.INVISIBLE);
99 } else {
100 if (alpha == 1) {
101 mSettingsFadedIn = true;
102 }
103 mGearIcon.setVisibility(View.VISIBLE);
104 }
105 mGearIcon.setAlpha(alpha);
106 }
107
108 /**
109 * Returns the horizontal space in pixels required to display the gear behind a notification.
110 */
111 public float getSpaceForGear() {
112 return mHorizSpaceForGear;
113 }
114
115 /**
116 * Indicates whether the gear is visible at 1 alpha. Does not indicate
117 * if entire view is visible.
118 */
119 public boolean isVisible() {
120 return mSettingsFadedIn;
121 }
122
123 public void cancelFadeAnimator() {
124 if (mFadeAnimator != null) {
125 mFadeAnimator.cancel();
126 }
127 }
128
129 public void updateSettingsIcons(final float transX, final float size) {
130 if (mAnimating || (mGearIcon.getAlpha() == 0)) {
131 // Don't adjust when animating or settings aren't visible
132 return;
133 }
134 setIconLocation(transX > 0 /* fromLeft */);
135 final float fadeThreshold = size * 0.3f;
136 final float absTrans = Math.abs(transX);
137 float desiredAlpha = 0;
138
Mady Mellor4b80b102016-01-22 08:03:58 -0800139 if (absTrans <= fadeThreshold) {
140 desiredAlpha = 1;
141 } else {
142 desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
143 }
144 setGearAlpha(desiredAlpha);
145 }
146
147 public void fadeInSettings(final boolean fromLeft, final float transX,
148 final float notiThreshold) {
149 setIconLocation(transX > 0 /* fromLeft */);
150 mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
151 mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
152 @Override
153 public void onAnimationUpdate(ValueAnimator animation) {
154 final float absTrans = Math.abs(transX);
155
156 boolean pastGear = (fromLeft && transX <= notiThreshold)
157 || (!fromLeft && absTrans <= notiThreshold);
158 if (pastGear && !mSettingsFadedIn) {
159 setGearAlpha((float) animation.getAnimatedValue());
160 }
161 }
162 });
163 mFadeAnimator.addListener(new AnimatorListenerAdapter() {
164 @Override
165 public void onAnimationCancel(Animator animation) {
166 super.onAnimationCancel(animation);
167 mAnimating = false;
168 mSettingsFadedIn = false;
169 }
170
171 @Override
172 public void onAnimationStart(Animator animation) {
173 super.onAnimationStart(animation);
174 mAnimating = true;
175 }
176
177 @Override
178 public void onAnimationEnd(Animator animation) {
179 super.onAnimationEnd(animation);
180 mAnimating = false;
181 mSettingsFadedIn = true;
182 }
183 });
184 mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
185 mFadeAnimator.setDuration(200);
186 mFadeAnimator.start();
187 }
188
Mady Mellor4b80b102016-01-22 08:03:58 -0800189 private void setIconLocation(boolean onLeft) {
190 if (onLeft == mOnLeft) {
191 // Same side? Do nothing.
192 return;
193 }
Mady Mellorf0625802016-02-11 18:03:48 -0800194
195 setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
Mady Mellor4b80b102016-01-22 08:03:58 -0800196 mOnLeft = onLeft;
197 }
Mady Mellorf0625802016-02-11 18:03:48 -0800198
199 @Override
200 public void onClick(View v) {
201 if (v.getId() == R.id.gear_icon) {
202 if (mListener != null) {
203 mListener.onGearTouched(mParent);
204 }
205 } else {
206 // Do nothing when the background is touched.
207 }
208 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800209}