2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.actionbarsherlock.internal.widget;
18 import android.content.Context;
19 import android.content.res.Configuration;
20 import android.content.res.TypedArray;
21 import android.os.Build;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.animation.DecelerateInterpolator;
25 import android.view.animation.Interpolator;
27 import com.actionbarsherlock.R;
28 import com.actionbarsherlock.internal.nineoldandroids.animation.Animator;
29 import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet;
30 import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator;
31 import com.actionbarsherlock.internal.nineoldandroids.view.NineViewGroup;
32 import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter;
33 import com.actionbarsherlock.internal.view.menu.ActionMenuView;
35 import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean;
37 public abstract class AbsActionBarView extends NineViewGroup {
38 protected ActionMenuView mMenuView;
39 protected ActionMenuPresenter mActionMenuPresenter;
40 protected ActionBarContainer mSplitView;
41 protected boolean mSplitActionBar;
42 protected boolean mSplitWhenNarrow;
43 protected int mContentHeight;
45 final Context mContext;
47 protected Animator mVisibilityAnim;
48 protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
50 private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator();
52 private static final int FADE_DURATION = 200;
54 public AbsActionBarView(Context context) {
59 public AbsActionBarView(Context context, AttributeSet attrs) {
60 super(context, attrs);
64 public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) {
65 super(context, attrs, defStyle);
70 * Must be public so we can dispatch pre-2.2 via ActionBarImpl.
73 public void onConfigurationChanged(Configuration newConfig) {
74 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
75 super.onConfigurationChanged(newConfig);
76 } else if (mMenuView != null) {
77 mMenuView.onConfigurationChanged(newConfig);
80 // Action bar can change size on configuration changes.
81 // Reread the desired height from the theme-specified style.
82 TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar,
83 R.attr.actionBarStyle, 0);
84 setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0));
86 if (mSplitWhenNarrow) {
87 setSplitActionBar(getResources_getBoolean(getContext(),
88 R.bool.abs__split_action_bar_is_narrow));
90 if (mActionMenuPresenter != null) {
91 mActionMenuPresenter.onConfigurationChanged(newConfig);
96 * Sets whether the bar should be split right now, no questions asked.
97 * @param split true if the bar should split
99 public void setSplitActionBar(boolean split) {
100 mSplitActionBar = split;
104 * Sets whether the bar should split if we enter a narrow screen configuration.
105 * @param splitWhenNarrow true if the bar should check to split after a config change
107 public void setSplitWhenNarrow(boolean splitWhenNarrow) {
108 mSplitWhenNarrow = splitWhenNarrow;
111 public void setContentHeight(int height) {
112 mContentHeight = height;
116 public int getContentHeight() {
117 return mContentHeight;
120 public void setSplitView(ActionBarContainer splitView) {
121 mSplitView = splitView;
125 * @return Current visibility or if animating, the visibility being animated to.
127 public int getAnimatedVisibility() {
128 if (mVisibilityAnim != null) {
129 return mVisAnimListener.mFinalVisibility;
131 return getVisibility();
134 public void animateToVisibility(int visibility) {
135 if (mVisibilityAnim != null) {
136 mVisibilityAnim.cancel();
138 if (visibility == VISIBLE) {
139 if (getVisibility() != VISIBLE) {
141 if (mSplitView != null && mMenuView != null) {
142 mMenuView.setAlpha(0);
145 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
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", 1);
151 splitAnim.setDuration(FADE_DURATION);
152 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
153 set.play(anim).with(splitAnim);
156 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
160 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
161 anim.setDuration(FADE_DURATION);
162 anim.setInterpolator(sAlphaInterpolator);
163 if (mSplitView != null && mMenuView != null) {
164 AnimatorSet set = new AnimatorSet();
165 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
166 splitAnim.setDuration(FADE_DURATION);
167 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
168 set.play(anim).with(splitAnim);
171 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
178 public void setVisibility(int visibility) {
179 if (mVisibilityAnim != null) {
180 mVisibilityAnim.end();
182 super.setVisibility(visibility);
185 public boolean showOverflowMenu() {
186 if (mActionMenuPresenter != null) {
187 return mActionMenuPresenter.showOverflowMenu();
192 public void postShowOverflowMenu() {
193 post(new Runnable() {
200 public boolean hideOverflowMenu() {
201 if (mActionMenuPresenter != null) {
202 return mActionMenuPresenter.hideOverflowMenu();
207 public boolean isOverflowMenuShowing() {
208 if (mActionMenuPresenter != null) {
209 return mActionMenuPresenter.isOverflowMenuShowing();
214 public boolean isOverflowReserved() {
215 return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
218 public void dismissPopupMenus() {
219 if (mActionMenuPresenter != null) {
220 mActionMenuPresenter.dismissPopupMenus();
224 protected int measureChildView(View child, int availableWidth, int childSpecHeight,
226 child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
229 availableWidth -= child.getMeasuredWidth();
230 availableWidth -= spacing;
232 return Math.max(0, availableWidth);
235 protected int positionChild(View child, int x, int y, int contentHeight) {
236 int childWidth = child.getMeasuredWidth();
237 int childHeight = child.getMeasuredHeight();
238 int childTop = y + (contentHeight - childHeight) / 2;
240 child.layout(x, childTop, x + childWidth, childTop + childHeight);
245 protected int positionChildInverse(View child, int x, int y, int contentHeight) {
246 int childWidth = child.getMeasuredWidth();
247 int childHeight = child.getMeasuredHeight();
248 int childTop = y + (contentHeight - childHeight) / 2;
250 child.layout(x - childWidth, childTop, x, childTop + childHeight);
255 protected class VisibilityAnimListener implements Animator.AnimatorListener {
256 private boolean mCanceled = false;
257 int mFinalVisibility;
259 public VisibilityAnimListener withFinalVisibility(int visibility) {
260 mFinalVisibility = visibility;
265 public void onAnimationStart(Animator animation) {
266 setVisibility(VISIBLE);
267 mVisibilityAnim = animation;
272 public void onAnimationEnd(Animator animation) {
273 if (mCanceled) return;
275 mVisibilityAnim = null;
276 setVisibility(mFinalVisibility);
277 if (mSplitView != null && mMenuView != null) {
278 mMenuView.setVisibility(mFinalVisibility);
283 public void onAnimationCancel(Animator animation) {
288 public void onAnimationRepeat(Animator animation) {