ActionBarContainer.java revision da10fdd1400ecfd8d7f2e55651dd528d0614dfc5
1/* 2 * Copyright (C) 2010 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 17package android.support.v7.internal.widget; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.graphics.Canvas; 22import android.graphics.drawable.Drawable; 23import android.support.v7.app.ActionBar; 24import android.support.v7.appcompat.R; 25import android.support.v7.internal.view.ActionMode; 26import android.util.AttributeSet; 27import android.view.MotionEvent; 28import android.view.View; 29import android.view.ViewGroup; 30import android.widget.FrameLayout; 31 32/** 33 * This class acts as a container for the action bar view and action mode context views. It applies 34 * special styles as needed to help handle animated transitions between them. 35 * 36 * @hide 37 */ 38public class ActionBarContainer extends FrameLayout { 39 40 private boolean mIsTransitioning; 41 private View mTabContainer; 42 private ActionBarView mActionBarView; 43 44 private Drawable mBackground; 45 private Drawable mStackedBackground; 46 private Drawable mSplitBackground; 47 private boolean mIsSplit; 48 private boolean mIsStacked; 49 50 public ActionBarContainer(Context context) { 51 this(context, null); 52 } 53 54 public ActionBarContainer(Context context, AttributeSet attrs) { 55 super(context, attrs); 56 57 setBackgroundDrawable(null); 58 59 TypedArray a = context.obtainStyledAttributes(attrs, 60 R.styleable.ActionBar); 61 mBackground = a.getDrawable(R.styleable.ActionBar_background); 62 mStackedBackground = a.getDrawable( 63 R.styleable.ActionBar_backgroundStacked); 64 65 if (getId() == R.id.split_action_bar) { 66 mIsSplit = true; 67 mSplitBackground = a.getDrawable( 68 R.styleable.ActionBar_backgroundSplit); 69 } 70 a.recycle(); 71 72 setWillNotDraw(mIsSplit ? mSplitBackground == null : 73 mBackground == null && mStackedBackground == null); 74 } 75 76 @Override 77 public void onFinishInflate() { 78 super.onFinishInflate(); 79 mActionBarView = (ActionBarView) findViewById(R.id.action_bar); 80 } 81 82 public void setPrimaryBackground(Drawable bg) { 83 mBackground = bg; 84 invalidate(); 85 } 86 87 public void setStackedBackground(Drawable bg) { 88 mStackedBackground = bg; 89 invalidate(); 90 } 91 92 public void setSplitBackground(Drawable bg) { 93 mSplitBackground = bg; 94 invalidate(); 95 } 96 97 /** 98 * Set the action bar into a "transitioning" state. While transitioning the bar will block focus 99 * and touch from all of its descendants. This prevents the user from interacting with the bar 100 * while it is animating in or out. 101 * 102 * @param isTransitioning true if the bar is currently transitioning, false otherwise. 103 */ 104 public void setTransitioning(boolean isTransitioning) { 105 mIsTransitioning = isTransitioning; 106 setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS 107 : FOCUS_AFTER_DESCENDANTS); 108 } 109 110 @Override 111 public boolean onInterceptTouchEvent(MotionEvent ev) { 112 return mIsTransitioning || super.onInterceptTouchEvent(ev); 113 } 114 115 @Override 116 public boolean onTouchEvent(MotionEvent ev) { 117 super.onTouchEvent(ev); 118 119 // An action bar always eats touch events. 120 return true; 121 } 122 123 //@Override 124 public boolean onHoverEvent(MotionEvent ev) { 125 //super.onHoverEvent(ev); 126 127 // An action bar always eats hover events. 128 return true; 129 } 130 131 public void setTabContainer(ScrollingTabContainerView tabView) { 132 if (mTabContainer != null) { 133 removeView(mTabContainer); 134 } 135 mTabContainer = tabView; 136 if (tabView != null) { 137 addView(tabView); 138 final ViewGroup.LayoutParams lp = tabView.getLayoutParams(); 139 lp.width = LayoutParams.FILL_PARENT; 140 lp.height = LayoutParams.WRAP_CONTENT; 141 tabView.setAllowCollapse(false); 142 } 143 } 144 145 public View getTabContainer() { 146 return mTabContainer; 147 } 148 149 @Override 150 public void onDraw(Canvas canvas) { 151 if (getWidth() == 0 || getHeight() == 0) { 152 return; 153 } 154 155 if (mIsSplit) { 156 if (mSplitBackground != null) { 157 mSplitBackground.draw(canvas); 158 } 159 } else { 160 if (mBackground != null) { 161 mBackground.draw(canvas); 162 } 163 if (mStackedBackground != null && mIsStacked) { 164 mStackedBackground.draw(canvas); 165 } 166 } 167 } 168 169 //@Override 170 public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { 171 // No starting an action mode for an action bar child! (Where would it go?) 172 return null; 173 } 174 175 @Override 176 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 177 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 178 179 if (mActionBarView == null) { 180 return; 181 } 182 183 final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams(); 184 final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 : 185 mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; 186 187 if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { 188 final int mode = MeasureSpec.getMode(heightMeasureSpec); 189 if (mode == MeasureSpec.AT_MOST) { 190 final int maxHeight = MeasureSpec.getSize(heightMeasureSpec); 191 setMeasuredDimension(getMeasuredWidth(), 192 Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(), 193 maxHeight)); 194 } 195 } 196 } 197 198 @Override 199 public void onLayout(boolean changed, int l, int t, int r, int b) { 200 super.onLayout(changed, l, t, r, b); 201 202 final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE; 203 204 if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { 205 final int containerHeight = getMeasuredHeight(); 206 final int tabHeight = mTabContainer.getMeasuredHeight(); 207 208 if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) { 209 // Not showing home, put tabs on top. 210 final int count = getChildCount(); 211 for (int i = 0; i < count; i++) { 212 final View child = getChildAt(i); 213 214 if (child == mTabContainer) { 215 continue; 216 } 217 218 if (!mActionBarView.isCollapsed()) { 219 child.offsetTopAndBottom(tabHeight); 220 } 221 } 222 mTabContainer.layout(l, 0, r, tabHeight); 223 } else { 224 mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight); 225 } 226 } 227 228 boolean needsInvalidate = false; 229 if (mIsSplit) { 230 if (mSplitBackground != null) { 231 mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); 232 needsInvalidate = true; 233 } 234 } else { 235 if (mBackground != null) { 236 mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(), 237 mActionBarView.getRight(), mActionBarView.getBottom()); 238 needsInvalidate = true; 239 } 240 if ((mIsStacked = hasTabs && mStackedBackground != null)) { 241 mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(), 242 mTabContainer.getRight(), mTabContainer.getBottom()); 243 needsInvalidate = true; 244 } 245 } 246 247 if (needsInvalidate) { 248 invalidate(); 249 } 250 } 251} 252