blob: 183478faca52af4eb5a9c9c86cc5dd11772bfbfa [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 Powellfa18d182014-01-07 15:56:59 -080019import android.widget.ActionMenuPresenter;
20import android.widget.ActionMenuView;
Adam Powell640a66e2011-04-29 10:18:53 -070021
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) {
Alan Viveretted6479ec2013-09-10 17:03:02 -070050 this(context, null);
Adam Powell640a66e2011-04-29 10:18:53 -070051 }
52
53 public AbsActionBarView(Context context, AttributeSet attrs) {
Alan Viveretted6479ec2013-09-10 17:03:02 -070054 this(context, attrs, 0);
Adam Powell640a66e2011-04-29 10:18:53 -070055 }
56
Alan Viverette617feb92013-09-09 18:09:13 -070057 public AbsActionBarView(Context context, AttributeSet attrs, int defStyleAttr) {
58 this(context, attrs, defStyleAttr, 0);
59 }
60
61 public AbsActionBarView(
62 Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
63 super(context, attrs, defStyleAttr, defStyleRes);
Adam Powell640a66e2011-04-29 10:18:53 -070064 }
65
Adam Powell425689e2011-09-08 18:09:33 -070066 @Override
67 protected void onConfigurationChanged(Configuration newConfig) {
68 super.onConfigurationChanged(newConfig);
69
70 // Action bar can change size on configuration changes.
71 // Reread the desired height from the theme-specified style.
72 TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
73 com.android.internal.R.attr.actionBarStyle, 0);
74 setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
75 a.recycle();
Adam Powella05aba92011-09-23 14:22:49 -070076 if (mSplitWhenNarrow) {
77 setSplitActionBar(getContext().getResources().getBoolean(
78 com.android.internal.R.bool.split_action_bar_is_narrow));
79 }
Adam Powell425689e2011-09-08 18:09:33 -070080 if (mActionMenuPresenter != null) {
81 mActionMenuPresenter.onConfigurationChanged(newConfig);
82 }
83 }
84
Adam Powella05aba92011-09-23 14:22:49 -070085 /**
86 * Sets whether the bar should be split right now, no questions asked.
87 * @param split true if the bar should split
88 */
89 public void setSplitActionBar(boolean split) {
90 mSplitActionBar = split;
91 }
92
93 /**
94 * Sets whether the bar should split if we enter a narrow screen configuration.
95 * @param splitWhenNarrow true if the bar should check to split after a config change
96 */
97 public void setSplitWhenNarrow(boolean splitWhenNarrow) {
98 mSplitWhenNarrow = splitWhenNarrow;
99 }
100
Adam Powell425689e2011-09-08 18:09:33 -0700101 public void setContentHeight(int height) {
102 mContentHeight = height;
103 requestLayout();
104 }
105
106 public int getContentHeight() {
107 return mContentHeight;
108 }
109
Adam Powell640a66e2011-04-29 10:18:53 -0700110 public void setSplitView(ActionBarContainer splitView) {
111 mSplitView = splitView;
112 }
113
Adam Powell9a5cc282011-08-28 16:18:16 -0700114 /**
115 * @return Current visibility or if animating, the visibility being animated to.
116 */
117 public int getAnimatedVisibility() {
118 if (mVisibilityAnim != null) {
119 return mVisAnimListener.mFinalVisibility;
120 }
121 return getVisibility();
122 }
123
Adam Powell640a66e2011-04-29 10:18:53 -0700124 public void animateToVisibility(int visibility) {
125 if (mVisibilityAnim != null) {
126 mVisibilityAnim.cancel();
127 }
128 if (visibility == VISIBLE) {
129 if (getVisibility() != VISIBLE) {
130 setAlpha(0);
131 if (mSplitView != null && mMenuView != null) {
132 mMenuView.setAlpha(0);
133 }
134 }
135 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
136 anim.setDuration(FADE_DURATION);
137 anim.setInterpolator(sAlphaInterpolator);
138 if (mSplitView != null && mMenuView != null) {
139 AnimatorSet set = new AnimatorSet();
140 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
141 splitAnim.setDuration(FADE_DURATION);
142 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
143 set.play(anim).with(splitAnim);
Adam Powell5c1cb192011-05-05 18:42:16 -0700144 set.start();
Adam Powell640a66e2011-04-29 10:18:53 -0700145 } else {
146 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
147 anim.start();
148 }
149 } else {
150 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
151 anim.setDuration(FADE_DURATION);
152 anim.setInterpolator(sAlphaInterpolator);
153 if (mSplitView != null && mMenuView != null) {
154 AnimatorSet set = new AnimatorSet();
155 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
156 splitAnim.setDuration(FADE_DURATION);
157 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
158 set.play(anim).with(splitAnim);
Adam Powell5c1cb192011-05-05 18:42:16 -0700159 set.start();
Adam Powell640a66e2011-04-29 10:18:53 -0700160 } else {
161 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
162 anim.start();
163 }
164 }
165 }
166
167 @Override
168 public void setVisibility(int visibility) {
George Mount9caeb142012-04-19 14:33:34 -0700169 if (visibility != getVisibility()) {
170 if (mVisibilityAnim != null) {
171 mVisibilityAnim.end();
172 }
173 super.setVisibility(visibility);
Adam Powell640a66e2011-04-29 10:18:53 -0700174 }
Adam Powell640a66e2011-04-29 10:18:53 -0700175 }
176
177 public boolean showOverflowMenu() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700178 if (mActionMenuPresenter != null) {
179 return mActionMenuPresenter.showOverflowMenu();
Adam Powell640a66e2011-04-29 10:18:53 -0700180 }
181 return false;
182 }
183
184 public void postShowOverflowMenu() {
185 post(new Runnable() {
186 public void run() {
187 showOverflowMenu();
188 }
189 });
190 }
191
192 public boolean hideOverflowMenu() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700193 if (mActionMenuPresenter != null) {
194 return mActionMenuPresenter.hideOverflowMenu();
Adam Powell640a66e2011-04-29 10:18:53 -0700195 }
196 return false;
197 }
198
199 public boolean isOverflowMenuShowing() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700200 if (mActionMenuPresenter != null) {
201 return mActionMenuPresenter.isOverflowMenuShowing();
Adam Powell640a66e2011-04-29 10:18:53 -0700202 }
203 return false;
204 }
205
Adam Powell5fcf5b92013-09-11 08:45:36 -0700206 public boolean isOverflowMenuShowPending() {
207 if (mActionMenuPresenter != null) {
208 return mActionMenuPresenter.isOverflowMenuShowPending();
209 }
210 return false;
211 }
212
Adam Powell640a66e2011-04-29 10:18:53 -0700213 public boolean isOverflowReserved() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700214 return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
Adam Powell640a66e2011-04-29 10:18:53 -0700215 }
216
217 public void dismissPopupMenus() {
Adam Powell8d02dea2011-05-31 21:35:13 -0700218 if (mActionMenuPresenter != null) {
219 mActionMenuPresenter.dismissPopupMenus();
Adam Powell640a66e2011-04-29 10:18:53 -0700220 }
221 }
222
223 protected int measureChildView(View child, int availableWidth, int childSpecHeight,
224 int spacing) {
225 child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
226 childSpecHeight);
227
228 availableWidth -= child.getMeasuredWidth();
229 availableWidth -= spacing;
230
Adam Powell5d4034a2011-05-17 13:41:24 -0700231 return Math.max(0, availableWidth);
Adam Powell640a66e2011-04-29 10:18:53 -0700232 }
233
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700234 static protected int next(int x, int val, boolean isRtl) {
235 return isRtl ? x - val : x + val;
Adam Powell640a66e2011-04-29 10:18:53 -0700236 }
237
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700238 protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
Adam Powell640a66e2011-04-29 10:18:53 -0700239 int childWidth = child.getMeasuredWidth();
240 int childHeight = child.getMeasuredHeight();
241 int childTop = y + (contentHeight - childHeight) / 2;
242
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700243 if (reverse) {
244 child.layout(x - childWidth, childTop, x, childTop + childHeight);
245 } else {
246 child.layout(x, childTop, x + childWidth, childTop + childHeight);
247 }
Adam Powell640a66e2011-04-29 10:18:53 -0700248
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700249 return (reverse ? -childWidth : childWidth);
Adam Powell640a66e2011-04-29 10:18:53 -0700250 }
251
252 protected class VisibilityAnimListener implements Animator.AnimatorListener {
253 private boolean mCanceled = false;
Adam Powell9a5cc282011-08-28 16:18:16 -0700254 int mFinalVisibility;
Adam Powell640a66e2011-04-29 10:18:53 -0700255
256 public VisibilityAnimListener withFinalVisibility(int visibility) {
257 mFinalVisibility = visibility;
258 return this;
259 }
260
261 @Override
262 public void onAnimationStart(Animator animation) {
263 setVisibility(VISIBLE);
264 mVisibilityAnim = animation;
265 mCanceled = false;
266 }
267
268 @Override
269 public void onAnimationEnd(Animator animation) {
270 if (mCanceled) return;
271
272 mVisibilityAnim = null;
273 setVisibility(mFinalVisibility);
Adam Powell9a5cc282011-08-28 16:18:16 -0700274 if (mSplitView != null && mMenuView != null) {
275 mMenuView.setVisibility(mFinalVisibility);
276 }
Adam Powell640a66e2011-04-29 10:18:53 -0700277 }
278
279 @Override
280 public void onAnimationCancel(Animator animation) {
281 mCanceled = true;
282 }
283
284 @Override
285 public void onAnimationRepeat(Animator animation) {
286 }
287 }
288}