PanelBar.java revision 919adac28bd6a9888c3bbd53a1736f260bc76bbf
1package com.android.systemui.statusbar.phone; 2 3import java.util.ArrayList; 4 5import android.content.Context; 6import android.util.AttributeSet; 7import android.util.Slog; 8import android.view.MotionEvent; 9import android.view.View; 10import android.widget.FrameLayout; 11 12public class PanelBar extends FrameLayout { 13 public static final boolean DEBUG = false; 14 public static final String TAG = PanelBar.class.getSimpleName(); 15 public static final void LOG(String fmt, Object... args) { 16 if (!DEBUG) return; 17 Slog.v(TAG, String.format(fmt, args)); 18 } 19 20 public static final int STATE_CLOSED = 0; 21 public static final int STATE_OPENING = 1; 22 public static final int STATE_OPEN = 2; 23 24 private PanelHolder mPanelHolder; 25 private ArrayList<PanelView> mPanels = new ArrayList<PanelView>(); 26 protected PanelView mTouchingPanel; 27 private int mState = STATE_CLOSED; 28 private boolean mTracking; 29 30 public void go(int state) { 31 LOG("go state: %d -> %d", mState, state); 32 mState = state; 33 } 34 35 public PanelBar(Context context, AttributeSet attrs) { 36 super(context, attrs); 37 } 38 39 @Override 40 protected void onFinishInflate() { 41 super.onFinishInflate(); 42 } 43 44 public void addPanel(PanelView pv) { 45 mPanels.add(pv); 46 pv.setBar(this); 47 } 48 49 public void setPanelHolder(PanelHolder ph) { 50 if (ph == null) { 51 Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable()); 52 return; 53 } 54 ph.setBar(this); 55 mPanelHolder = ph; 56 final int N = ph.getChildCount(); 57 for (int i=0; i<N; i++) { 58 final PanelView v = (PanelView) ph.getChildAt(i); 59 if (v != null) { 60 addPanel(v); 61 } 62 } 63 } 64 65 public float getBarHeight() { 66 return getMeasuredHeight(); 67 } 68 69 public PanelView selectPanelForTouchX(float x) { 70 final int N = mPanels.size(); 71 return mPanels.get((int)(N * x / getMeasuredWidth())); 72 } 73 74 public boolean panelsEnabled() { 75 return true; 76 } 77 78 @Override 79 public boolean onTouchEvent(MotionEvent event) { 80 // Allow subclasses to implement enable/disable semantics 81 if (!panelsEnabled()) return false; 82 83 // figure out which panel needs to be talked to here 84 if (event.getAction() == MotionEvent.ACTION_DOWN) { 85 final PanelView panel = selectPanelForTouchX(event.getX()); 86 boolean enabled = panel.isEnabled(); 87 LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, 88 (enabled ? "" : " (disabled)")); 89 if (!enabled) 90 return false; 91 startOpeningPanel(panel); 92 } 93 final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event); 94 return result; 95 } 96 97 // called from PanelView when self-expanding, too 98 public void startOpeningPanel(PanelView panel) { 99 LOG("startOpeningPanel: " + panel); 100 mTouchingPanel = panel; 101 mPanelHolder.setSelectedPanel(mTouchingPanel); 102 } 103 104 public void panelExpansionChanged(PanelView panel, float frac) { 105 boolean fullyClosed = true; 106 PanelView fullyOpenedPanel = null; 107 LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); 108 for (PanelView pv : mPanels) { 109 final boolean visible = pv.getVisibility() == View.VISIBLE; 110 // adjust any other panels that may be partially visible 111 if (pv.getExpandedHeight() > 0f) { 112 if (mState == STATE_CLOSED) { 113 go(STATE_OPENING); 114 onPanelPeeked(); 115 } 116 fullyClosed = false; 117 final float thisFrac = pv.getExpandedFraction(); 118 LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 119 if (panel == pv) { 120 if (thisFrac == 1f) fullyOpenedPanel = panel; 121 } else { 122 pv.setExpandedFraction(1f-frac); 123 } 124 } 125 if (pv.getExpandedHeight() > 0f) { 126 if (!visible) pv.setVisibility(View.VISIBLE); 127 } else { 128 if (visible) pv.setVisibility(View.GONE); 129 } 130 } 131 if (fullyOpenedPanel != null && !mTracking) { 132 go(STATE_OPEN); 133 onPanelFullyOpened(fullyOpenedPanel); 134 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 135 go(STATE_CLOSED); 136 onAllPanelsCollapsed(); 137 } 138 139 LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 140 (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); 141 } 142 143 public void collapseAllPanels(boolean animate) { 144 boolean waiting = false; 145 for (PanelView pv : mPanels) { 146 if (animate && !pv.isFullyCollapsed()) { 147 pv.collapse(); 148 waiting = true; 149 } else { 150 pv.setExpandedFraction(0); // just in case 151 } 152 pv.setVisibility(View.GONE); 153 } 154 if (!waiting) { 155 // it's possible that nothing animated, so we replicate the termination 156 // conditions of panelExpansionChanged here 157 go(STATE_CLOSED); 158 onAllPanelsCollapsed(); 159 } 160 } 161 162 public void onPanelPeeked() { 163 LOG("onPanelPeeked"); 164 } 165 166 public void onAllPanelsCollapsed() { 167 LOG("onAllPanelsCollapsed"); 168 } 169 170 public void onPanelFullyOpened(PanelView openPanel) { 171 LOG("onPanelFullyOpened"); 172 } 173 174 public void onTrackingStarted(PanelView panel) { 175 mTracking = true; 176 if (panel != mTouchingPanel) { 177 LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)", 178 panel, mTouchingPanel); 179 } 180 } 181 182 public void onTrackingStopped(PanelView panel) { 183 mTracking = false; 184 panelExpansionChanged(panel, panel.getExpandedFraction()); 185 } 186} 187