1 /* 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 package com.android.car.hvac.controllers; 17 18 import android.animation.Animator; 19 import android.animation.AnimatorSet; 20 import android.animation.ObjectAnimator; 21 import android.animation.ValueAnimator; 22 import android.content.Context; 23 import android.content.res.Resources; 24 import android.graphics.drawable.Drawable; 25 import android.support.annotation.IntDef; 26 import android.view.MotionEvent; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.view.WindowManager; 30 import android.widget.ImageView; 31 import com.android.car.hvac.HvacController; 32 import com.android.car.hvac.R; 33 import com.android.car.hvac.ui.FanDirectionButtons; 34 import com.android.car.hvac.ui.FanSpeedBar; 35 import com.android.car.hvac.ui.HvacPanelRow; 36 import com.android.car.hvac.ui.SeatWarmerButton; 37 import com.android.car.hvac.ui.TemperatureBarOverlay; 38 import com.android.car.hvac.ui.ToggleButton; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 /** 44 * A state machine to control transition from various HVAC UI layouts. 45 */ 46 public class HvacPanelController { 47 private static final int PANEL_ANIMATION_TIME_MS = 200; 48 private static final int PANEL_COLLAPSE_ANIMATION_TIME_MS = 500; 49 50 private static final int PANEL_ANIMATION_DELAY_MS = 100; 51 private static final int PANEL_ANIMATION_LONG_DELAY_MS = 3 * PANEL_ANIMATION_DELAY_MS; 52 53 private static final float DISABLED_BUTTON_ALPHA = 0.20f; 54 private static final float ENABLED_BUTTON_ALPHA = 1.0f; 55 56 private static final int STATE_COLLAPSED = 0; 57 private static final int STATE_COLLAPSED_DIMMED = 1; 58 private static final int STATE_FULL_EXPANDED = 2; 59 60 @IntDef({STATE_COLLAPSED, 61 STATE_COLLAPSED_DIMMED, 62 STATE_FULL_EXPANDED}) 63 private @interface HvacPanelState {} 64 65 private @HvacPanelState int mCurrentState; 66 67 private int mPanelCollapsedHeight; 68 private int mPanelFullExpandedHeight; 69 70 private View mPanel; 71 private View mContainer; 72 73 private TemperatureBarOverlay mDriverTemperature; 74 private TemperatureBarOverlay mPassengerTemperature; 75 76 private ViewGroup mDriverTemperatureTouchOverlay; 77 private ViewGroup mPassengerTemperatureTouchOverlay; 78 79 private SeatWarmerButton mDriverSeatWarmer; 80 private SeatWarmerButton mPassengerSeatWarmer; 81 82 private ToggleButton mAcButton; 83 private ToggleButton mRecycleAirButton; 84 85 private ToggleButton mFrontDefrosterButton; 86 private ToggleButton mRearDefrosterButton; 87 88 private Drawable mAutoOnDrawable; 89 private Drawable mAutoOffDrawable; 90 91 private ImageView mAutoButton; 92 93 private HvacPanelRow mPanelTopRow; 94 private HvacPanelRow mPanelBottomRow; 95 96 private FanSpeedBar mFanSpeedBar; 97 private FanDirectionButtons mFanDirectionButtons; 98 99 private float mTopPanelMaxAlpha = 1.0f; 100 101 private WindowManager mWindowManager; 102 103 private HvacPanelStateTransition mTransition; 104 105 private View mHvacFanControlBackground; 106 107 private HvacController mHvacController; 108 private FanSpeedBarController mFanSpeedBarController; 109 private FanDirectionButtonsController mFanDirectionButtonsController; 110 private TemperatureController mTemperatureController; 111 private SeatWarmerController mSeatWarmerController; 112 113 private boolean mInAnimation; 114 private boolean mHvacIsOn; 115 116 // TODO: read from shared pref 117 private boolean mAutoMode; 118 HvacPanelController(Context context, View container, WindowManager windowManager, TemperatureBarOverlay driverTemperature, TemperatureBarOverlay passengerTemperature, ViewGroup driverTemperatureBarTouchOverlay, ViewGroup passengerTemperatureBarTouchOverlay)119 public HvacPanelController(Context context, View container, 120 WindowManager windowManager, TemperatureBarOverlay driverTemperature, 121 TemperatureBarOverlay passengerTemperature, ViewGroup driverTemperatureBarTouchOverlay, 122 ViewGroup passengerTemperatureBarTouchOverlay) { 123 124 mCurrentState = STATE_COLLAPSED; 125 mWindowManager = windowManager; 126 127 Resources res = context.getResources(); 128 mPanelCollapsedHeight = res.getDimensionPixelSize(R.dimen.car_hvac_panel_collapsed_height); 129 mPanelFullExpandedHeight 130 = res.getDimensionPixelSize(R.dimen.car_hvac_panel_full_expanded_height); 131 132 mAutoOffDrawable = res.getDrawable(R.drawable.ic_auto_off); 133 mAutoOnDrawable = res.getDrawable(R.drawable.ic_auto_on); 134 135 mDriverTemperature = driverTemperature; 136 mDriverTemperature.setBarOnClickListener(mPanelClickListener); 137 138 mPassengerTemperature = passengerTemperature; 139 mPassengerTemperature.setBarOnClickListener(mPanelClickListener); 140 141 mDriverTemperature.setCloseButtonOnClickListener(mOpenCloseToggleListener); 142 mPassengerTemperature.setCloseButtonOnClickListener(mOpenCloseToggleListener); 143 144 // Initially the hvac panel is collapsed, disable touches on the overlay container. 145 disableTouchOnOverlay(mDriverTemperature); 146 disableTouchOnOverlay(mPassengerTemperature); 147 148 mDriverTemperatureTouchOverlay = driverTemperatureBarTouchOverlay; 149 mPassengerTemperatureTouchOverlay = passengerTemperatureBarTouchOverlay; 150 151 mDriverTemperatureTouchOverlay.setOnClickListener(mOpenCloseToggleListener); 152 mPassengerTemperatureTouchOverlay.setOnClickListener(mOpenCloseToggleListener); 153 154 mContainer = container; 155 mContainer.setVisibility(View.INVISIBLE); 156 mContainer.setOnClickListener(mOpenCloseToggleListener); 157 mPanel = mContainer.findViewById(R.id.hvac_center_panel); 158 159 mHvacFanControlBackground = mPanel.findViewById(R.id.fan_control_bg); 160 mPanel.setOnClickListener(mPanelClickListener); 161 162 // Set up top row buttons 163 mPanelTopRow = (HvacPanelRow) mContainer.findViewById(R.id.top_row); 164 165 mAcButton = (ToggleButton) mPanelTopRow.findViewById(R.id.ac_button); 166 mAcButton.setToggleIcons(res.getDrawable(R.drawable.ic_ac_on), 167 res.getDrawable(R.drawable.ic_ac_off)); 168 169 mRecycleAirButton = (ToggleButton) mPanelTopRow.findViewById(R.id.recycle_air_button); 170 171 mRecycleAirButton.setToggleIcons(res.getDrawable(R.drawable.ic_recycle_air_on), 172 res.getDrawable(R.drawable.ic_recycle_air_off)); 173 174 // Setup bottom row buttons 175 mPanelBottomRow = (HvacPanelRow) mContainer.findViewById(R.id.bottom_row); 176 177 mAutoButton = (ImageView) mContainer.findViewById(R.id.auto_button); 178 mAutoButton.setOnClickListener(mAutoButtonClickListener); 179 180 mFrontDefrosterButton = (ToggleButton) mPanelBottomRow.findViewById(R.id.front_defroster); 181 mRearDefrosterButton = (ToggleButton) mPanelBottomRow.findViewById(R.id.rear_defroster); 182 183 mFrontDefrosterButton.setToggleIcons(res.getDrawable(R.drawable.ic_front_defroster_on), 184 res.getDrawable(R.drawable.ic_front_defroster_off)); 185 186 mRearDefrosterButton.setToggleIcons(res.getDrawable(R.drawable.ic_rear_defroster_on), 187 res.getDrawable(R.drawable.ic_rear_defroster_off)); 188 189 mFanSpeedBar = (FanSpeedBar) mContainer.findViewById(R.id.fan_speed_bar); 190 mFanDirectionButtons = (FanDirectionButtons) mContainer.findViewById(R.id.fan_direction_buttons); 191 192 mDriverSeatWarmer = (SeatWarmerButton) mContainer.findViewById(R.id.left_seat_heater); 193 mPassengerSeatWarmer = (SeatWarmerButton) mContainer.findViewById(R.id.right_seat_heater); 194 } 195 updateHvacController(HvacController controller)196 public void updateHvacController(HvacController controller) { 197 //TODO: handle disconnected HvacController. 198 mHvacController = controller; 199 200 mFanSpeedBarController = new FanSpeedBarController(mFanSpeedBar, mHvacController); 201 mFanDirectionButtonsController 202 = new FanDirectionButtonsController(mFanDirectionButtons, mHvacController); 203 mTemperatureController = new TemperatureController(mPassengerTemperature, 204 mDriverTemperature, mHvacController); 205 mSeatWarmerController = new SeatWarmerController(mPassengerSeatWarmer, 206 mDriverSeatWarmer, mHvacController); 207 208 // Toggle buttons do not need additional logic to map between hardware 209 // and UI settings. Simply use a ToggleListener to handle clicks. 210 mAcButton.setIsOn(mHvacController.getAcState()); 211 mAcButton.setToggleListener(new ToggleButton.ToggleListener() { 212 @Override 213 public void onToggled(boolean isOn) { 214 mHvacController.setAcState(isOn); 215 } 216 }); 217 218 mFrontDefrosterButton.setIsOn(mHvacController.getFrontDefrosterState()); 219 mFrontDefrosterButton.setToggleListener(new ToggleButton.ToggleListener() { 220 @Override 221 public void onToggled(boolean isOn) { 222 mHvacController.setFrontDefrosterState(isOn); 223 } 224 }); 225 226 mRearDefrosterButton.setIsOn(mHvacController.getRearDefrosterState()); 227 mRearDefrosterButton.setToggleListener(new ToggleButton.ToggleListener() { 228 @Override 229 public void onToggled(boolean isOn) { 230 mHvacController.setRearDefrosterState(isOn); 231 } 232 }); 233 234 mRecycleAirButton.setIsOn(mHvacController.getAirCirculationState()); 235 mRecycleAirButton.setToggleListener(new ToggleButton.ToggleListener() { 236 @Override 237 public void onToggled(boolean isOn) { 238 mHvacController.setAirCirculation(isOn); 239 } 240 }); 241 242 setAutoMode(mHvacController.getAutoModeState()); 243 244 mHvacController.registerCallback(mToggleButtonCallbacks); 245 mToggleButtonCallbacks.onHvacPowerChange(mHvacController.getHvacPowerState()); 246 } 247 248 private HvacController.Callback mToggleButtonCallbacks 249 = new HvacController.Callback() { 250 @Override 251 public void onAirCirculationChange(boolean isOn) { 252 mRecycleAirButton.setIsOn(isOn); 253 } 254 255 @Override 256 public void onFrontDefrosterChange(boolean isOn) { 257 mFrontDefrosterButton.setIsOn(isOn); 258 } 259 260 @Override 261 public void onRearDefrosterChange(boolean isOn) { 262 mRearDefrosterButton.setIsOn(isOn); 263 } 264 265 @Override 266 public void onAcStateChange(boolean isOn) { 267 mAcButton.setIsOn(isOn); 268 } 269 270 @Override 271 public void onAutoModeChange(boolean isOn) { 272 mAutoMode = isOn; 273 setAutoMode(mAutoMode); 274 } 275 276 @Override 277 public void onHvacPowerChange(boolean isOn) { 278 // When the HVAC Power is turned off, collapse the panel and fade the temperature 279 // bars. Also disable expanding the panel until power is back on. 280 mHvacIsOn = isOn; 281 if (!mHvacIsOn && mCurrentState == STATE_FULL_EXPANDED) { 282 transitionState(STATE_FULL_EXPANDED, STATE_COLLAPSED); 283 } 284 285 mDriverTemperature.setIsOn(mHvacIsOn); 286 mPassengerTemperature.setIsOn(mHvacIsOn); 287 } 288 }; 289 290 /** 291 * Take the listeners and animators from a {@link AnimatorSet} and merge them to the 292 * input {@link Animator} and {@link android.animation.Animator.AnimatorListener} lists. 293 */ combineAnimationSet(List<Animator> animatorList, List<Animator.AnimatorListener> listenerList, AnimatorSet set)294 private void combineAnimationSet(List<Animator> animatorList, 295 List<Animator.AnimatorListener> listenerList, AnimatorSet set) { 296 297 ArrayList<Animator> list = set.getChildAnimations(); 298 if (list != null) { 299 int size = list.size(); 300 for (int i = 0; i < size; i++) { 301 animatorList.add(list.get(i)); 302 } 303 } 304 305 ArrayList<Animator.AnimatorListener> listeners = set.getListeners(); 306 if (listeners != null) { 307 int size = listeners.size(); 308 for (int i = 0; i < size; i++) { 309 listenerList.add(listeners.get(i)); 310 } 311 } 312 } 313 314 /** 315 * Play necessary animations between {@link HvacPanelState} transitions 316 */ transitionState(@vacPanelState int startState, @HvacPanelState int endState)317 private void transitionState(@HvacPanelState int startState, @HvacPanelState int endState) { 318 if (startState == endState || mInAnimation) { 319 return; 320 } 321 322 List<Animator> animationList = new ArrayList<>(); 323 List<Animator.AnimatorListener> listenerList = new ArrayList<>(); 324 ValueAnimator heightAnimator = getPanelHeightAnimator(startState, endState); 325 mTransition = new HvacPanelStateTransition(startState, endState); 326 ValueAnimator fanBgAlphaAnimator; 327 switch (endState) { 328 case STATE_COLLAPSED: 329 // Transition to collapsed state: 330 // 1. Collapse the temperature bars. 331 // 2. Collapse the top and bottom panel, staggered with a different delay. 332 // 3. Decrease height of the hvac center panel, but maintain container height. 333 // 4. Fade the background of the fan controls seperately to create staggered effect. 334 animationList.add(heightAnimator); 335 heightAnimator.setDuration(PANEL_COLLAPSE_ANIMATION_TIME_MS); 336 fanBgAlphaAnimator 337 = ObjectAnimator.ofFloat(mHvacFanControlBackground, View.ALPHA, 1, 0) 338 .setDuration(PANEL_COLLAPSE_ANIMATION_TIME_MS); 339 fanBgAlphaAnimator.setStartDelay(PANEL_ANIMATION_DELAY_MS); 340 animationList.add(fanBgAlphaAnimator); 341 342 ValueAnimator panelAlphaAnimator 343 = ObjectAnimator.ofFloat(mContainer, View.ALPHA, 1, 0); 344 panelAlphaAnimator.setDuration(200); 345 panelAlphaAnimator.setStartDelay(300); 346 347 animationList.add(panelAlphaAnimator); 348 349 combineAnimationSet(animationList, listenerList, 350 mDriverTemperature.getCollapseAnimations()); 351 combineAnimationSet(animationList, listenerList, 352 mPassengerTemperature.getCollapseAnimations()); 353 354 combineAnimationSet(animationList, listenerList, 355 mPanelTopRow.getCollapseAnimation(PANEL_ANIMATION_DELAY_MS, 356 mTopPanelMaxAlpha)); 357 combineAnimationSet(animationList, listenerList, 358 mPanelBottomRow.getCollapseAnimation(PANEL_ANIMATION_DELAY_MS, 359 mTopPanelMaxAlpha)); 360 break; 361 case STATE_COLLAPSED_DIMMED: 362 // Hide the temperature numbers, open arrows and auto state button. 363 // TODO: determine if this section is still needed. 364 break; 365 case STATE_FULL_EXPANDED: 366 // Transition to expaneded state: 367 // 1. Expand the temperature bars. 368 // 2. Expand the top and bottom panel, staggered with a different delay. 369 // 3. Increase height of the hvac center panel, but maintain container height. 370 // 4. Fade in fan control background in a staggered manner. 371 fanBgAlphaAnimator 372 = ObjectAnimator.ofFloat(mHvacFanControlBackground, View.ALPHA, 0, 1) 373 .setDuration(PANEL_ANIMATION_TIME_MS); 374 fanBgAlphaAnimator.setStartDelay(PANEL_ANIMATION_DELAY_MS); 375 animationList.add(fanBgAlphaAnimator); 376 377 animationList.add(heightAnimator); 378 combineAnimationSet(animationList, listenerList, 379 mDriverTemperature.getExpandAnimatons()); 380 combineAnimationSet(animationList, listenerList, 381 mPassengerTemperature.getExpandAnimatons()); 382 383 // During expansion, the bottom panel animation should be delayed 384 combineAnimationSet(animationList, listenerList, 385 mPanelTopRow.getExpandAnimation(PANEL_ANIMATION_DELAY_MS, 386 mTopPanelMaxAlpha)); 387 combineAnimationSet(animationList, listenerList, 388 mPanelBottomRow.getExpandAnimation(PANEL_ANIMATION_LONG_DELAY_MS, 1f)); 389 break; 390 default: 391 } 392 393 // If there are animations for the state change, play them all together and ensure 394 // the animation listeners are attached. 395 if (animationList.size() > 0) { 396 AnimatorSet animatorSet = new AnimatorSet(); 397 animatorSet.playTogether(animationList); 398 for (Animator.AnimatorListener listener : listenerList) { 399 animatorSet.addListener(listener); 400 } 401 animatorSet.addListener(mAnimatorListener); 402 animatorSet.start(); 403 } 404 } 405 406 private AnimatorSet.AnimatorListener mAnimatorListener = new AnimatorSet.AnimatorListener() { 407 @Override 408 public void onAnimationStart(Animator animation) { 409 mTransition.onTransitionStart(); 410 } 411 412 @Override 413 public void onAnimationEnd(Animator animation) { 414 mTransition.onTransitionComplete(); 415 } 416 417 @Override 418 public void onAnimationCancel(Animator animation) {} 419 420 @Override 421 public void onAnimationRepeat(Animator animation) {} 422 }; 423 getPanelHeightAnimator(@vacPanelState int startState, @HvacPanelState int endState)424 private ValueAnimator getPanelHeightAnimator(@HvacPanelState int startState, 425 @HvacPanelState int endState) { 426 int startHeight = getStateHeight(startState); 427 int endHeight = getStateHeight(endState); 428 if (startHeight == endHeight) { 429 return null; 430 } 431 432 ValueAnimator heightAnimator = new ValueAnimator().ofInt(startHeight, endHeight) 433 .setDuration(PANEL_ANIMATION_TIME_MS); 434 heightAnimator.addUpdateListener(mHeightUpdateListener); 435 return heightAnimator; 436 } 437 getStateHeight(@vacPanelState int state)438 private int getStateHeight(@HvacPanelState int state) { 439 switch (state) { 440 case STATE_COLLAPSED: 441 case STATE_COLLAPSED_DIMMED: 442 return mPanelCollapsedHeight; 443 case STATE_FULL_EXPANDED: 444 return mPanelFullExpandedHeight; 445 default: 446 throw new IllegalArgumentException("No height mapped to HVAC State: " + state); 447 } 448 } 449 setAutoMode(boolean isOn)450 private void setAutoMode(boolean isOn) { 451 if (isOn) { 452 mPanelTopRow.setOnTouchListener(new View.OnTouchListener() { 453 @Override 454 public boolean onTouch(View v, MotionEvent event) { 455 return true; 456 } 457 }); 458 mAutoMode = true; 459 mPanelTopRow.disablePanel(true); 460 mTopPanelMaxAlpha = DISABLED_BUTTON_ALPHA; 461 mAutoButton.setImageDrawable(mAutoOnDrawable); 462 } else { 463 mPanelTopRow.disablePanel(false); 464 mTopPanelMaxAlpha = ENABLED_BUTTON_ALPHA; 465 mAutoButton.setImageDrawable(mAutoOffDrawable); 466 } 467 mHvacFanControlBackground.setAlpha(mTopPanelMaxAlpha); 468 mPanelTopRow.setAlpha(mTopPanelMaxAlpha); 469 } 470 471 private View.OnClickListener mPanelClickListener = new View.OnClickListener() { 472 @Override 473 public void onClick(View v) { 474 if (!mHvacIsOn) { 475 return; 476 } 477 switch (mCurrentState) { 478 case STATE_COLLAPSED: 479 transitionState(STATE_COLLAPSED, STATE_FULL_EXPANDED); 480 break; 481 case STATE_COLLAPSED_DIMMED: 482 transitionState(mCurrentState, STATE_COLLAPSED); 483 break; 484 default: 485 } 486 } 487 }; 488 489 private View.OnClickListener mAutoButtonClickListener = new View.OnClickListener() { 490 @Override 491 public void onClick(View v) { 492 if (mAutoMode) { 493 mAutoMode = false; 494 } else { 495 mAutoMode = true; 496 } 497 mHvacController.setAutoMode(mAutoMode); 498 setAutoMode(mAutoMode); 499 } 500 }; 501 502 private View.OnClickListener mOpenCloseToggleListener = new View.OnClickListener() { 503 @Override 504 public void onClick(View v) { 505 if (!mHvacIsOn) { 506 return; 507 } 508 if (mCurrentState == STATE_FULL_EXPANDED) { 509 transitionState(mCurrentState, STATE_COLLAPSED); 510 } else if (mCurrentState == STATE_COLLAPSED) { 511 transitionState(mCurrentState, STATE_FULL_EXPANDED); 512 } 513 } 514 }; 515 516 private ValueAnimator.AnimatorUpdateListener mHeightUpdateListener 517 = new ValueAnimator.AnimatorUpdateListener() { 518 @Override 519 public void onAnimationUpdate(ValueAnimator animation) { 520 int height = (Integer) animation.getAnimatedValue(); 521 int currentHeight = mPanel.getLayoutParams().height; 522 mPanel.getLayoutParams().height = height; 523 mPanel.setTop(mPanel.getTop() + height - currentHeight); 524 mPanel.requestLayout(); 525 } 526 }; 527 528 /** 529 * Handles the necessary setup/clean up before and after a state transition. 530 */ 531 private class HvacPanelStateTransition { 532 private @HvacPanelState int mEndState; 533 private @HvacPanelState int mStartState; 534 HvacPanelStateTransition(@vacPanelState int startState, @HvacPanelState int endState)535 public HvacPanelStateTransition(@HvacPanelState int startState, 536 @HvacPanelState int endState) { 537 mStartState = startState; 538 mEndState = endState; 539 } 540 onTransitionStart()541 public void onTransitionStart() { 542 mInAnimation = true; 543 if (mEndState == STATE_FULL_EXPANDED) { 544 mContainer.setAlpha(1); 545 mContainer.setVisibility(View.VISIBLE); 546 } else if (mStartState == STATE_FULL_EXPANDED) { 547 // Finished transitioning out of the fully expanded panel. Make the HVAC container 548 // and temperature bars not touchable so clicks on the screen bar are not intercepted. 549 disableTouchOnOverlay(mContainer); 550 disableTouchOnOverlay(mDriverTemperature); 551 disableTouchOnOverlay(mPassengerTemperature); 552 } 553 } 554 onTransitionComplete()555 public void onTransitionComplete() { 556 if (mStartState == STATE_FULL_EXPANDED) { 557 mContainer.setVisibility(View.INVISIBLE); 558 559 enableTouchOnOverlay(mDriverTemperatureTouchOverlay); 560 enableTouchOnOverlay(mPassengerTemperatureTouchOverlay); 561 } else if (mEndState == STATE_FULL_EXPANDED) { 562 // Finished transitioning into the fully expanded HVAC panel, make the 563 // container and temperature bars touchable since it covers the screen. 564 enableTouchOnOverlay(mContainer); 565 enableTouchOnOverlay(mDriverTemperature); 566 enableTouchOnOverlay(mPassengerTemperature); 567 568 disableTouchOnOverlay(mDriverTemperatureTouchOverlay); 569 disableTouchOnOverlay(mPassengerTemperatureTouchOverlay); 570 } 571 572 // set new states 573 mCurrentState = mEndState; 574 mInAnimation = false; 575 } 576 } 577 disableTouchOnOverlay(View view)578 private void disableTouchOnOverlay(View view) { 579 WindowManager.LayoutParams params 580 = (WindowManager.LayoutParams) view.getLayoutParams(); 581 params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 582 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 583 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS 584 & ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 585 mWindowManager.updateViewLayout(view, params); 586 } 587 enableTouchOnOverlay(View view)588 private void enableTouchOnOverlay(View view) { 589 WindowManager.LayoutParams params 590 = (WindowManager.LayoutParams) view.getLayoutParams(); 591 params.flags = 592 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 593 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS 594 & ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 595 mWindowManager.updateViewLayout(view, params); 596 } 597 598 } 599