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 5 * except 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 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.phone; 16 17 import static com.android.systemui.Interpolators.LINEAR; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorListenerAdapter; 21 import android.animation.ValueAnimator; 22 import android.view.View; 23 import android.view.View.AccessibilityDelegate; 24 25 import com.android.systemui.Dependency; 26 import com.android.systemui.assist.AssistManager; 27 import com.android.systemui.statusbar.policy.KeyButtonDrawable; 28 29 import java.util.ArrayList; 30 31 /** 32 * Dispatches common view calls to multiple views. This is used to handle 33 * multiples of the same nav bar icon appearing. 34 */ 35 public class ButtonDispatcher { 36 private static final int FADE_DURATION_IN = 150; 37 private static final int FADE_DURATION_OUT = 250; 38 39 private final ArrayList<View> mViews = new ArrayList<>(); 40 41 private final int mId; 42 private final AssistManager mAssistManager; 43 44 private View.OnClickListener mClickListener; 45 private View.OnTouchListener mTouchListener; 46 private View.OnLongClickListener mLongClickListener; 47 private View.OnHoverListener mOnHoverListener; 48 private Boolean mLongClickable; 49 private Float mAlpha; 50 private Float mDarkIntensity; 51 private Integer mVisibility = View.VISIBLE; 52 private Boolean mDelayTouchFeedback; 53 private KeyButtonDrawable mImageDrawable; 54 private View mCurrentView; 55 private boolean mVertical; 56 private ValueAnimator mFadeAnimator; 57 private AccessibilityDelegate mAccessibilityDelegate; 58 59 private final ValueAnimator.AnimatorUpdateListener mAlphaListener = animation -> 60 setAlpha( 61 (float) animation.getAnimatedValue(), 62 false /* animate */, 63 false /* cancelAnimator */); 64 65 private final AnimatorListenerAdapter mFadeListener = new AnimatorListenerAdapter() { 66 @Override 67 public void onAnimationEnd(Animator animation) { 68 mFadeAnimator = null; 69 setVisibility(getAlpha() == 1 ? View.VISIBLE : View.INVISIBLE); 70 } 71 }; 72 ButtonDispatcher(int id)73 public ButtonDispatcher(int id) { 74 mId = id; 75 mAssistManager = Dependency.get(AssistManager.class); 76 } 77 clear()78 void clear() { 79 mViews.clear(); 80 } 81 addView(View view)82 void addView(View view) { 83 mViews.add(view); 84 view.setOnClickListener(mClickListener); 85 view.setOnTouchListener(mTouchListener); 86 view.setOnLongClickListener(mLongClickListener); 87 view.setOnHoverListener(mOnHoverListener); 88 if (mLongClickable != null) { 89 view.setLongClickable(mLongClickable); 90 } 91 if (mAlpha != null) { 92 view.setAlpha(mAlpha); 93 } 94 if (mVisibility != null) { 95 view.setVisibility(mVisibility); 96 } 97 if (mAccessibilityDelegate != null) { 98 view.setAccessibilityDelegate(mAccessibilityDelegate); 99 } 100 if (view instanceof ButtonInterface) { 101 final ButtonInterface button = (ButtonInterface) view; 102 if (mDarkIntensity != null) { 103 button.setDarkIntensity(mDarkIntensity); 104 } 105 if (mImageDrawable != null) { 106 button.setImageDrawable(mImageDrawable); 107 } 108 if (mDelayTouchFeedback != null) { 109 button.setDelayTouchFeedback(mDelayTouchFeedback); 110 } 111 button.setVertical(mVertical); 112 } 113 } 114 getId()115 public int getId() { 116 return mId; 117 } 118 getVisibility()119 public int getVisibility() { 120 return mVisibility != null ? mVisibility : View.VISIBLE; 121 } 122 isVisible()123 public boolean isVisible() { 124 return getVisibility() == View.VISIBLE; 125 } 126 getAlpha()127 public float getAlpha() { 128 return mAlpha != null ? mAlpha : 1; 129 } 130 getImageDrawable()131 public KeyButtonDrawable getImageDrawable() { 132 return mImageDrawable; 133 } 134 setImageDrawable(KeyButtonDrawable drawable)135 public void setImageDrawable(KeyButtonDrawable drawable) { 136 mImageDrawable = drawable; 137 final int N = mViews.size(); 138 for (int i = 0; i < N; i++) { 139 if (mViews.get(i) instanceof ButtonInterface) { 140 ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable); 141 } 142 } 143 if (mImageDrawable != null) { 144 mImageDrawable.setCallback(mCurrentView); 145 } 146 } 147 setVisibility(int visibility)148 public void setVisibility(int visibility) { 149 if (mVisibility == visibility) return; 150 if (mFadeAnimator != null) { 151 mFadeAnimator.cancel(); 152 } 153 154 mVisibility = visibility; 155 final int N = mViews.size(); 156 for (int i = 0; i < N; i++) { 157 mViews.get(i).setVisibility(mVisibility); 158 } 159 } 160 abortCurrentGesture()161 public void abortCurrentGesture() { 162 // This seems to be an instantaneous thing, so not going to persist it. 163 final int N = mViews.size(); 164 for (int i = 0; i < N; i++) { 165 if (mViews.get(i) instanceof ButtonInterface) { 166 ((ButtonInterface) mViews.get(i)).abortCurrentGesture(); 167 } 168 } 169 } 170 setAlpha(float alpha)171 public void setAlpha(float alpha) { 172 setAlpha(alpha, false /* animate */); 173 } 174 setAlpha(float alpha, boolean animate)175 public void setAlpha(float alpha, boolean animate) { 176 setAlpha(alpha, animate, true /* cancelAnimator */); 177 } 178 setAlpha(float alpha, boolean animate, long duration)179 public void setAlpha(float alpha, boolean animate, long duration) { 180 setAlpha(alpha, animate, duration, true /* cancelAnimator */); 181 } 182 setAlpha(float alpha, boolean animate, boolean cancelAnimator)183 public void setAlpha(float alpha, boolean animate, boolean cancelAnimator) { 184 setAlpha( 185 alpha, 186 animate, 187 (getAlpha() < alpha) ? FADE_DURATION_IN : FADE_DURATION_OUT, 188 cancelAnimator); 189 } 190 setAlpha(float alpha, boolean animate, long duration, boolean cancelAnimator)191 public void setAlpha(float alpha, boolean animate, long duration, boolean cancelAnimator) { 192 if (mFadeAnimator != null && (cancelAnimator || animate)) { 193 mFadeAnimator.cancel(); 194 } 195 if (animate) { 196 setVisibility(View.VISIBLE); 197 mFadeAnimator = ValueAnimator.ofFloat(getAlpha(), alpha); 198 mFadeAnimator.setStartDelay( 199 mAssistManager.getAssistHandleShowAndGoRemainingDurationMs()); 200 mFadeAnimator.setDuration(duration); 201 mFadeAnimator.setInterpolator(LINEAR); 202 mFadeAnimator.addListener(mFadeListener); 203 mFadeAnimator.addUpdateListener(mAlphaListener); 204 mFadeAnimator.start(); 205 } else { 206 mAlpha = alpha; 207 final int N = mViews.size(); 208 for (int i = 0; i < N; i++) { 209 mViews.get(i).setAlpha(alpha); 210 } 211 } 212 } 213 setDarkIntensity(float darkIntensity)214 public void setDarkIntensity(float darkIntensity) { 215 mDarkIntensity = darkIntensity; 216 final int N = mViews.size(); 217 for (int i = 0; i < N; i++) { 218 if (mViews.get(i) instanceof ButtonInterface) { 219 ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity); 220 } 221 } 222 } 223 setDelayTouchFeedback(boolean delay)224 public void setDelayTouchFeedback(boolean delay) { 225 mDelayTouchFeedback = delay; 226 final int N = mViews.size(); 227 for (int i = 0; i < N; i++) { 228 if (mViews.get(i) instanceof ButtonInterface) { 229 ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay); 230 } 231 } 232 } 233 setOnClickListener(View.OnClickListener clickListener)234 public void setOnClickListener(View.OnClickListener clickListener) { 235 mClickListener = clickListener; 236 final int N = mViews.size(); 237 for (int i = 0; i < N; i++) { 238 mViews.get(i).setOnClickListener(mClickListener); 239 } 240 } 241 setOnTouchListener(View.OnTouchListener touchListener)242 public void setOnTouchListener(View.OnTouchListener touchListener) { 243 mTouchListener = touchListener; 244 final int N = mViews.size(); 245 for (int i = 0; i < N; i++) { 246 mViews.get(i).setOnTouchListener(mTouchListener); 247 } 248 } 249 setLongClickable(boolean isLongClickable)250 public void setLongClickable(boolean isLongClickable) { 251 mLongClickable = isLongClickable; 252 final int N = mViews.size(); 253 for (int i = 0; i < N; i++) { 254 mViews.get(i).setLongClickable(mLongClickable); 255 } 256 } 257 setOnLongClickListener(View.OnLongClickListener longClickListener)258 public void setOnLongClickListener(View.OnLongClickListener longClickListener) { 259 mLongClickListener = longClickListener; 260 final int N = mViews.size(); 261 for (int i = 0; i < N; i++) { 262 mViews.get(i).setOnLongClickListener(mLongClickListener); 263 } 264 } 265 setOnHoverListener(View.OnHoverListener hoverListener)266 public void setOnHoverListener(View.OnHoverListener hoverListener) { 267 mOnHoverListener = hoverListener; 268 final int N = mViews.size(); 269 for (int i = 0; i < N; i++) { 270 mViews.get(i).setOnHoverListener(mOnHoverListener); 271 } 272 } 273 setAccessibilityDelegate(AccessibilityDelegate delegate)274 public void setAccessibilityDelegate(AccessibilityDelegate delegate) { 275 mAccessibilityDelegate = delegate; 276 final int N = mViews.size(); 277 for (int i = 0; i < N; i++) { 278 mViews.get(i).setAccessibilityDelegate(delegate); 279 } 280 } 281 setClickable(boolean clickable)282 public void setClickable(boolean clickable) { 283 abortCurrentGesture(); 284 final int N = mViews.size(); 285 for (int i = 0; i < N; i++) { 286 mViews.get(i).setClickable(clickable); 287 } 288 } 289 setTranslation(int x, int y, int z)290 public void setTranslation(int x, int y, int z) { 291 final int N = mViews.size(); 292 for (int i = 0; i < N; i++) { 293 final View view = mViews.get(i); 294 view.setTranslationX(x); 295 view.setTranslationY(y); 296 view.setTranslationZ(z); 297 } 298 } 299 getViews()300 public ArrayList<View> getViews() { 301 return mViews; 302 } 303 getCurrentView()304 public View getCurrentView() { 305 return mCurrentView; 306 } 307 setCurrentView(View currentView)308 public void setCurrentView(View currentView) { 309 mCurrentView = currentView.findViewById(mId); 310 if (mImageDrawable != null) { 311 mImageDrawable.setCallback(mCurrentView); 312 } 313 if (mCurrentView != null) { 314 mCurrentView.setTranslationX(0); 315 mCurrentView.setTranslationY(0); 316 mCurrentView.setTranslationZ(0); 317 } 318 } 319 setVertical(boolean vertical)320 public void setVertical(boolean vertical) { 321 mVertical = vertical; 322 final int N = mViews.size(); 323 for (int i = 0; i < N; i++) { 324 final View view = mViews.get(i); 325 if (view instanceof ButtonInterface) { 326 ((ButtonInterface) view).setVertical(vertical); 327 } 328 } 329 } 330 331 /** 332 * Executes when button is detached from window. 333 */ onDestroy()334 protected void onDestroy() { 335 } 336 } 337