blob: f3891c7577c51ab3d86db49b048b2f44cd15f64e [file] [log] [blame]
Adam Powell640a66e2011-04-29 10:18:53 -07001/*
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
Adam Powell425689e2011-09-08 18:09:33 -070018import com.android.internal.R;
Adam Powell640a66e2011-04-29 10:18:53 -070019import 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;
Adam Powell425689e2011-09-08 18:09:33 -070027import android.content.res.Configuration;
28import android.content.res.TypedArray;
Adam Powell640a66e2011-04-29 10:18:53 -070029import 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;
Adam Powell8d02dea2011-05-31 21:35:13 -070036 protected ActionMenuPresenter mActionMenuPresenter;
Adam Powell640a66e2011-04-29 10:18:53 -070037 protected ActionBarContainer mSplitView;
Adam Powella05aba92011-09-23 14:22:49 -070038 protected boolean mSplitActionBar;
39 protected boolean mSplitWhenNarrow;
Adam Powell425689e2011-09-08 18:09:33 -070040 protected int mContentHeight;
Adam Powell640a66e2011-04-29 10:18:53 -070041
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
Adam Powell425689e2011-09-08 18:09:33 -070061 @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();
Adam Powella05aba92011-09-23 14:22:49 -070071 if (mSplitWhenNarrow) {
72 setSplitActionBar(getContext().getResources().getBoolean(
73 com.android.internal.R.bool.split_action_bar_is_narrow));
74 }
Adam Powell425689e2011-09-08 18:09:33 -070075 if (mActionMenuPresenter != null) {
76 mActionMenuPresenter.onConfigurationChanged(newConfig);
77 }
78 }
79
Adam Powella05aba92011-09-23 14:22:49 -070080 /**
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
Adam Powell425689e2011-09-08 18:09:33 -070096 public void setContentHeight(int height) {
97 mContentHeight = height;
Adam Powelld5c81db2012-08-02 14:35:26 -070098 if (mMenuView != null) {
99 mMenuView.setMaxItemHeight(mContentHeight);
100 }
Adam Powell425689e2011-09-08 18:09:33 -0700101 requestLayout();
102 }
103
104 public int getContentHeight() {
105 return mContentHeight;
106 }
107
Adam Powell640a66e2011-04-29 10:18:53 -0700108 public void setSplitView(ActionBarContainer splitView) {
109 mSplitView = splitView;
110 }
111
Adam Powell9a5cc282011-08-28 16:18:16 -0700112 /**
113 * @return Current visibility or if animating, the visibility being animated to.
114 */
115 public int getAnimatedVisibility() {
116 if (mVisibilityAnim != null) {
117 return mVisAnimListener.mFinalVisibility;
118 }
119 return getVisibility();
120 }
121
Adam Powell640a66e2011-04-29 10:18:53 -0700122 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);
Adam Powell5c1cb192011-05-05 18:42:16 -0700142 set.start();
Adam Powell640a66e2011-04-29 10:18:53 -0700143 } 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);
Adam Powell5c1cb192011-05-05 18:42:16 -0700157 set.start();
Adam Powell640a66e2011-04-29 10:18:53 -0700158 } else {
159 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
160 anim.start();
161 }
162 }
163 }
164
165 @Override
166 public void setVisibility(int visibility) {
George Mount9caeb142012-04-19 14:33:34 -0700167 if (visibility != getVisibility()) {
168 if (mVisibilityAnim != null) {
169 mVisibilityAnim.end();
170 }
171 super.setVisibility(visibility);
Adam Powell640a66e2011-04-29 10:18:53 -0700172 }
Adam Powell640a66e2011-04-29 10:18:53 -0700173 }
174
175 public boolean showOverflowMenu() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700176 if (mActionMenuPresenter != null) {
177 return mActionMenuPresenter.showOverflowMenu();
Adam Powell640a66e2011-04-29 10:18:53 -0700178 }
179 return false;
180 }
181
182 public void postShowOverflowMenu() {
183 post(new Runnable() {
184 public void run() {
185 showOverflowMenu();
186 }
187 });
188 }
189
190 public boolean hideOverflowMenu() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700191 if (mActionMenuPresenter != null) {
192 return mActionMenuPresenter.hideOverflowMenu();
Adam Powell640a66e2011-04-29 10:18:53 -0700193 }
194 return false;
195 }
196
197 public boolean isOverflowMenuShowing() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700198 if (mActionMenuPresenter != null) {
199 return mActionMenuPresenter.isOverflowMenuShowing();
Adam Powell640a66e2011-04-29 10:18:53 -0700200 }
201 return false;
202 }
203
Adam Powell5fcf5b92013-09-11 08:45:36 -0700204 public boolean isOverflowMenuShowPending() {
205 if (mActionMenuPresenter != null) {
206 return mActionMenuPresenter.isOverflowMenuShowPending();
207 }
208 return false;
209 }
210
Adam Powell640a66e2011-04-29 10:18:53 -0700211 public boolean isOverflowReserved() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700212 return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
Adam Powell640a66e2011-04-29 10:18:53 -0700213 }
214
215 public void dismissPopupMenus() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700216 if (mActionMenuPresenter != null) {
217 mActionMenuPresenter.dismissPopupMenus();
Adam Powell640a66e2011-04-29 10:18:53 -0700218 }
219 }
220
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
Adam Powell5d4034a2011-05-17 13:41:24 -0700229 return Math.max(0, availableWidth);
Adam Powell640a66e2011-04-29 10:18:53 -0700230 }
231
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700232 static protected int next(int x, int val, boolean isRtl) {
233 return isRtl ? x - val : x + val;
Adam Powell640a66e2011-04-29 10:18:53 -0700234 }
235
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700236 protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
Adam Powell640a66e2011-04-29 10:18:53 -0700237 int childWidth = child.getMeasuredWidth();
238 int childHeight = child.getMeasuredHeight();
239 int childTop = y + (contentHeight - childHeight) / 2;
240
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700241 if (reverse) {
242 child.layout(x - childWidth, childTop, x, childTop + childHeight);
243 } else {
244 child.layout(x, childTop, x + childWidth, childTop + childHeight);
245 }
Adam Powell640a66e2011-04-29 10:18:53 -0700246
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700247 return (reverse ? -childWidth : childWidth);
Adam Powell640a66e2011-04-29 10:18:53 -0700248 }
249
250 protected class VisibilityAnimListener implements Animator.AnimatorListener {
251 private boolean mCanceled = false;
Adam Powell9a5cc282011-08-28 16:18:16 -0700252 int mFinalVisibility;
Adam Powell640a66e2011-04-29 10:18:53 -0700253
254 public VisibilityAnimListener withFinalVisibility(int visibility) {
255 mFinalVisibility = visibility;
256 return this;
257 }
258
259 @Override
260 public void onAnimationStart(Animator animation) {
261 setVisibility(VISIBLE);
262 mVisibilityAnim = animation;
263 mCanceled = false;
264 }
265
266 @Override
267 public void onAnimationEnd(Animator animation) {
268 if (mCanceled) return;
269
270 mVisibilityAnim = null;
271 setVisibility(mFinalVisibility);
Adam Powell9a5cc282011-08-28 16:18:16 -0700272 if (mSplitView != null && mMenuView != null) {
273 mMenuView.setVisibility(mFinalVisibility);
274 }
Adam Powell640a66e2011-04-29 10:18:53 -0700275 }
276
277 @Override
278 public void onAnimationCancel(Animator animation) {
279 mCanceled = true;
280 }
281
282 @Override
283 public void onAnimationRepeat(Animator animation) {
284 }
285 }
286}