• 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         if (mMenuView != null) {
99             mMenuView.setMaxItemHeight(mContentHeight);
100         }
101         requestLayout();
102     }
103 
getContentHeight()104     public int getContentHeight() {
105         return mContentHeight;
106     }
107 
setSplitView(ActionBarContainer splitView)108     public void setSplitView(ActionBarContainer splitView) {
109         mSplitView = splitView;
110     }
111 
112     /**
113      * @return Current visibility or if animating, the visibility being animated to.
114      */
getAnimatedVisibility()115     public int getAnimatedVisibility() {
116         if (mVisibilityAnim != null) {
117             return mVisAnimListener.mFinalVisibility;
118         }
119         return getVisibility();
120     }
121 
animateToVisibility(int visibility)122     public void animateToVisibility(int visibility) {
123         if (mVisibilityAnim != null) {
124             mVisibilityAnim.cancel();
125         }
126         if (visibility == VISIBLE) {
127             if (getVisibility() != VISIBLE) {
128                 setAlpha(0);
129                 if (mSplitView != null && mMenuView != null) {
130                     mMenuView.setAlpha(0);
131                 }
132             }
133             ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
134             anim.setDuration(FADE_DURATION);
135             anim.setInterpolator(sAlphaInterpolator);
136             if (mSplitView != null && mMenuView != null) {
137                 AnimatorSet set = new AnimatorSet();
138                 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
139                 splitAnim.setDuration(FADE_DURATION);
140                 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
141                 set.play(anim).with(splitAnim);
142                 set.start();
143             } else {
144                 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
145                 anim.start();
146             }
147         } else {
148             ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
149             anim.setDuration(FADE_DURATION);
150             anim.setInterpolator(sAlphaInterpolator);
151             if (mSplitView != null && mMenuView != null) {
152                 AnimatorSet set = new AnimatorSet();
153                 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
154                 splitAnim.setDuration(FADE_DURATION);
155                 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
156                 set.play(anim).with(splitAnim);
157                 set.start();
158             } else {
159                 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
160                 anim.start();
161             }
162         }
163     }
164 
165     @Override
setVisibility(int visibility)166     public void setVisibility(int visibility) {
167         if (visibility != getVisibility()) {
168             if (mVisibilityAnim != null) {
169                 mVisibilityAnim.end();
170             }
171             super.setVisibility(visibility);
172         }
173     }
174 
showOverflowMenu()175     public boolean showOverflowMenu() {
176         if (mActionMenuPresenter != null) {
177             return mActionMenuPresenter.showOverflowMenu();
178         }
179         return false;
180     }
181 
postShowOverflowMenu()182     public void postShowOverflowMenu() {
183         post(new Runnable() {
184             public void run() {
185                 showOverflowMenu();
186             }
187         });
188     }
189 
hideOverflowMenu()190     public boolean hideOverflowMenu() {
191         if (mActionMenuPresenter != null) {
192             return mActionMenuPresenter.hideOverflowMenu();
193         }
194         return false;
195     }
196 
isOverflowMenuShowing()197     public boolean isOverflowMenuShowing() {
198         if (mActionMenuPresenter != null) {
199             return mActionMenuPresenter.isOverflowMenuShowing();
200         }
201         return false;
202     }
203 
isOverflowMenuShowPending()204     public boolean isOverflowMenuShowPending() {
205         if (mActionMenuPresenter != null) {
206             return mActionMenuPresenter.isOverflowMenuShowPending();
207         }
208         return false;
209     }
210 
isOverflowReserved()211     public boolean isOverflowReserved() {
212         return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
213     }
214 
dismissPopupMenus()215     public void dismissPopupMenus() {
216         if (mActionMenuPresenter != null) {
217             mActionMenuPresenter.dismissPopupMenus();
218         }
219     }
220 
measureChildView(View child, int availableWidth, int childSpecHeight, int spacing)221     protected int measureChildView(View child, int availableWidth, int childSpecHeight,
222             int spacing) {
223         child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
224                 childSpecHeight);
225 
226         availableWidth -= child.getMeasuredWidth();
227         availableWidth -= spacing;
228 
229         return Math.max(0, availableWidth);
230     }
231 
next(int x, int val, boolean isRtl)232     static protected int next(int x, int val, boolean isRtl) {
233         return isRtl ? x - val : x + val;
234     }
235 
positionChild(View child, int x, int y, int contentHeight, boolean reverse)236     protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
237         int childWidth = child.getMeasuredWidth();
238         int childHeight = child.getMeasuredHeight();
239         int childTop = y + (contentHeight - childHeight) / 2;
240 
241         if (reverse) {
242             child.layout(x - childWidth, childTop, x, childTop + childHeight);
243         } else {
244             child.layout(x, childTop, x + childWidth, childTop + childHeight);
245         }
246 
247         return  (reverse ? -childWidth : childWidth);
248     }
249 
250     protected class VisibilityAnimListener implements Animator.AnimatorListener {
251         private boolean mCanceled = false;
252         int mFinalVisibility;
253 
withFinalVisibility(int visibility)254         public VisibilityAnimListener withFinalVisibility(int visibility) {
255             mFinalVisibility = visibility;
256             return this;
257         }
258 
259         @Override
onAnimationStart(Animator animation)260         public void onAnimationStart(Animator animation) {
261             setVisibility(VISIBLE);
262             mVisibilityAnim = animation;
263             mCanceled = false;
264         }
265 
266         @Override
onAnimationEnd(Animator animation)267         public void onAnimationEnd(Animator animation) {
268             if (mCanceled) return;
269 
270             mVisibilityAnim = null;
271             setVisibility(mFinalVisibility);
272             if (mSplitView != null && mMenuView != null) {
273                 mMenuView.setVisibility(mFinalVisibility);
274             }
275         }
276 
277         @Override
onAnimationCancel(Animator animation)278         public void onAnimationCancel(Animator animation) {
279             mCanceled = true;
280         }
281 
282         @Override
onAnimationRepeat(Animator animation)283         public void onAnimationRepeat(Animator animation) {
284         }
285     }
286 }
287