PanelBar.java revision 173bae2c674b2bc25cf376cbb4e150bd86703049
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 LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s", mState, panel); 87 startOpeningPanel(panel); 88 } 89 final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event); 90 return result; 91 } 92 93 // called from PanelView when self-expanding, too 94 public void startOpeningPanel(PanelView panel) { 95 LOG("startOpeningPanel: " + panel); 96 mTouchingPanel = panel; 97 mPanelHolder.setSelectedPanel(mTouchingPanel); 98 } 99 100 public void panelExpansionChanged(PanelView panel, float frac) { 101 boolean fullyClosed = true; 102 PanelView fullyOpenedPanel = null; 103 LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); 104 for (PanelView pv : mPanels) { 105 final boolean visible = pv.getVisibility() == View.VISIBLE; 106 // adjust any other panels that may be partially visible 107 if (pv.getExpandedHeight() > 0f) { 108 if (mState == STATE_CLOSED) { 109 go(STATE_OPENING); 110 onPanelPeeked(); 111 } 112 fullyClosed = false; 113 final float thisFrac = pv.getExpandedFraction(); 114 LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 115 if (panel == pv) { 116 if (thisFrac == 1f) fullyOpenedPanel = panel; 117 } else { 118 pv.setExpandedFraction(1f-frac); 119 } 120 } 121 if (pv.getExpandedHeight() > 0f) { 122 if (!visible) pv.setVisibility(View.VISIBLE); 123 } else { 124 if (visible) pv.setVisibility(View.GONE); 125 } 126 } 127 if (fullyOpenedPanel != null && !mTracking) { 128 go(STATE_OPEN); 129 onPanelFullyOpened(fullyOpenedPanel); 130 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 131 go(STATE_CLOSED); 132 onAllPanelsCollapsed(); 133 } 134 135 LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 136 (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); 137 } 138 139 public void collapseAllPanels(boolean animate) { 140 boolean waiting = false; 141 for (PanelView pv : mPanels) { 142 if (animate && !pv.isFullyCollapsed()) { 143 pv.collapse(); 144 waiting = true; 145 } else { 146 pv.setExpandedFraction(0); // just in case 147 } 148 pv.setVisibility(View.GONE); 149 } 150 if (!waiting) { 151 // it's possible that nothing animated, so we replicate the termination 152 // conditions of panelExpansionChanged here 153 go(STATE_CLOSED); 154 onAllPanelsCollapsed(); 155 } 156 } 157 158 public void onPanelPeeked() { 159 LOG("onPanelPeeked"); 160 } 161 162 public void onAllPanelsCollapsed() { 163 LOG("onAllPanelsCollapsed"); 164 } 165 166 public void onPanelFullyOpened(PanelView openPanel) { 167 LOG("onPanelFullyOpened"); 168 } 169 170 public void onTrackingStarted(PanelView panel) { 171 mTracking = true; 172 if (panel != mTouchingPanel) { 173 LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)", 174 panel, mTouchingPanel); 175 } 176 } 177 178 public void onTrackingStopped(PanelView panel) { 179 mTracking = false; 180 panelExpansionChanged(panel, panel.getExpandedFraction()); 181 } 182} 183