AbsActionBarView.java revision a05aba9c506cd12a753c53e060c289095c3477e9
1/* 2 * Copyright (C) 2011 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 */ 16package com.android.internal.widget; 17 18import com.android.internal.R; 19import com.android.internal.view.menu.ActionMenuPresenter; 20import com.android.internal.view.menu.ActionMenuView; 21 22import android.animation.Animator; 23import android.animation.AnimatorSet; 24import android.animation.ObjectAnimator; 25import android.animation.TimeInterpolator; 26import android.content.Context; 27import android.content.res.Configuration; 28import android.content.res.TypedArray; 29import android.util.AttributeSet; 30import android.view.View; 31import android.view.ViewGroup; 32import android.view.animation.DecelerateInterpolator; 33 34public abstract class AbsActionBarView extends ViewGroup { 35 protected ActionMenuView mMenuView; 36 protected ActionMenuPresenter mActionMenuPresenter; 37 protected ActionBarContainer mSplitView; 38 protected boolean mSplitActionBar; 39 protected boolean mSplitWhenNarrow; 40 protected int mContentHeight; 41 42 protected Animator mVisibilityAnim; 43 protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); 44 45 private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator(); 46 47 private static final int FADE_DURATION = 200; 48 49 public AbsActionBarView(Context context) { 50 super(context); 51 } 52 53 public AbsActionBarView(Context context, AttributeSet attrs) { 54 super(context, attrs); 55 } 56 57 public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) { 58 super(context, attrs, defStyle); 59 } 60 61 @Override 62 protected void onConfigurationChanged(Configuration newConfig) { 63 super.onConfigurationChanged(newConfig); 64 65 // Action bar can change size on configuration changes. 66 // Reread the desired height from the theme-specified style. 67 TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar, 68 com.android.internal.R.attr.actionBarStyle, 0); 69 setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0)); 70 a.recycle(); 71 if (mSplitWhenNarrow) { 72 setSplitActionBar(getContext().getResources().getBoolean( 73 com.android.internal.R.bool.split_action_bar_is_narrow)); 74 } 75 if (mActionMenuPresenter != null) { 76 mActionMenuPresenter.onConfigurationChanged(newConfig); 77 } 78 } 79 80 /** 81 * Sets whether the bar should be split right now, no questions asked. 82 * @param split true if the bar should split 83 */ 84 public void setSplitActionBar(boolean split) { 85 mSplitActionBar = split; 86 } 87 88 /** 89 * Sets whether the bar should split if we enter a narrow screen configuration. 90 * @param splitWhenNarrow true if the bar should check to split after a config change 91 */ 92 public void setSplitWhenNarrow(boolean splitWhenNarrow) { 93 mSplitWhenNarrow = splitWhenNarrow; 94 } 95 96 public void setContentHeight(int height) { 97 mContentHeight = height; 98 requestLayout(); 99 } 100 101 public int getContentHeight() { 102 return mContentHeight; 103 } 104 105 public void setSplitView(ActionBarContainer splitView) { 106 mSplitView = splitView; 107 } 108 109 /** 110 * @return Current visibility or if animating, the visibility being animated to. 111 */ 112 public int getAnimatedVisibility() { 113 if (mVisibilityAnim != null) { 114 return mVisAnimListener.mFinalVisibility; 115 } 116 return getVisibility(); 117 } 118 119 public void animateToVisibility(int visibility) { 120 if (mVisibilityAnim != null) { 121 mVisibilityAnim.cancel(); 122 } 123 if (visibility == VISIBLE) { 124 if (getVisibility() != VISIBLE) { 125 setAlpha(0); 126 if (mSplitView != null && mMenuView != null) { 127 mMenuView.setAlpha(0); 128 } 129 } 130 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); 131 anim.setDuration(FADE_DURATION); 132 anim.setInterpolator(sAlphaInterpolator); 133 if (mSplitView != null && mMenuView != null) { 134 AnimatorSet set = new AnimatorSet(); 135 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1); 136 splitAnim.setDuration(FADE_DURATION); 137 set.addListener(mVisAnimListener.withFinalVisibility(visibility)); 138 set.play(anim).with(splitAnim); 139 set.start(); 140 } else { 141 anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); 142 anim.start(); 143 } 144 } else { 145 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); 146 anim.setDuration(FADE_DURATION); 147 anim.setInterpolator(sAlphaInterpolator); 148 if (mSplitView != null && mMenuView != null) { 149 AnimatorSet set = new AnimatorSet(); 150 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0); 151 splitAnim.setDuration(FADE_DURATION); 152 set.addListener(mVisAnimListener.withFinalVisibility(visibility)); 153 set.play(anim).with(splitAnim); 154 set.start(); 155 } else { 156 anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); 157 anim.start(); 158 } 159 } 160 } 161 162 @Override 163 public void setVisibility(int visibility) { 164 if (mVisibilityAnim != null) { 165 mVisibilityAnim.end(); 166 } 167 super.setVisibility(visibility); 168 } 169 170 public boolean showOverflowMenu() { 171 if (mActionMenuPresenter != null) { 172 return mActionMenuPresenter.showOverflowMenu(); 173 } 174 return false; 175 } 176 177 public void postShowOverflowMenu() { 178 post(new Runnable() { 179 public void run() { 180 showOverflowMenu(); 181 } 182 }); 183 } 184 185 public boolean hideOverflowMenu() { 186 if (mActionMenuPresenter != null) { 187 return mActionMenuPresenter.hideOverflowMenu(); 188 } 189 return false; 190 } 191 192 public boolean isOverflowMenuShowing() { 193 if (mActionMenuPresenter != null) { 194 return mActionMenuPresenter.isOverflowMenuShowing(); 195 } 196 return false; 197 } 198 199 public boolean isOverflowReserved() { 200 return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved(); 201 } 202 203 public void dismissPopupMenus() { 204 if (mActionMenuPresenter != null) { 205 mActionMenuPresenter.dismissPopupMenus(); 206 } 207 } 208 209 protected int measureChildView(View child, int availableWidth, int childSpecHeight, 210 int spacing) { 211 child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 212 childSpecHeight); 213 214 availableWidth -= child.getMeasuredWidth(); 215 availableWidth -= spacing; 216 217 return Math.max(0, availableWidth); 218 } 219 220 protected int positionChild(View child, int x, int y, int contentHeight) { 221 int childWidth = child.getMeasuredWidth(); 222 int childHeight = child.getMeasuredHeight(); 223 int childTop = y + (contentHeight - childHeight) / 2; 224 225 child.layout(x, childTop, x + childWidth, childTop + childHeight); 226 227 return childWidth; 228 } 229 230 protected int positionChildInverse(View child, int x, int y, int contentHeight) { 231 int childWidth = child.getMeasuredWidth(); 232 int childHeight = child.getMeasuredHeight(); 233 int childTop = y + (contentHeight - childHeight) / 2; 234 235 child.layout(x - childWidth, childTop, x, childTop + childHeight); 236 237 return childWidth; 238 } 239 240 protected class VisibilityAnimListener implements Animator.AnimatorListener { 241 private boolean mCanceled = false; 242 int mFinalVisibility; 243 244 public VisibilityAnimListener withFinalVisibility(int visibility) { 245 mFinalVisibility = visibility; 246 return this; 247 } 248 249 @Override 250 public void onAnimationStart(Animator animation) { 251 setVisibility(VISIBLE); 252 mVisibilityAnim = animation; 253 mCanceled = false; 254 } 255 256 @Override 257 public void onAnimationEnd(Animator animation) { 258 if (mCanceled) return; 259 260 mVisibilityAnim = null; 261 setVisibility(mFinalVisibility); 262 if (mSplitView != null && mMenuView != null) { 263 mMenuView.setVisibility(mFinalVisibility); 264 } 265 } 266 267 @Override 268 public void onAnimationCancel(Animator animation) { 269 mCanceled = true; 270 } 271 272 @Override 273 public void onAnimationRepeat(Animator animation) { 274 } 275 } 276} 277