blob: 4cfc9dc7f305e4bdb506471542d5d1c648a9877e [file] [log] [blame]
Jim Miller19a52672012-10-23 19:52:04 -07001/*
2 * Copyright (C) 2012 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
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
Adam Powell9d34f9d2012-11-06 15:25:05 -080018
Chris Wrenc3451462012-10-30 11:22:58 -040019import android.animation.Animator;
Chris Wrenc3451462012-10-30 11:22:58 -040020import android.animation.AnimatorListenerAdapter;
21import android.animation.ObjectAnimator;
Jim Miller19a52672012-10-23 19:52:04 -070022import android.content.Context;
Adam Powell9d34f9d2012-11-06 15:25:05 -080023import android.content.res.Resources;
Jim Miller19a52672012-10-23 19:52:04 -070024import android.content.res.TypedArray;
25import android.graphics.Rect;
26import android.util.AttributeSet;
Adam Powell9d34f9d2012-11-06 15:25:05 -080027import android.util.DisplayMetrics;
Jim Miller19a52672012-10-23 19:52:04 -070028import android.view.Gravity;
29import android.view.View;
30import android.view.ViewGroup;
John Spurlock256ae672013-09-26 12:14:33 -040031import android.view.View.MeasureSpec;
Jim Miller19a52672012-10-23 19:52:04 -070032import android.widget.LinearLayout;
33
Jim Miller19a52672012-10-23 19:52:04 -070034public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayout {
35 private static final String TAG = "MultiPaneChallengeLayout";
36
37 final int mOrientation;
Adam Powelleee20932012-10-24 16:26:56 -070038 private boolean mIsBouncing;
Jim Miller19a52672012-10-23 19:52:04 -070039
40 public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
41 public static final int VERTICAL = LinearLayout.VERTICAL;
Winson Chung70c2f872012-11-07 21:47:12 -080042 public static final int ANIMATE_BOUNCE_DURATION = 350;
Jim Miller19a52672012-10-23 19:52:04 -070043
Chris Wrenc3451462012-10-30 11:22:58 -040044 private KeyguardSecurityContainer mChallengeView;
Jim Miller19a52672012-10-23 19:52:04 -070045 private View mUserSwitcherView;
Adam Powelleee20932012-10-24 16:26:56 -070046 private View mScrimView;
Adam Powell0b1b5522012-10-25 13:39:30 -070047 private OnBouncerStateChangedListener mBouncerListener;
Jim Miller19a52672012-10-23 19:52:04 -070048
49 private final Rect mTempRect = new Rect();
Winson Chungc065a5d2012-11-07 17:17:33 -080050 private final Rect mZeroPadding = new Rect();
John Spurlock256ae672013-09-26 12:14:33 -040051 private final Rect mInsets = new Rect();
Adam Powell9d34f9d2012-11-06 15:25:05 -080052
53 private final DisplayMetrics mDisplayMetrics;
Jim Miller19a52672012-10-23 19:52:04 -070054
Adam Powelleee20932012-10-24 16:26:56 -070055 private final OnClickListener mScrimClickListener = new OnClickListener() {
56 @Override
57 public void onClick(View v) {
58 hideBouncer();
59 }
60 };
61
Jim Miller19a52672012-10-23 19:52:04 -070062 public MultiPaneChallengeLayout(Context context) {
63 this(context, null);
64 }
65
66 public MultiPaneChallengeLayout(Context context, AttributeSet attrs) {
67 this(context, attrs, 0);
68 }
69
70 public MultiPaneChallengeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
71 super(context, attrs, defStyleAttr);
72
73 final TypedArray a = context.obtainStyledAttributes(attrs,
74 R.styleable.MultiPaneChallengeLayout, defStyleAttr, 0);
Jim Miller5ecd8112013-01-09 18:50:26 -080075 mOrientation = a.getInt(R.styleable.MultiPaneChallengeLayout_android_orientation,
Jim Miller19a52672012-10-23 19:52:04 -070076 HORIZONTAL);
77 a.recycle();
Adam Powell9d34f9d2012-11-06 15:25:05 -080078
79 final Resources res = getResources();
80 mDisplayMetrics = res.getDisplayMetrics();
Adam Powelleec4fe22012-11-07 18:07:15 -080081
John Spurlockbd957402013-10-03 11:38:39 -040082 setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
Jim Miller19a52672012-10-23 19:52:04 -070083 }
84
John Spurlock256ae672013-09-26 12:14:33 -040085 public void setInsets(Rect insets) {
86 mInsets.set(insets);
87 }
88
Jim Miller19a52672012-10-23 19:52:04 -070089 @Override
90 public boolean isChallengeShowing() {
91 return true;
92 }
93
94 @Override
95 public boolean isChallengeOverlapping() {
96 return false;
97 }
98
99 @Override
100 public void showChallenge(boolean b) {
101 }
102
103 @Override
Winson Chung70c2f872012-11-07 21:47:12 -0800104 public int getBouncerAnimationDuration() {
105 return ANIMATE_BOUNCE_DURATION;
106 }
107
108 @Override
Jim Miller19a52672012-10-23 19:52:04 -0700109 public void showBouncer() {
Adam Powelleee20932012-10-24 16:26:56 -0700110 if (mIsBouncing) return;
111 mIsBouncing = true;
112 if (mScrimView != null) {
Chris Wrenc3451462012-10-30 11:22:58 -0400113 if (mChallengeView != null) {
114 mChallengeView.showBouncer(ANIMATE_BOUNCE_DURATION);
115 }
116
117 Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 1f);
118 anim.setDuration(ANIMATE_BOUNCE_DURATION);
119 anim.addListener(new AnimatorListenerAdapter() {
120 @Override
121 public void onAnimationStart(Animator animation) {
122 mScrimView.setVisibility(VISIBLE);
123 }
124 });
125 anim.start();
Adam Powelleee20932012-10-24 16:26:56 -0700126 }
Adam Powell0b1b5522012-10-25 13:39:30 -0700127 if (mBouncerListener != null) {
128 mBouncerListener.onBouncerStateChanged(true);
129 }
Adam Powelleee20932012-10-24 16:26:56 -0700130 }
131
132 @Override
133 public void hideBouncer() {
134 if (!mIsBouncing) return;
135 mIsBouncing = false;
136 if (mScrimView != null) {
Chris Wrenc3451462012-10-30 11:22:58 -0400137 if (mChallengeView != null) {
138 mChallengeView.hideBouncer(ANIMATE_BOUNCE_DURATION);
139 }
140
141 Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 0f);
142 anim.setDuration(ANIMATE_BOUNCE_DURATION);
143 anim.addListener(new AnimatorListenerAdapter() {
144 @Override
145 public void onAnimationEnd(Animator animation) {
146 mScrimView.setVisibility(INVISIBLE);
147 }
148 });
149 anim.start();
Adam Powelleee20932012-10-24 16:26:56 -0700150 }
Adam Powell0b1b5522012-10-25 13:39:30 -0700151 if (mBouncerListener != null) {
152 mBouncerListener.onBouncerStateChanged(false);
153 }
Adam Powelleee20932012-10-24 16:26:56 -0700154 }
155
156 @Override
157 public boolean isBouncing() {
158 return mIsBouncing;
159 }
160
Adam Powell0b1b5522012-10-25 13:39:30 -0700161 @Override
162 public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
163 mBouncerListener = listener;
164 }
165
166 @Override
167 public void requestChildFocus(View child, View focused) {
168 if (mIsBouncing && child != mChallengeView) {
169 // Clear out of the bouncer if the user tries to move focus outside of
170 // the security challenge view.
171 hideBouncer();
172 }
173 super.requestChildFocus(child, focused);
174 }
175
Adam Powelleee20932012-10-24 16:26:56 -0700176 void setScrimView(View scrim) {
177 if (mScrimView != null) {
178 mScrimView.setOnClickListener(null);
179 }
180 mScrimView = scrim;
John Spurlock257f2832013-09-21 18:41:53 -0400181 if (mScrimView != null) {
182 mScrimView.setAlpha(mIsBouncing ? 1.0f : 0.0f);
183 mScrimView.setVisibility(mIsBouncing ? VISIBLE : INVISIBLE);
184 mScrimView.setFocusable(true);
185 mScrimView.setOnClickListener(mScrimClickListener);
186 }
Jim Miller19a52672012-10-23 19:52:04 -0700187 }
188
Adam Powell9d34f9d2012-11-06 15:25:05 -0800189 private int getVirtualHeight(LayoutParams lp, int height, int heightUsed) {
190 int virtualHeight = height;
191 final View root = getRootView();
192 if (root != null) {
193 // This calculation is super dodgy and relies on several assumptions.
194 // Specifically that the root of the window will be padded in for insets
195 // and that the window is LAYOUT_IN_SCREEN.
John Spurlock256ae672013-09-26 12:14:33 -0400196 virtualHeight = mDisplayMetrics.heightPixels - root.getPaddingTop() - mInsets.top;
Adam Powell9d34f9d2012-11-06 15:25:05 -0800197 }
Alan Viverette0cec85b2013-10-10 17:46:03 -0700198 if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
199 // Always measure the user switcher as if there were no IME insets
200 // on the window.
Adam Powell9d34f9d2012-11-06 15:25:05 -0800201 return virtualHeight - heightUsed;
Winson Chungc065a5d2012-11-07 17:17:33 -0800202 } else if (lp.childType == LayoutParams.CHILD_TYPE_PAGE_DELETE_DROP_TARGET) {
203 return height;
Adam Powell9d34f9d2012-11-06 15:25:05 -0800204 }
205 return Math.min(virtualHeight - heightUsed, height);
206 }
207
Jim Miller19a52672012-10-23 19:52:04 -0700208 @Override
Adam Powell9d34f9d2012-11-06 15:25:05 -0800209 protected void onMeasure(final int widthSpec, final int heightSpec) {
Jim Miller19a52672012-10-23 19:52:04 -0700210 if (MeasureSpec.getMode(widthSpec) != MeasureSpec.EXACTLY ||
211 MeasureSpec.getMode(heightSpec) != MeasureSpec.EXACTLY) {
212 throw new IllegalArgumentException(
213 "MultiPaneChallengeLayout must be measured with an exact size");
214 }
215
216 final int width = MeasureSpec.getSize(widthSpec);
217 final int height = MeasureSpec.getSize(heightSpec);
218 setMeasuredDimension(width, height);
219
John Spurlock256ae672013-09-26 12:14:33 -0400220 final int insetHeight = height - mInsets.top - mInsets.bottom;
221 final int insetHeightSpec = MeasureSpec.makeMeasureSpec(insetHeight, MeasureSpec.EXACTLY);
222
Jim Miller19a52672012-10-23 19:52:04 -0700223 int widthUsed = 0;
224 int heightUsed = 0;
225
226 // First pass. Find the challenge view and measure the user switcher,
227 // which consumes space in the layout.
228 mChallengeView = null;
229 mUserSwitcherView = null;
230 final int count = getChildCount();
231 for (int i = 0; i < count; i++) {
232 final View child = getChildAt(i);
233 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
234
235 if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
236 if (mChallengeView != null) {
237 throw new IllegalStateException(
238 "There may only be one child of type challenge");
239 }
Chris Wrenc3451462012-10-30 11:22:58 -0400240 if (!(child instanceof KeyguardSecurityContainer)) {
241 throw new IllegalArgumentException(
242 "Challenge must be a KeyguardSecurityContainer");
243 }
244 mChallengeView = (KeyguardSecurityContainer) child;
Jim Miller19a52672012-10-23 19:52:04 -0700245 } else if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
246 if (mUserSwitcherView != null) {
247 throw new IllegalStateException(
248 "There may only be one child of type userSwitcher");
249 }
250 mUserSwitcherView = child;
251
252 if (child.getVisibility() == GONE) continue;
253
Adam Powell9d34f9d2012-11-06 15:25:05 -0800254 int adjustedWidthSpec = widthSpec;
John Spurlock256ae672013-09-26 12:14:33 -0400255 int adjustedHeightSpec = insetHeightSpec;
Adam Powell9d34f9d2012-11-06 15:25:05 -0800256 if (lp.maxWidth >= 0) {
257 adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
258 Math.min(lp.maxWidth, width), MeasureSpec.EXACTLY);
259 }
260 if (lp.maxHeight >= 0) {
261 adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
John Spurlock256ae672013-09-26 12:14:33 -0400262 Math.min(lp.maxHeight, insetHeight), MeasureSpec.EXACTLY);
Adam Powell9d34f9d2012-11-06 15:25:05 -0800263 }
264 // measureChildWithMargins will resolve layout direction for the LayoutParams
265 measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
266
267 // Only subtract out space from one dimension. Favor vertical.
268 // Offset by 1.5x to add some balance along the other edge.
269 if (Gravity.isVertical(lp.gravity)) {
270 heightUsed += child.getMeasuredHeight() * 1.5f;
271 } else if (Gravity.isHorizontal(lp.gravity)) {
272 widthUsed += child.getMeasuredWidth() * 1.5f;
Jim Miller19a52672012-10-23 19:52:04 -0700273 }
Adam Powelleee20932012-10-24 16:26:56 -0700274 } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
275 setScrimView(child);
276 child.measure(widthSpec, heightSpec);
Jim Miller19a52672012-10-23 19:52:04 -0700277 }
278 }
279
280 // Second pass. Measure everything that's left.
281 for (int i = 0; i < count; i++) {
282 final View child = getChildAt(i);
283 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
284
285 if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER ||
Adam Powelleee20932012-10-24 16:26:56 -0700286 lp.childType == LayoutParams.CHILD_TYPE_SCRIM ||
Jim Miller19a52672012-10-23 19:52:04 -0700287 child.getVisibility() == GONE) {
288 // Don't need to measure GONE children, and the user switcher was already measured.
289 continue;
290 }
291
John Spurlock256ae672013-09-26 12:14:33 -0400292 final int virtualHeight = getVirtualHeight(lp, insetHeight, heightUsed);
Adam Powell9d34f9d2012-11-06 15:25:05 -0800293
Jim Miller19a52672012-10-23 19:52:04 -0700294 int adjustedWidthSpec;
295 int adjustedHeightSpec;
296 if (lp.centerWithinArea > 0) {
297 if (mOrientation == HORIZONTAL) {
298 adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
Adam Powell0a27c482012-10-26 17:00:52 -0700299 (int) ((width - widthUsed) * lp.centerWithinArea + 0.5f),
300 MeasureSpec.EXACTLY);
Jim Miller19a52672012-10-23 19:52:04 -0700301 adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
Adam Powell9d34f9d2012-11-06 15:25:05 -0800302 virtualHeight, MeasureSpec.EXACTLY);
Adam Powell0a27c482012-10-26 17:00:52 -0700303 } else {
304 adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
Adam Powell9d34f9d2012-11-06 15:25:05 -0800305 width - widthUsed, MeasureSpec.EXACTLY);
Adam Powell0a27c482012-10-26 17:00:52 -0700306 adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
Adam Powell9d34f9d2012-11-06 15:25:05 -0800307 (int) (virtualHeight * lp.centerWithinArea + 0.5f),
Adam Powell0a27c482012-10-26 17:00:52 -0700308 MeasureSpec.EXACTLY);
Jim Miller19a52672012-10-23 19:52:04 -0700309 }
310 } else {
Adam Powell0a27c482012-10-26 17:00:52 -0700311 adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
Adam Powell9d34f9d2012-11-06 15:25:05 -0800312 width - widthUsed, MeasureSpec.EXACTLY);
Adam Powell0a27c482012-10-26 17:00:52 -0700313 adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
Adam Powell9d34f9d2012-11-06 15:25:05 -0800314 virtualHeight, MeasureSpec.EXACTLY);
Jim Miller19a52672012-10-23 19:52:04 -0700315 }
316 if (lp.maxWidth >= 0) {
317 adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
Adam Powell0a27c482012-10-26 17:00:52 -0700318 Math.min(lp.maxWidth, MeasureSpec.getSize(adjustedWidthSpec)),
Jim Miller19a52672012-10-23 19:52:04 -0700319 MeasureSpec.EXACTLY);
320 }
321 if (lp.maxHeight >= 0) {
322 adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
Adam Powell0a27c482012-10-26 17:00:52 -0700323 Math.min(lp.maxHeight, MeasureSpec.getSize(adjustedHeightSpec)),
Jim Miller19a52672012-10-23 19:52:04 -0700324 MeasureSpec.EXACTLY);
325 }
326
Adam Powell0a27c482012-10-26 17:00:52 -0700327 measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
Jim Miller19a52672012-10-23 19:52:04 -0700328 }
329 }
330
331 @Override
332 protected void onLayout(boolean changed, int l, int t, int r, int b) {
333 final Rect padding = mTempRect;
334 padding.left = getPaddingLeft();
335 padding.top = getPaddingTop();
336 padding.right = getPaddingRight();
337 padding.bottom = getPaddingBottom();
338 final int width = r - l;
339 final int height = b - t;
John Spurlock256ae672013-09-26 12:14:33 -0400340 final int insetHeight = height - mInsets.top - mInsets.bottom;
Jim Miller19a52672012-10-23 19:52:04 -0700341
342 // Reserve extra space in layout for the user switcher by modifying
343 // local padding during this layout pass
344 if (mUserSwitcherView != null && mUserSwitcherView.getVisibility() != GONE) {
John Spurlock256ae672013-09-26 12:14:33 -0400345 layoutWithGravity(width, insetHeight, mUserSwitcherView, padding, true);
Jim Miller19a52672012-10-23 19:52:04 -0700346 }
347
348 final int count = getChildCount();
349 for (int i = 0; i < count; i++) {
350 final View child = getChildAt(i);
Winson Chungc065a5d2012-11-07 17:17:33 -0800351 LayoutParams lp = (LayoutParams) child.getLayoutParams();
Jim Miller19a52672012-10-23 19:52:04 -0700352
353 // We did the user switcher above if we have one.
354 if (child == mUserSwitcherView || child.getVisibility() == GONE) continue;
355
Adam Powelleee20932012-10-24 16:26:56 -0700356 if (child == mScrimView) {
357 child.layout(0, 0, width, height);
358 continue;
Winson Chungc065a5d2012-11-07 17:17:33 -0800359 } else if (lp.childType == LayoutParams.CHILD_TYPE_PAGE_DELETE_DROP_TARGET) {
John Spurlock256ae672013-09-26 12:14:33 -0400360 layoutWithGravity(width, insetHeight, child, mZeroPadding, false);
Winson Chungc065a5d2012-11-07 17:17:33 -0800361 continue;
Adam Powelleee20932012-10-24 16:26:56 -0700362 }
363
John Spurlock256ae672013-09-26 12:14:33 -0400364 layoutWithGravity(width, insetHeight, child, padding, false);
Jim Miller19a52672012-10-23 19:52:04 -0700365 }
366 }
367
368 private void layoutWithGravity(int width, int height, View child, Rect padding,
369 boolean adjustPadding) {
370 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
371
Adam Powell9d34f9d2012-11-06 15:25:05 -0800372 final int heightUsed = padding.top + padding.bottom - getPaddingTop() - getPaddingBottom();
373 height = getVirtualHeight(lp, height, heightUsed);
374
Jim Miller19a52672012-10-23 19:52:04 -0700375 final int gravity = Gravity.getAbsoluteGravity(lp.gravity, getLayoutDirection());
376
377 final boolean fixedLayoutSize = lp.centerWithinArea > 0;
378 final boolean fixedLayoutHorizontal = fixedLayoutSize && mOrientation == HORIZONTAL;
379 final boolean fixedLayoutVertical = fixedLayoutSize && mOrientation == VERTICAL;
380
381 final int adjustedWidth;
382 final int adjustedHeight;
383 if (fixedLayoutHorizontal) {
Adam Powellc0657fb2012-10-24 14:00:04 -0700384 final int paddedWidth = width - padding.left - padding.right;
385 adjustedWidth = (int) (paddedWidth * lp.centerWithinArea + 0.5f);
Jim Miller19a52672012-10-23 19:52:04 -0700386 adjustedHeight = height;
387 } else if (fixedLayoutVertical) {
Adam Powelleeb62552012-11-07 14:07:23 -0800388 final int paddedHeight = height - getPaddingTop() - getPaddingBottom();
Jim Miller19a52672012-10-23 19:52:04 -0700389 adjustedWidth = width;
Adam Powellc0657fb2012-10-24 14:00:04 -0700390 adjustedHeight = (int) (paddedHeight * lp.centerWithinArea + 0.5f);
Jim Miller19a52672012-10-23 19:52:04 -0700391 } else {
392 adjustedWidth = width;
393 adjustedHeight = height;
394 }
395
396 final boolean isVertical = Gravity.isVertical(gravity);
397 final boolean isHorizontal = Gravity.isHorizontal(gravity);
398 final int childWidth = child.getMeasuredWidth();
399 final int childHeight = child.getMeasuredHeight();
400
401 int left = padding.left;
402 int top = padding.top;
403 int right = left + childWidth;
404 int bottom = top + childHeight;
405 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
406 case Gravity.TOP:
407 top = fixedLayoutVertical ?
408 padding.top + (adjustedHeight - childHeight) / 2 : padding.top;
409 bottom = top + childHeight;
Adam Powellc0657fb2012-10-24 14:00:04 -0700410 if (adjustPadding && isVertical) {
411 padding.top = bottom;
412 padding.bottom += childHeight / 2;
413 }
Jim Miller19a52672012-10-23 19:52:04 -0700414 break;
415 case Gravity.BOTTOM:
416 bottom = fixedLayoutVertical
Adam Powell97997142012-11-06 21:32:42 -0800417 ? padding.top + height - (adjustedHeight - childHeight) / 2
418 : padding.top + height;
Jim Miller19a52672012-10-23 19:52:04 -0700419 top = bottom - childHeight;
Adam Powellc0657fb2012-10-24 14:00:04 -0700420 if (adjustPadding && isVertical) {
421 padding.bottom = height - top;
422 padding.top += childHeight / 2;
423 }
Jim Miller19a52672012-10-23 19:52:04 -0700424 break;
425 case Gravity.CENTER_VERTICAL:
Adam Powell9d34f9d2012-11-06 15:25:05 -0800426 top = padding.top + (height - childHeight) / 2;
Jim Miller19a52672012-10-23 19:52:04 -0700427 bottom = top + childHeight;
428 break;
429 }
430 switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
431 case Gravity.LEFT:
432 left = fixedLayoutHorizontal ?
433 padding.left + (adjustedWidth - childWidth) / 2 : padding.left;
434 right = left + childWidth;
Adam Powellc0657fb2012-10-24 14:00:04 -0700435 if (adjustPadding && isHorizontal && !isVertical) {
436 padding.left = right;
437 padding.right += childWidth / 2;
438 }
Jim Miller19a52672012-10-23 19:52:04 -0700439 break;
440 case Gravity.RIGHT:
441 right = fixedLayoutHorizontal
442 ? width - padding.right - (adjustedWidth - childWidth) / 2
443 : width - padding.right;
444 left = right - childWidth;
Adam Powellc0657fb2012-10-24 14:00:04 -0700445 if (adjustPadding && isHorizontal && !isVertical) {
446 padding.right = width - left;
447 padding.left += childWidth / 2;
448 }
Jim Miller19a52672012-10-23 19:52:04 -0700449 break;
450 case Gravity.CENTER_HORIZONTAL:
Adam Powellc0657fb2012-10-24 14:00:04 -0700451 final int paddedWidth = width - padding.left - padding.right;
452 left = (paddedWidth - childWidth) / 2;
Jim Miller19a52672012-10-23 19:52:04 -0700453 right = left + childWidth;
454 break;
455 }
John Spurlock256ae672013-09-26 12:14:33 -0400456 top += mInsets.top;
457 bottom += mInsets.top;
Jim Miller19a52672012-10-23 19:52:04 -0700458 child.layout(left, top, right, bottom);
459 }
460
461 @Override
462 public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
463 return new LayoutParams(getContext(), attrs, this);
464 }
465
466 @Override
467 protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
468 return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) :
469 p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams) p) :
470 new LayoutParams(p);
471 }
472
473 @Override
474 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
475 return new LayoutParams();
476 }
477
478 @Override
479 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
480 return p instanceof LayoutParams;
481 }
482
483 public static class LayoutParams extends MarginLayoutParams {
484
485 public float centerWithinArea = 0;
486
487 public int childType = 0;
488
489 public static final int CHILD_TYPE_NONE = 0;
490 public static final int CHILD_TYPE_WIDGET = 1;
491 public static final int CHILD_TYPE_CHALLENGE = 2;
492 public static final int CHILD_TYPE_USER_SWITCHER = 3;
Adam Powelleee20932012-10-24 16:26:56 -0700493 public static final int CHILD_TYPE_SCRIM = 4;
Winson Chungc065a5d2012-11-07 17:17:33 -0800494 public static final int CHILD_TYPE_PAGE_DELETE_DROP_TARGET = 7;
Jim Miller19a52672012-10-23 19:52:04 -0700495
496 public int gravity = Gravity.NO_GRAVITY;
497
498 public int maxWidth = -1;
499 public int maxHeight = -1;
500
501 public LayoutParams() {
502 this(WRAP_CONTENT, WRAP_CONTENT);
503 }
504
505 LayoutParams(Context c, AttributeSet attrs, MultiPaneChallengeLayout parent) {
506 super(c, attrs);
507
508 final TypedArray a = c.obtainStyledAttributes(attrs,
509 R.styleable.MultiPaneChallengeLayout_Layout);
510
511 centerWithinArea = a.getFloat(
512 R.styleable.MultiPaneChallengeLayout_Layout_layout_centerWithinArea, 0);
513 childType = a.getInt(R.styleable.MultiPaneChallengeLayout_Layout_layout_childType,
514 CHILD_TYPE_NONE);
515 gravity = a.getInt(R.styleable.MultiPaneChallengeLayout_Layout_layout_gravity,
516 Gravity.NO_GRAVITY);
517 maxWidth = a.getDimensionPixelSize(
518 R.styleable.MultiPaneChallengeLayout_Layout_layout_maxWidth, -1);
519 maxHeight = a.getDimensionPixelSize(
520 R.styleable.MultiPaneChallengeLayout_Layout_layout_maxHeight, -1);
521
522 // Default gravity settings based on type and parent orientation
523 if (gravity == Gravity.NO_GRAVITY) {
524 if (parent.mOrientation == HORIZONTAL) {
525 switch (childType) {
526 case CHILD_TYPE_WIDGET:
527 gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
528 break;
529 case CHILD_TYPE_CHALLENGE:
530 gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
531 break;
532 case CHILD_TYPE_USER_SWITCHER:
533 gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
534 break;
535 }
536 } else {
537 switch (childType) {
538 case CHILD_TYPE_WIDGET:
539 gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
540 break;
541 case CHILD_TYPE_CHALLENGE:
542 gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
543 break;
544 case CHILD_TYPE_USER_SWITCHER:
545 gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
546 break;
547 }
548 }
549 }
550
551 a.recycle();
552 }
553
554 public LayoutParams(int width, int height) {
555 super(width, height);
556 }
557
558 public LayoutParams(ViewGroup.LayoutParams source) {
559 super(source);
560 }
561
562 public LayoutParams(MarginLayoutParams source) {
563 super(source);
564 }
565
566 public LayoutParams(LayoutParams source) {
567 this((MarginLayoutParams) source);
568
569 centerWithinArea = source.centerWithinArea;
570 childType = source.childType;
571 gravity = source.gravity;
572 maxWidth = source.maxWidth;
573 maxHeight = source.maxHeight;
574 }
575 }
576}