2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 import android.graphics.Rect;
21 * Standard constants and tools for placing an object within a potentially
26 /** Constant indicating that no gravity has been set **/
27 public static final int NO_GRAVITY = 0x0000;
29 /** Raw bit indicating the gravity for an axis has been specified. */
30 public static final int AXIS_SPECIFIED = 0x0001;
32 /** Raw bit controlling how the left/top edge is placed. */
33 public static final int AXIS_PULL_BEFORE = 0x0002;
34 /** Raw bit controlling how the right/bottom edge is placed. */
35 public static final int AXIS_PULL_AFTER = 0x0004;
36 /** Raw bit controlling whether the right/bottom edge is clipped to its
37 * container, based on the gravity direction being applied. */
38 public static final int AXIS_CLIP = 0x0008;
40 /** Bits defining the horizontal axis. */
41 public static final int AXIS_X_SHIFT = 0;
42 /** Bits defining the vertical axis. */
43 public static final int AXIS_Y_SHIFT = 4;
45 /** Push object to the top of its container, not changing its size. */
46 public static final int TOP = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
47 /** Push object to the bottom of its container, not changing its size. */
48 public static final int BOTTOM = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
49 /** Push object to the left of its container, not changing its size. */
50 public static final int LEFT = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
51 /** Push object to the right of its container, not changing its size. */
52 public static final int RIGHT = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
54 /** Place object in the vertical center of its container, not changing its
56 public static final int CENTER_VERTICAL = AXIS_SPECIFIED<<AXIS_Y_SHIFT;
57 /** Grow the vertical size of the object if needed so it completely fills
59 public static final int FILL_VERTICAL = TOP|BOTTOM;
61 /** Place object in the horizontal center of its container, not changing its
63 public static final int CENTER_HORIZONTAL = AXIS_SPECIFIED<<AXIS_X_SHIFT;
64 /** Grow the horizontal size of the object if needed so it completely fills
66 public static final int FILL_HORIZONTAL = LEFT|RIGHT;
68 /** Place the object in the center of its container in both the vertical
69 * and horizontal axis, not changing its size. */
70 public static final int CENTER = CENTER_VERTICAL|CENTER_HORIZONTAL;
72 /** Grow the horizontal and vertical size of the object if needed so it
73 * completely fills its container. */
74 public static final int FILL = FILL_VERTICAL|FILL_HORIZONTAL;
76 /** Flag to clip the edges of the object to its container along the
78 public static final int CLIP_VERTICAL = AXIS_CLIP<<AXIS_Y_SHIFT;
80 /** Flag to clip the edges of the object to its container along the
82 public static final int CLIP_HORIZONTAL = AXIS_CLIP<<AXIS_X_SHIFT;
85 * Binary mask to get the horizontal gravity of a gravity.
87 public static final int HORIZONTAL_GRAVITY_MASK = (AXIS_SPECIFIED |
88 AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_X_SHIFT;
90 * Binary mask to get the vertical gravity of a gravity.
92 public static final int VERTICAL_GRAVITY_MASK = (AXIS_SPECIFIED |
93 AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_Y_SHIFT;
95 /** Special constant to enable clipping to an overall display along the
96 * vertical dimension. This is not applied by default by
97 * {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so
98 * yourself by calling {@link #applyDisplay}.
100 public static final int DISPLAY_CLIP_VERTICAL = 0x10000000;
102 /** Special constant to enable clipping to an overall display along the
103 * horizontal dimension. This is not applied by default by
104 * {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so
105 * yourself by calling {@link #applyDisplay}.
107 public static final int DISPLAY_CLIP_HORIZONTAL = 0x01000000;
110 * Apply a gravity constant to an object.
112 * @param gravity The desired placement of the object, as defined by the
113 * constants in this class.
114 * @param w The horizontal size of the object.
115 * @param h The vertical size of the object.
116 * @param container The frame of the containing space, in which the object
117 * will be placed. Should be large enough to contain the
118 * width and height of the object.
119 * @param outRect Receives the computed frame of the object in its
122 public static void apply(int gravity, int w, int h, Rect container,
124 apply(gravity, w, h, container, 0, 0, outRect);
128 * Apply a gravity constant to an object.
130 * @param gravity The desired placement of the object, as defined by the
131 * constants in this class.
132 * @param w The horizontal size of the object.
133 * @param h The vertical size of the object.
134 * @param container The frame of the containing space, in which the object
135 * will be placed. Should be large enough to contain the
136 * width and height of the object.
137 * @param xAdj Offset to apply to the X axis. If gravity is LEFT this
138 * pushes it to the right; if gravity is RIGHT it pushes it to
139 * the left; if gravity is CENTER_HORIZONTAL it pushes it to the
140 * right or left; otherwise it is ignored.
141 * @param yAdj Offset to apply to the Y axis. If gravity is TOP this pushes
142 * it down; if gravity is BOTTOM it pushes it up; if gravity is
143 * CENTER_VERTICAL it pushes it down or up; otherwise it is
145 * @param outRect Receives the computed frame of the object in its
148 public static void apply(int gravity, int w, int h, Rect container,
149 int xAdj, int yAdj, Rect outRect) {
150 switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT)) {
152 outRect.left = container.left
153 + ((container.right - container.left - w)/2) + xAdj;
154 outRect.right = outRect.left + w;
155 if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
156 == (AXIS_CLIP<<AXIS_X_SHIFT)) {
157 if (outRect.left < container.left) {
158 outRect.left = container.left;
160 if (outRect.right > container.right) {
161 outRect.right = container.right;
165 case AXIS_PULL_BEFORE<<AXIS_X_SHIFT:
166 outRect.left = container.left + xAdj;
167 outRect.right = outRect.left + w;
168 if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
169 == (AXIS_CLIP<<AXIS_X_SHIFT)) {
170 if (outRect.right > container.right) {
171 outRect.right = container.right;
175 case AXIS_PULL_AFTER<<AXIS_X_SHIFT:
176 outRect.right = container.right - xAdj;
177 outRect.left = outRect.right - w;
178 if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
179 == (AXIS_CLIP<<AXIS_X_SHIFT)) {
180 if (outRect.left < container.left) {
181 outRect.left = container.left;
186 outRect.left = container.left + xAdj;
187 outRect.right = container.right + xAdj;
191 switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_Y_SHIFT)) {
193 outRect.top = container.top
194 + ((container.bottom - container.top - h)/2) + yAdj;
195 outRect.bottom = outRect.top + h;
196 if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
197 == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
198 if (outRect.top < container.top) {
199 outRect.top = container.top;
201 if (outRect.bottom > container.bottom) {
202 outRect.bottom = container.bottom;
206 case AXIS_PULL_BEFORE<<AXIS_Y_SHIFT:
207 outRect.top = container.top + yAdj;
208 outRect.bottom = outRect.top + h;
209 if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
210 == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
211 if (outRect.bottom > container.bottom) {
212 outRect.bottom = container.bottom;
216 case AXIS_PULL_AFTER<<AXIS_Y_SHIFT:
217 outRect.bottom = container.bottom - yAdj;
218 outRect.top = outRect.bottom - h;
219 if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
220 == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
221 if (outRect.top < container.top) {
222 outRect.top = container.top;
227 outRect.top = container.top + yAdj;
228 outRect.bottom = container.bottom + yAdj;
234 * Apply additional gravity behavior based on the overall "display" that an
235 * object exists in. This can be used after
236 * {@link #apply(int, int, int, Rect, int, int, Rect)} to place the object
237 * within a visible display. By default this moves or clips the object
238 * to be visible in the display; the gravity flags
239 * {@link #DISPLAY_CLIP_HORIZONTAL} and {@link #DISPLAY_CLIP_VERTICAL}
240 * can be used to change this behavior.
242 * @param gravity Gravity constants to modify the placement within the
244 * @param display The rectangle of the display in which the object is
246 * @param inoutObj Supplies the current object position; returns with it
247 * modified if needed to fit in the display.
249 public static void applyDisplay(int gravity, Rect display, Rect inoutObj) {
250 if ((gravity&DISPLAY_CLIP_VERTICAL) != 0) {
251 if (inoutObj.top < display.top) inoutObj.top = display.top;
252 if (inoutObj.bottom > display.bottom) inoutObj.bottom = display.bottom;
255 if (inoutObj.top < display.top) off = display.top-inoutObj.top;
256 else if (inoutObj.bottom > display.bottom) off = display.bottom-inoutObj.bottom;
258 if (inoutObj.height() > (display.bottom-display.top)) {
259 inoutObj.top = display.top;
260 inoutObj.bottom = display.bottom;
263 inoutObj.bottom += off;
268 if ((gravity&DISPLAY_CLIP_HORIZONTAL) != 0) {
269 if (inoutObj.left < display.left) inoutObj.left = display.left;
270 if (inoutObj.right > display.right) inoutObj.right = display.right;
273 if (inoutObj.left < display.left) off = display.left-inoutObj.left;
274 else if (inoutObj.right > display.right) off = display.right-inoutObj.right;
276 if (inoutObj.width() > (display.right-display.left)) {
277 inoutObj.left = display.left;
278 inoutObj.right = display.right;
280 inoutObj.left += off;
281 inoutObj.right += off;
288 * <p>Indicate whether the supplied gravity has a vertical pull.</p>
290 * @param gravity the gravity to check for vertical pull
291 * @return true if the supplied gravity has a vertical pull
293 public static boolean isVertical(int gravity) {
294 return gravity > 0 && (gravity & VERTICAL_GRAVITY_MASK) != 0;
298 * <p>Indicate whether the supplied gravity has an horizontal pull.</p>
300 * @param gravity the gravity to check for horizontal pull
301 * @return true if the supplied gravity has an horizontal pull
303 public static boolean isHorizontal(int gravity) {
304 return gravity > 0 && (gravity & HORIZONTAL_GRAVITY_MASK) != 0;