• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
16 package com.android.internal.widget;
17 
18 import com.android.internal.R;
19 import com.android.internal.view.menu.ActionMenuPresenter;
20 import com.android.internal.view.menu.ActionMenuView;
21 
22 import android.animation.Animator;
23 import android.animation.AnimatorSet;
24 import android.animation.ObjectAnimator;
25 import android.animation.TimeInterpolator;
26 import android.content.Context;
27 import android.content.res.Configuration;
28 import android.content.res.TypedArray;
29 import android.util.AttributeSet;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.view.animation.DecelerateInterpolator;
33 
34 public 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 
AbsActionBarView(Context context)49     public AbsActionBarView(Context context) {
50         super(context);
51     }
52 
AbsActionBarView(Context context, AttributeSet attrs)53     public AbsActionBarView(Context context, AttributeSet attrs) {
54         super(context, attrs);
55     }
56 
AbsActionBarView(Context context, AttributeSet attrs, int defStyle)57     public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) {
58         super(context, attrs, defStyle);
59     }
60 
61     @Override
onConfigurationChanged(Configuration newConfig)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      */
setSplitActionBar(boolean split)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      */
setSplitWhenNarrow(boolean splitWhenNarrow)92     public void setSplitWhenNarrow(boolean splitWhenNarrow) {
93         mSplitWhenNarrow = splitWhenNarrow;
94     }
95 
setContentHeight(int height)96     public void setContentHeight(int height) {
97         mContentHeight = height;
98         requestLayout();
99     }
100 
getContentHeight()101     public int getContentHeight() {
102         return mContentHeight;
103     }
104 
setSplitView(ActionBarContainer splitView)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      */
getAnimatedVisibility()112     public int getAnimatedVisibility() {
113         if (mVisibilityAnim != null) {
114             return mVisAnimListener.mFinalVisibility;
115         }
116         return getVisibility();
117     }
118 
animateToVisibility(int visibility)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
setVisibility(int visibility)163     public void setVisibility(int visibility) {
164         if (visibility != getVisibility()) {
165             if (mVisibilityAnim != null) {
166                 mVisibilityAnim.end();
167             }
168             super.setVisibility(visibility);
169         }
170     }
171 
showOverflowMenu()172     public boolean showOverflowMenu() {
173         if (mActionMenuPresenter != null) {
174             return mActionMenuPresenter.showOverflowMenu();
175         }
176         return false;
177     }
178 
postShowOverflowMenu()179     public void postShowOverflowMenu() {
180         post(new Runnable() {
181             public void run() {
182                 showOverflowMenu();
183             }
184         });
185     }
186 
hideOverflowMenu()187     public boolean hideOverflowMenu() {
188         if (mActionMenuPresenter != null) {
189             return mActionMenuPresenter.hideOverflowMenu();
190         }
191         return false;
192     }
193 
isOverflowMenuShowing()194     public boolean isOverflowMenuShowing() {
195         if (mActionMenuPresenter != null) {
196             return mActionMenuPresenter.isOverflowMenuShowing();
197         }
198         return false;
199     }
200 
isOverflowReserved()201     public boolean isOverflowReserved() {
202         return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
203     }
204 
dismissPopupMenus()205     public void dismissPopupMenus() {
206         if (mActionMenuPresenter != null) {
207             mActionMenuPresenter.dismissPopupMenus();
208         }
209     }
210 
measureChildView(View child, int availableWidth, int childSpecHeight, int spacing)211     protected int measureChildView(View child, int availableWidth, int childSpecHeight,
212             int spacing) {
213         child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
214                 childSpecHeight);
215 
216         availableWidth -= child.getMeasuredWidth();
217         availableWidth -= spacing;
218 
219         return Math.max(0, availableWidth);
220     }
221 
positionChild(View child, int x, int y, int contentHeight)222     protected int positionChild(View child, int x, int y, int contentHeight) {
223         int childWidth = child.getMeasuredWidth();
224         int childHeight = child.getMeasuredHeight();
225         int childTop = y + (contentHeight - childHeight) / 2;
226 
227         child.layout(x, childTop, x + childWidth, childTop + childHeight);
228 
229         return childWidth;
230     }
231 
positionChildInverse(View child, int x, int y, int contentHeight)232     protected int positionChildInverse(View child, int x, int y, int contentHeight) {
233         int childWidth = child.getMeasuredWidth();
234         int childHeight = child.getMeasuredHeight();
235         int childTop = y + (contentHeight - childHeight) / 2;
236 
237         child.layout(x - childWidth, childTop, x, childTop + childHeight);
238 
239         return childWidth;
240     }
241 
242     protected class VisibilityAnimListener implements Animator.AnimatorListener {
243         private boolean mCanceled = false;
244         int mFinalVisibility;
245 
withFinalVisibility(int visibility)246         public VisibilityAnimListener withFinalVisibility(int visibility) {
247             mFinalVisibility = visibility;
248             return this;
249         }
250 
251         @Override
onAnimationStart(Animator animation)252         public void onAnimationStart(Animator animation) {
253             setVisibility(VISIBLE);
254             mVisibilityAnim = animation;
255             mCanceled = false;
256         }
257 
258         @Override
onAnimationEnd(Animator animation)259         public void onAnimationEnd(Animator animation) {
260             if (mCanceled) return;
261 
262             mVisibilityAnim = null;
263             setVisibility(mFinalVisibility);
264             if (mSplitView != null && mMenuView != null) {
265                 mMenuView.setVisibility(mFinalVisibility);
266             }
267         }
268 
269         @Override
onAnimationCancel(Animator animation)270         public void onAnimationCancel(Animator animation) {
271             mCanceled = true;
272         }
273 
274         @Override
onAnimationRepeat(Animator animation)275         public void onAnimationRepeat(Animator animation) {
276         }
277     }
278 }
279