blob: 860a8d9e51c30909463a70d441b9acb5279909ab [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;
98 requestLayout();
99 }
100
101 public int getContentHeight() {
102 return mContentHeight;
103 }
104
Adam Powell640a66e2011-04-29 10:18:53 -0700105 public void setSplitView(ActionBarContainer splitView) {
106 mSplitView = splitView;
107 }
108
Adam Powell9a5cc282011-08-28 16:18:16 -0700109 /**
110 * @return Current visibility or if animating, the visibility being animated to.
111 */
112 public int getAnimatedVisibility() {
113 if (mVisibilityAnim != null) {
114 return mVisAnimListener.mFinalVisibility;
115 }
116 return getVisibility();
117 }
118
Adam Powell640a66e2011-04-29 10:18:53 -0700119 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);
Adam Powell5c1cb192011-05-05 18:42:16 -0700139 set.start();
Adam Powell640a66e2011-04-29 10:18:53 -0700140 } 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);
Adam Powell5c1cb192011-05-05 18:42:16 -0700154 set.start();
Adam Powell640a66e2011-04-29 10:18:53 -0700155 } else {
156 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
157 anim.start();
158 }
159 }
160 }
161
162 @Override
163 public void setVisibility(int visibility) {
George Mount9caeb142012-04-19 14:33:34 -0700164 if (visibility != getVisibility()) {
165 if (mVisibilityAnim != null) {
166 mVisibilityAnim.end();
167 }
168 super.setVisibility(visibility);
Adam Powell640a66e2011-04-29 10:18:53 -0700169 }
Adam Powell640a66e2011-04-29 10:18:53 -0700170 }
171
172 public boolean showOverflowMenu() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700173 if (mActionMenuPresenter != null) {
174 return mActionMenuPresenter.showOverflowMenu();
Adam Powell640a66e2011-04-29 10:18:53 -0700175 }
176 return false;
177 }
178
179 public void postShowOverflowMenu() {
180 post(new Runnable() {
181 public void run() {
182 showOverflowMenu();
183 }
184 });
185 }
186
187 public boolean hideOverflowMenu() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700188 if (mActionMenuPresenter != null) {
189 return mActionMenuPresenter.hideOverflowMenu();
Adam Powell640a66e2011-04-29 10:18:53 -0700190 }
191 return false;
192 }
193
194 public boolean isOverflowMenuShowing() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700195 if (mActionMenuPresenter != null) {
196 return mActionMenuPresenter.isOverflowMenuShowing();
Adam Powell640a66e2011-04-29 10:18:53 -0700197 }
198 return false;
199 }
200
201 public boolean isOverflowReserved() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700202 return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
Adam Powell640a66e2011-04-29 10:18:53 -0700203 }
204
205 public void dismissPopupMenus() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700206 if (mActionMenuPresenter != null) {
207 mActionMenuPresenter.dismissPopupMenus();
Adam Powell640a66e2011-04-29 10:18:53 -0700208 }
209 }
210
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
Adam Powell5d4034a2011-05-17 13:41:24 -0700219 return Math.max(0, availableWidth);
Adam Powell640a66e2011-04-29 10:18:53 -0700220 }
221
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700222 static protected int next(int x, int val, boolean isRtl) {
223 return isRtl ? x - val : x + val;
Adam Powell640a66e2011-04-29 10:18:53 -0700224 }
225
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700226 protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
Adam Powell640a66e2011-04-29 10:18:53 -0700227 int childWidth = child.getMeasuredWidth();
228 int childHeight = child.getMeasuredHeight();
229 int childTop = y + (contentHeight - childHeight) / 2;
230
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700231 if (reverse) {
232 child.layout(x - childWidth, childTop, x, childTop + childHeight);
233 } else {
234 child.layout(x, childTop, x + childWidth, childTop + childHeight);
235 }
Adam Powell640a66e2011-04-29 10:18:53 -0700236
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700237 return (reverse ? -childWidth : childWidth);
Adam Powell640a66e2011-04-29 10:18:53 -0700238 }
239
240 protected class VisibilityAnimListener implements Animator.AnimatorListener {
241 private boolean mCanceled = false;
Adam Powell9a5cc282011-08-28 16:18:16 -0700242 int mFinalVisibility;
Adam Powell640a66e2011-04-29 10:18:53 -0700243
244 public VisibilityAnimListener withFinalVisibility(int visibility) {
245 mFinalVisibility = visibility;
246 return this;
247 }
248
249 @Override
250 public void onAnimationStart(Animator animation) {
251 setVisibility(VISIBLE);
252 mVisibilityAnim = animation;
253 mCanceled = false;
254 }
255
256 @Override
257 public void onAnimationEnd(Animator animation) {
258 if (mCanceled) return;
259
260 mVisibilityAnim = null;
261 setVisibility(mFinalVisibility);
Adam Powell9a5cc282011-08-28 16:18:16 -0700262 if (mSplitView != null && mMenuView != null) {
263 mMenuView.setVisibility(mFinalVisibility);
264 }
Adam Powell640a66e2011-04-29 10:18:53 -0700265 }
266
267 @Override
268 public void onAnimationCancel(Animator animation) {
269 mCanceled = true;
270 }
271
272 @Override
273 public void onAnimationRepeat(Animator animation) {
274 }
275 }
276}