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