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 15package com.android.systemui.statusbar.phone; 16 17import static com.android.systemui.Interpolators.ALPHA_IN; 18import static com.android.systemui.Interpolators.ALPHA_OUT; 19 20import android.animation.Animator; 21import android.animation.AnimatorListenerAdapter; 22import android.animation.ValueAnimator; 23import android.view.View; 24 25import android.view.View.AccessibilityDelegate; 26import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface; 27import com.android.systemui.statusbar.policy.KeyButtonDrawable; 28 29import 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 */ 35public class ButtonDispatcher { 36 private final static int FADE_DURATION_IN = 150; 37 private final static int FADE_DURATION_OUT = 100; 38 39 private final ArrayList<View> mViews = new ArrayList<>(); 40 41 private final int mId; 42 43 private View.OnClickListener mClickListener; 44 private View.OnTouchListener mTouchListener; 45 private View.OnLongClickListener mLongClickListener; 46 private View.OnHoverListener mOnHoverListener; 47 private Boolean mLongClickable; 48 private Float mAlpha; 49 private Float mDarkIntensity; 50 private Integer mVisibility = -1; 51 private Boolean mDelayTouchFeedback; 52 private KeyButtonDrawable mImageDrawable; 53 private View mCurrentView; 54 private boolean mVertical; 55 private ValueAnimator mFadeAnimator; 56 private AccessibilityDelegate mAccessibilityDelegate; 57 58 private final ValueAnimator.AnimatorUpdateListener mAlphaListener = animation -> 59 setAlpha((float) animation.getAnimatedValue()); 60 61 private final AnimatorListenerAdapter mFadeListener = new AnimatorListenerAdapter() { 62 @Override 63 public void onAnimationEnd(Animator animation) { 64 setVisibility(getAlpha() == 1 ? View.VISIBLE : View.INVISIBLE); 65 } 66 }; 67 68 public ButtonDispatcher(int id) { 69 mId = id; 70 } 71 72 void clear() { 73 mViews.clear(); 74 } 75 76 void addView(View view) { 77 mViews.add(view); 78 view.setOnClickListener(mClickListener); 79 view.setOnTouchListener(mTouchListener); 80 view.setOnLongClickListener(mLongClickListener); 81 view.setOnHoverListener(mOnHoverListener); 82 if (mLongClickable != null) { 83 view.setLongClickable(mLongClickable); 84 } 85 if (mAlpha != null) { 86 view.setAlpha(mAlpha); 87 } 88 if (mVisibility != null && mVisibility != -1) { 89 view.setVisibility(mVisibility); 90 } 91 if (mAccessibilityDelegate != null) { 92 view.setAccessibilityDelegate(mAccessibilityDelegate); 93 } 94 if (view instanceof ButtonInterface) { 95 final ButtonInterface button = (ButtonInterface) view; 96 if (mDarkIntensity != null) { 97 button.setDarkIntensity(mDarkIntensity); 98 } 99 if (mImageDrawable != null) { 100 button.setImageDrawable(mImageDrawable); 101 } 102 if (mDelayTouchFeedback != null) { 103 button.setDelayTouchFeedback(mDelayTouchFeedback); 104 } 105 button.setVertical(mVertical); 106 } 107 } 108 109 public int getId() { 110 return mId; 111 } 112 113 public int getVisibility() { 114 return mVisibility != null ? mVisibility : View.VISIBLE; 115 } 116 117 public boolean isVisible() { 118 return getVisibility() == View.VISIBLE; 119 } 120 121 public float getAlpha() { 122 return mAlpha != null ? mAlpha : 1; 123 } 124 125 public KeyButtonDrawable getImageDrawable() { 126 return mImageDrawable; 127 } 128 129 public void setImageDrawable(KeyButtonDrawable drawable) { 130 mImageDrawable = drawable; 131 final int N = mViews.size(); 132 for (int i = 0; i < N; i++) { 133 if (mViews.get(i) instanceof ButtonInterface) { 134 ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable); 135 } 136 } 137 } 138 139 public void setVisibility(int visibility) { 140 if (mVisibility == visibility) return; 141 mVisibility = visibility; 142 final int N = mViews.size(); 143 for (int i = 0; i < N; i++) { 144 mViews.get(i).setVisibility(mVisibility); 145 } 146 } 147 148 public void abortCurrentGesture() { 149 // This seems to be an instantaneous thing, so not going to persist it. 150 final int N = mViews.size(); 151 for (int i = 0; i < N; i++) { 152 if (mViews.get(i) instanceof ButtonInterface) { 153 ((ButtonInterface) mViews.get(i)).abortCurrentGesture(); 154 } 155 } 156 } 157 158 public void setAlpha(float alpha) { 159 setAlpha(alpha, false /* animate */); 160 } 161 162 public void setAlpha(float alpha, boolean animate) { 163 if (animate) { 164 if (mFadeAnimator != null) { 165 mFadeAnimator.cancel(); 166 } 167 mFadeAnimator = ValueAnimator.ofFloat(getAlpha(), alpha); 168 mFadeAnimator.setDuration(getAlpha() < alpha? FADE_DURATION_IN : FADE_DURATION_OUT); 169 mFadeAnimator.setInterpolator(getAlpha() < alpha ? ALPHA_IN : ALPHA_OUT); 170 mFadeAnimator.addListener(mFadeListener); 171 mFadeAnimator.addUpdateListener(mAlphaListener); 172 mFadeAnimator.start(); 173 setVisibility(View.VISIBLE); 174 } else { 175 mAlpha = alpha; 176 final int N = mViews.size(); 177 for (int i = 0; i < N; i++) { 178 mViews.get(i).setAlpha(alpha); 179 } 180 } 181 } 182 183 public void setDarkIntensity(float darkIntensity) { 184 mDarkIntensity = darkIntensity; 185 final int N = mViews.size(); 186 for (int i = 0; i < N; i++) { 187 if (mViews.get(i) instanceof ButtonInterface) { 188 ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity); 189 } 190 } 191 } 192 193 public void setDelayTouchFeedback(boolean delay) { 194 mDelayTouchFeedback = delay; 195 final int N = mViews.size(); 196 for (int i = 0; i < N; i++) { 197 if (mViews.get(i) instanceof ButtonInterface) { 198 ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay); 199 } 200 } 201 } 202 203 public void setOnClickListener(View.OnClickListener clickListener) { 204 mClickListener = clickListener; 205 final int N = mViews.size(); 206 for (int i = 0; i < N; i++) { 207 mViews.get(i).setOnClickListener(mClickListener); 208 } 209 } 210 211 public void setOnTouchListener(View.OnTouchListener touchListener) { 212 mTouchListener = touchListener; 213 final int N = mViews.size(); 214 for (int i = 0; i < N; i++) { 215 mViews.get(i).setOnTouchListener(mTouchListener); 216 } 217 } 218 219 public void setLongClickable(boolean isLongClickable) { 220 mLongClickable = isLongClickable; 221 final int N = mViews.size(); 222 for (int i = 0; i < N; i++) { 223 mViews.get(i).setLongClickable(mLongClickable); 224 } 225 } 226 227 public void setOnLongClickListener(View.OnLongClickListener longClickListener) { 228 mLongClickListener = longClickListener; 229 final int N = mViews.size(); 230 for (int i = 0; i < N; i++) { 231 mViews.get(i).setOnLongClickListener(mLongClickListener); 232 } 233 } 234 235 public void setOnHoverListener(View.OnHoverListener hoverListener) { 236 mOnHoverListener = hoverListener; 237 final int N = mViews.size(); 238 for (int i = 0; i < N; i++) { 239 mViews.get(i).setOnHoverListener(mOnHoverListener); 240 } 241 } 242 243 public void setAccessibilityDelegate(AccessibilityDelegate delegate) { 244 mAccessibilityDelegate = delegate; 245 final int N = mViews.size(); 246 for (int i = 0; i < N; i++) { 247 mViews.get(i).setAccessibilityDelegate(delegate); 248 } 249 } 250 251 public void setClickable(boolean clickable) { 252 abortCurrentGesture(); 253 final int N = mViews.size(); 254 for (int i = 0; i < N; i++) { 255 mViews.get(i).setClickable(clickable); 256 } 257 } 258 259 public ArrayList<View> getViews() { 260 return mViews; 261 } 262 263 public View getCurrentView() { 264 return mCurrentView; 265 } 266 267 public void setCurrentView(View currentView) { 268 mCurrentView = currentView.findViewById(mId); 269 } 270 271 public void setVertical(boolean vertical) { 272 mVertical = vertical; 273 final int N = mViews.size(); 274 for (int i = 0; i < N; i++) { 275 final View view = mViews.get(i); 276 if (view instanceof ButtonInterface) { 277 ((ButtonInterface) view).setVertical(vertical); 278 } 279 } 280 } 281} 282