1 /* 2 * Copyright (C) 2012 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.systemui.statusbar.phone; 18 19 import android.content.Context; 20 import android.util.AttributeSet; 21 import android.util.Log; 22 import android.view.MotionEvent; 23 import android.view.View; 24 import android.widget.FrameLayout; 25 26 public abstract class PanelBar extends FrameLayout { 27 public static final boolean DEBUG = false; 28 public static final String TAG = PanelBar.class.getSimpleName(); 29 private static final boolean SPEW = false; 30 31 public static final void LOG(String fmt, Object... args) { 32 if (!DEBUG) return; 33 Log.v(TAG, String.format(fmt, args)); 34 } 35 36 public static final int STATE_CLOSED = 0; 37 public static final int STATE_OPENING = 1; 38 public static final int STATE_OPEN = 2; 39 40 PanelView mPanel; 41 private int mState = STATE_CLOSED; 42 private boolean mTracking; 43 44 public void go(int state) { 45 if (DEBUG) LOG("go state: %d -> %d", mState, state); 46 mState = state; 47 } 48 49 public PanelBar(Context context, AttributeSet attrs) { 50 super(context, attrs); 51 } 52 53 @Override 54 protected void onFinishInflate() { 55 super.onFinishInflate(); 56 } 57 58 public void setPanel(PanelView pv) { 59 mPanel = pv; 60 pv.setBar(this); 61 } 62 63 public void setBouncerShowing(boolean showing) { 64 int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 65 : IMPORTANT_FOR_ACCESSIBILITY_AUTO; 66 67 setImportantForAccessibility(important); 68 69 if (mPanel != null) mPanel.setImportantForAccessibility(important); 70 } 71 72 public boolean panelEnabled() { 73 return true; 74 } 75 76 @Override 77 public boolean onTouchEvent(MotionEvent event) { 78 // Allow subclasses to implement enable/disable semantics 79 if (!panelEnabled()) { 80 if (event.getAction() == MotionEvent.ACTION_DOWN) { 81 Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)", 82 (int) event.getX(), (int) event.getY())); 83 } 84 return false; 85 } 86 87 if (event.getAction() == MotionEvent.ACTION_DOWN) { 88 final PanelView panel = mPanel; 89 if (panel == null) { 90 // panel is not there, so we'll eat the gesture 91 Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)", 92 (int) event.getX(), (int) event.getY())); 93 return true; 94 } 95 boolean enabled = panel.isEnabled(); 96 if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, 97 (enabled ? "" : " (disabled)")); 98 if (!enabled) { 99 // panel is disabled, so we'll eat the gesture 100 Log.v(TAG, String.format( 101 "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)", 102 panel, (int) event.getX(), (int) event.getY())); 103 return true; 104 } 105 } 106 return mPanel == null || mPanel.onTouchEvent(event); 107 } 108 109 public abstract void panelScrimMinFractionChanged(float minFraction); 110 111 /** 112 * @param frac the fraction from the expansion in [0, 1] 113 * @param expanded whether the panel is currently expanded; this is independent from the 114 * fraction as the panel also might be expanded if the fraction is 0 115 */ 116 public void panelExpansionChanged(float frac, boolean expanded) { 117 boolean fullyClosed = true; 118 boolean fullyOpened = false; 119 if (SPEW) LOG("panelExpansionChanged: start state=%d", mState); 120 PanelView pv = mPanel; 121 pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE); 122 // adjust any other panels that may be partially visible 123 if (expanded) { 124 if (mState == STATE_CLOSED) { 125 go(STATE_OPENING); 126 onPanelPeeked(); 127 } 128 fullyClosed = false; 129 final float thisFrac = pv.getExpandedFraction(); 130 if (SPEW) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 131 fullyOpened = thisFrac >= 1f; 132 } 133 if (fullyOpened && !mTracking) { 134 go(STATE_OPEN); 135 onPanelFullyOpened(); 136 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 137 go(STATE_CLOSED); 138 onPanelCollapsed(); 139 } 140 141 if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 142 fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":""); 143 } 144 145 public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) { 146 boolean waiting = false; 147 PanelView pv = mPanel; 148 if (animate && !pv.isFullyCollapsed()) { 149 pv.collapse(delayed, speedUpFactor); 150 waiting = true; 151 } else { 152 pv.resetViews(); 153 pv.setExpandedFraction(0); // just in case 154 pv.cancelPeek(); 155 } 156 if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting); 157 if (!waiting && mState != STATE_CLOSED) { 158 // it's possible that nothing animated, so we replicate the termination 159 // conditions of panelExpansionChanged here 160 go(STATE_CLOSED); 161 onPanelCollapsed(); 162 } 163 } 164 165 public void onPanelPeeked() { 166 if (DEBUG) LOG("onPanelPeeked"); 167 } 168 169 public void onPanelCollapsed() { 170 if (DEBUG) LOG("onPanelCollapsed"); 171 } 172 173 public void onPanelFullyOpened() { 174 if (DEBUG) LOG("onPanelFullyOpened"); 175 } 176 177 public void onTrackingStarted() { 178 mTracking = true; 179 } 180 181 public void onTrackingStopped(boolean expand) { 182 mTracking = false; 183 } 184 185 public void onExpandingFinished() { 186 if (DEBUG) LOG("onExpandingFinished"); 187 } 188 189 public void onClosingFinished() { 190 191 } 192 } 193