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 17 package com.android.calculator2; 18 19 import android.content.Context; 20 import android.transition.Fade; 21 import android.transition.Transition; 22 import android.transition.TransitionManager; 23 import android.util.AttributeSet; 24 import android.view.GestureDetector; 25 import android.view.MotionEvent; 26 import android.view.View; 27 import android.view.accessibility.AccessibilityManager; 28 import android.widget.LinearLayout; 29 import android.widget.Toolbar; 30 31 public class CalculatorDisplay extends LinearLayout 32 implements AccessibilityManager.AccessibilityStateChangeListener { 33 34 /** 35 * The duration in milliseconds after which to hide the toolbar. 36 */ 37 private static final long AUTO_HIDE_DELAY_MILLIS = 3000L; 38 39 /** 40 * The duration in milliseconds to fade in/out the toolbar. 41 */ 42 private static final long FADE_DURATION = 200L; 43 44 private final Runnable mHideToolbarRunnable = new Runnable() { 45 @Override 46 public void run() { 47 // Remove any duplicate callbacks to hide the toolbar. 48 removeCallbacks(this); 49 50 // Only animate if we have been laid out at least once. 51 if (isLaidOut()) { 52 TransitionManager.beginDelayedTransition(CalculatorDisplay.this, mTransition); 53 } 54 mToolbar.setVisibility(View.INVISIBLE); 55 } 56 }; 57 58 private final AccessibilityManager mAccessibilityManager; 59 private final GestureDetector mTapDetector; 60 61 private Toolbar mToolbar; 62 private Transition mTransition; 63 64 private boolean mForceToolbarVisible; 65 CalculatorDisplay(Context context)66 public CalculatorDisplay(Context context) { 67 this(context, null /* attrs */); 68 } 69 CalculatorDisplay(Context context, AttributeSet attrs)70 public CalculatorDisplay(Context context, AttributeSet attrs) { 71 this(context, attrs, 0 /* defStyleAttr */); 72 } 73 CalculatorDisplay(Context context, AttributeSet attrs, int defStyleAttr)74 public CalculatorDisplay(Context context, AttributeSet attrs, int defStyleAttr) { 75 super(context, attrs, defStyleAttr); 76 77 mAccessibilityManager = 78 (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); 79 80 mTapDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 81 @Override 82 public boolean onDown(MotionEvent e) { 83 // Remove callbacks to hide the toolbar. 84 removeCallbacks(mHideToolbarRunnable); 85 86 return true; 87 } 88 89 @Override 90 public boolean onSingleTapConfirmed(MotionEvent e) { 91 if (mToolbar.getVisibility() != View.VISIBLE) { 92 showToolbar(true); 93 } else { 94 hideToolbar(); 95 } 96 97 return true; 98 } 99 }); 100 101 // Draw the children in reverse order so that the toolbar is on top. 102 setChildrenDrawingOrderEnabled(true); 103 } 104 105 @Override onFinishInflate()106 protected void onFinishInflate() { 107 super.onFinishInflate(); 108 109 mToolbar = (Toolbar) findViewById(R.id.toolbar); 110 mTransition = new Fade() 111 .setDuration(FADE_DURATION) 112 .addTarget(mToolbar); 113 } 114 115 @Override getChildDrawingOrder(int childCount, int i)116 protected int getChildDrawingOrder(int childCount, int i) { 117 // Reverse the normal drawing order. 118 return (childCount - 1) - i; 119 } 120 121 @Override onAttachedToWindow()122 protected void onAttachedToWindow() { 123 super.onAttachedToWindow(); 124 mAccessibilityManager.addAccessibilityStateChangeListener(this); 125 } 126 127 @Override onDetachedFromWindow()128 protected void onDetachedFromWindow() { 129 super.onDetachedFromWindow(); 130 mAccessibilityManager.removeAccessibilityStateChangeListener(this); 131 } 132 133 @Override onAccessibilityStateChanged(boolean enabled)134 public void onAccessibilityStateChanged(boolean enabled) { 135 // Always show the toolbar whenever accessibility is enabled. 136 showToolbar(true); 137 } 138 139 @Override onInterceptTouchEvent(MotionEvent event)140 public boolean onInterceptTouchEvent(MotionEvent event) { 141 mTapDetector.onTouchEvent(event); 142 return super.onInterceptTouchEvent(event); 143 } 144 145 @Override onTouchEvent(MotionEvent event)146 public boolean onTouchEvent(MotionEvent event) { 147 return mTapDetector.onTouchEvent(event) || super.onTouchEvent(event); 148 } 149 150 /** 151 * Returns {@code true} if the toolbar should remain visible. 152 */ getForceToolbarVisible()153 public boolean getForceToolbarVisible() { 154 return mForceToolbarVisible || mAccessibilityManager.isEnabled(); 155 } 156 157 /** 158 * Forces the toolbar to remain visible. 159 * 160 * @param forceToolbarVisible {@code true} to keep the toolbar visible 161 */ setForceToolbarVisible(boolean forceToolbarVisible)162 public void setForceToolbarVisible(boolean forceToolbarVisible) { 163 if (mForceToolbarVisible != forceToolbarVisible) { 164 mForceToolbarVisible = forceToolbarVisible; 165 showToolbar(!forceToolbarVisible); 166 } 167 } 168 169 /** 170 * Shows the toolbar. 171 * @param autoHide Automatically ide toolbar again after delay 172 */ showToolbar(boolean autoHide)173 public void showToolbar(boolean autoHide) { 174 // Only animate if we have been laid out at least once. 175 if (isLaidOut()) { 176 TransitionManager.beginDelayedTransition(this, mTransition); 177 } 178 mToolbar.setVisibility(View.VISIBLE); 179 180 // Remove callbacks to hide the toolbar. 181 removeCallbacks(mHideToolbarRunnable); 182 183 // Auto hide the toolbar after 3 seconds. 184 if (autoHide && !getForceToolbarVisible()) { 185 postDelayed(mHideToolbarRunnable, AUTO_HIDE_DELAY_MILLIS); 186 } 187 } 188 189 /** 190 * Hides the toolbar. 191 */ hideToolbar()192 public void hideToolbar() { 193 if (!getForceToolbarVisible()) { 194 removeCallbacks(mHideToolbarRunnable); 195 mHideToolbarRunnable.run(); 196 } 197 } 198 isToolbarVisible()199 public boolean isToolbarVisible() { 200 return mToolbar.getVisibility() == View.VISIBLE; 201 } 202 } 203