PanelBar.java revision 173bae2c674b2bc25cf376cbb4e150bd86703049
108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerpackage com.android.systemui.statusbar.phone; 208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport java.util.ArrayList; 408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.content.Context; 608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.util.AttributeSet; 708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.util.Slog; 808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.view.MotionEvent; 9173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandlerimport android.view.View; 1008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.widget.FrameLayout; 1108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 1208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerpublic class PanelBar extends FrameLayout { 13bf4aa9d5bc34df144afcab45e8045d34a0ac090aDaniel Sandler public static final boolean DEBUG = false; 14198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final String TAG = PanelBar.class.getSimpleName(); 1508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public static final void LOG(String fmt, Object... args) { 1608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler if (!DEBUG) return; 1708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler Slog.v(TAG, String.format(fmt, args)); 1808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 1908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 20198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final int STATE_CLOSED = 0; 21198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final int STATE_OPENING = 1; 22198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final int STATE_OPEN = 2; 23198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler 2408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler private PanelHolder mPanelHolder; 2508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler private ArrayList<PanelView> mPanels = new ArrayList<PanelView>(); 268e72c9e19cfb0b6c1463fa841f1dd02be8f3b4e1Daniel Sandler protected PanelView mTouchingPanel; 27978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler private int mState = STATE_CLOSED; 28978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler private boolean mTracking; 29978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler 30198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public void go(int state) { 31978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler LOG("go state: %d -> %d", mState, state); 32978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler mState = state; 33978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler } 3408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 3508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public PanelBar(Context context, AttributeSet attrs) { 3608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler super(context, attrs); 3708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 3808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 3908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler @Override 4008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler protected void onFinishInflate() { 4108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler super.onFinishInflate(); 4208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 4308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 4408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void addPanel(PanelView pv) { 4508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler mPanels.add(pv); 4608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler pv.setBar(this); 4708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 4808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 4908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void setPanelHolder(PanelHolder ph) { 5008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler if (ph == null) { 5108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable()); 5208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler return; 5308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 5408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler ph.setBar(this); 5508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler mPanelHolder = ph; 5608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler final int N = ph.getChildCount(); 5708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler for (int i=0; i<N; i++) { 5808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler final PanelView v = (PanelView) ph.getChildAt(i); 5908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler if (v != null) { 6008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler addPanel(v); 6108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 6208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 6308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 6408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 6508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public float getBarHeight() { 6608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler return getMeasuredHeight(); 6708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 6808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 69cf591db04914d8ceadd982451b325bd8c4817086Daniel Sandler public PanelView selectPanelForTouchX(float x) { 70cf591db04914d8ceadd982451b325bd8c4817086Daniel Sandler final int N = mPanels.size(); 71cf591db04914d8ceadd982451b325bd8c4817086Daniel Sandler return mPanels.get((int)(N * x / getMeasuredWidth())); 72cf591db04914d8ceadd982451b325bd8c4817086Daniel Sandler } 73cf591db04914d8ceadd982451b325bd8c4817086Daniel Sandler 745050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler public boolean panelsEnabled() { 751e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler return true; 761e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler } 771e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler 7808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler @Override 7908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public boolean onTouchEvent(MotionEvent event) { 801e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler // Allow subclasses to implement enable/disable semantics 815050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler if (!panelsEnabled()) return false; 821e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler 8308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler // figure out which panel needs to be talked to here 8408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler if (event.getAction() == MotionEvent.ACTION_DOWN) { 85198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler final PanelView panel = selectPanelForTouchX(event.getX()); 86198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s", mState, panel); 87198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler startOpeningPanel(panel); 8808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 8908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event); 9008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler return result; 9108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 9208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 93198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler // called from PanelView when self-expanding, too 94198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public void startOpeningPanel(PanelView panel) { 95198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler LOG("startOpeningPanel: " + panel); 96198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler mTouchingPanel = panel; 97198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler mPanelHolder.setSelectedPanel(mTouchingPanel); 98198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler } 99198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler 10008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void panelExpansionChanged(PanelView panel, float frac) { 10108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler boolean fullyClosed = true; 1028e72c9e19cfb0b6c1463fa841f1dd02be8f3b4e1Daniel Sandler PanelView fullyOpenedPanel = null; 103978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); 10408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler for (PanelView pv : mPanels) { 105173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler final boolean visible = pv.getVisibility() == View.VISIBLE; 106978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler // adjust any other panels that may be partially visible 10708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler if (pv.getExpandedHeight() > 0f) { 108198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler if (mState == STATE_CLOSED) { 109198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler go(STATE_OPENING); 110198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler onPanelPeeked(); 111198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler } 11208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler fullyClosed = false; 11308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler final float thisFrac = pv.getExpandedFraction(); 114978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 11508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler if (panel == pv) { 1168e72c9e19cfb0b6c1463fa841f1dd02be8f3b4e1Daniel Sandler if (thisFrac == 1f) fullyOpenedPanel = panel; 11708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } else { 11808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler pv.setExpandedFraction(1f-frac); 11908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 12008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 121173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler if (pv.getExpandedHeight() > 0f) { 122173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler if (!visible) pv.setVisibility(View.VISIBLE); 123173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler } else { 124173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler if (visible) pv.setVisibility(View.GONE); 125173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler } 12608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 127978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler if (fullyOpenedPanel != null && !mTracking) { 128978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler go(STATE_OPEN); 129978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler onPanelFullyOpened(fullyOpenedPanel); 130198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 131978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler go(STATE_CLOSED); 132978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler onAllPanelsCollapsed(); 133978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler } 13408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 135978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 1368e72c9e19cfb0b6c1463fa841f1dd02be8f3b4e1Daniel Sandler (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); 13708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 13808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 13908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void collapseAllPanels(boolean animate) { 140198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler boolean waiting = false; 14108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler for (PanelView pv : mPanels) { 142198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler if (animate && !pv.isFullyCollapsed()) { 143198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler pv.collapse(); 144198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler waiting = true; 14508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } else { 14608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler pv.setExpandedFraction(0); // just in case 14708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 148173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandler pv.setVisibility(View.GONE); 14908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 150198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler if (!waiting) { 151198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler // it's possible that nothing animated, so we replicate the termination 152198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler // conditions of panelExpansionChanged here 153198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler go(STATE_CLOSED); 154198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler onAllPanelsCollapsed(); 155198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler } 15608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 15708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 15808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void onPanelPeeked() { 15908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler LOG("onPanelPeeked"); 16008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 16108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 16208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void onAllPanelsCollapsed() { 16308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler LOG("onAllPanelsCollapsed"); 16408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 16508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 1668e72c9e19cfb0b6c1463fa841f1dd02be8f3b4e1Daniel Sandler public void onPanelFullyOpened(PanelView openPanel) { 16708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler LOG("onPanelFullyOpened"); 16808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 169978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler 170978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler public void onTrackingStarted(PanelView panel) { 171978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler mTracking = true; 172978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler if (panel != mTouchingPanel) { 173978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)", 174978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler panel, mTouchingPanel); 175978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler } 176978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler } 177978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler 178978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler public void onTrackingStopped(PanelView panel) { 179978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler mTracking = false; 180978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler panelExpansionChanged(panel, panel.getExpandedFraction()); 181978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler } 18208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler} 183