Gravity.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/*
2 * Copyright (C) 2006 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
17package android.view;
18import android.graphics.Rect;
19
20/**
21 * Standard constants and tools for placing an object within a potentially
22 * larger container.
23 */
24public class Gravity
25{
26    /** Contstant indicating that no gravity has been set **/
27    public static final int NO_GRAVITY = 0x0000;
28
29    /** Raw bit indicating the gravity for an axis has been specified. */
30    public static final int AXIS_SPECIFIED = 0x0001;
31
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
37    /** Bits defining the horizontal axis. */
38    public static final int AXIS_X_SHIFT = 0;
39    /** Bits defining the vertical axis. */
40    public static final int AXIS_Y_SHIFT = 4;
41
42    /** Push object to the top of its container, not changing its size. */
43    public static final int TOP = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
44    /** Push object to the bottom of its container, not changing its size. */
45    public static final int BOTTOM = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
46    /** Push object to the left of its container, not changing its size. */
47    public static final int LEFT = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
48    /** Push object to the right of its container, not changing its size. */
49    public static final int RIGHT = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
50
51    /** Place object in the vertical center of its container, not changing its
52     *  size. */
53    public static final int CENTER_VERTICAL = AXIS_SPECIFIED<<AXIS_Y_SHIFT;
54    /** Grow the vertical size of the object if needed so it completely fills
55     *  its container. */
56    public static final int FILL_VERTICAL = TOP|BOTTOM;
57
58    /** Place object in the horizontal center of its container, not changing its
59     *  size. */
60    public static final int CENTER_HORIZONTAL = AXIS_SPECIFIED<<AXIS_X_SHIFT;
61    /** Grow the horizontal size of the object if needed so it completely fills
62     *  its container. */
63    public static final int FILL_HORIZONTAL = LEFT|RIGHT;
64
65    /** Place the object in the center of its container in both the vertical
66     *  and horizontal axis, not changing its size. */
67    public static final int CENTER = CENTER_VERTICAL|CENTER_HORIZONTAL;
68
69    /** Grow the horizontal and vertical size of the obejct if needed so it
70     *  completely fills its container. */
71    public static final int FILL = FILL_VERTICAL|FILL_HORIZONTAL;
72
73    /**
74     * Binary mask to get the horizontal gravity of a gravity.
75     */
76    public static final int HORIZONTAL_GRAVITY_MASK = (AXIS_SPECIFIED |
77            AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_X_SHIFT;
78    /**
79     * Binary mask to get the vertical gravity of a gravity.
80     */
81    public static final int VERTICAL_GRAVITY_MASK = (AXIS_SPECIFIED |
82            AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_Y_SHIFT;
83
84    /**
85     * Apply a gravity constant to an object.
86     *
87     * @param gravity The desired placement of the object, as defined by the
88     *                constants in this class.
89     * @param w The horizontal size of the object.
90     * @param h The vertical size of the object.
91     * @param container The frame of the containing space, in which the object
92     *                  will be placed.  Should be large enough to contain the
93     *                  width and height of the object.
94     * @param outRect Receives the computed frame of the object in its
95     *                container.
96     */
97    public static void apply(int gravity, int w, int h, Rect container,
98                             Rect outRect) {
99        apply(gravity, w, h, container, 0, 0, outRect);
100    }
101
102    /**
103     * Apply a gravity constant to an object.
104     *
105     * @param gravity The desired placement of the object, as defined by the
106     *                constants in this class.
107     * @param w The horizontal size of the object.
108     * @param h The vertical size of the object.
109     * @param container The frame of the containing space, in which the object
110     *                  will be placed.  Should be large enough to contain the
111     *                  width and height of the object.
112     * @param xAdj Offset to apply to the X axis.  If gravity is LEFT this
113     *             pushes it to the right; if gravity is RIGHT it pushes it to
114     *             the left; if gravity is CENTER_HORIZONTAL it pushes it to the
115     *             right or left; otherwise it is ignored.
116     * @param yAdj Offset to apply to the Y axis.  If gravity is TOP this pushes
117     *             it down; if gravity is BOTTOM it pushes it up; if gravity is
118     *             CENTER_VERTICAL it pushes it down or up; otherwise it is
119     *             ignored.
120     * @param outRect Receives the computed frame of the object in its
121     *                container.
122     */
123    public static void apply(int gravity, int w, int h, Rect container,
124                             int xAdj, int yAdj, Rect outRect) {
125        if ((gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT))
126             == ((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT)) {
127            outRect.left = container.left;
128            outRect.right = container.right;
129        } else {
130            outRect.left = applyMovement(
131                gravity>>AXIS_X_SHIFT, w, container.left, container.right, xAdj);
132            outRect.right = outRect.left + w;
133        }
134
135        if ((gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_Y_SHIFT))
136             == ((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_Y_SHIFT)) {
137            outRect.top = container.top;
138            outRect.bottom = container.bottom;
139        } else {
140            outRect.top = applyMovement(
141                gravity>>AXIS_Y_SHIFT, h, container.top, container.bottom, yAdj);
142            outRect.bottom = outRect.top + h;
143        }
144    }
145
146    /**
147     * <p>Indicate whether the supplied gravity has a vertical pull.</p>
148     *
149     * @param gravity the gravity to check for vertical pull
150     * @return true if the supplied gravity has a vertical pull
151     */
152    public static boolean isVertical(int gravity) {
153        return gravity > 0 && (gravity & VERTICAL_GRAVITY_MASK) != 0;
154    }
155
156    /**
157     * <p>Indicate whether the supplied gravity has an horizontal pull.</p>
158     *
159     * @param gravity the gravity to check for horizontal pull
160     * @return true if the supplied gravity has an horizontal pull
161     */
162    public static boolean isHorizontal(int gravity) {
163        return gravity > 0 && (gravity & HORIZONTAL_GRAVITY_MASK) != 0;
164    }
165
166    private static int applyMovement(int mode, int size,
167            int start, int end, int adj) {
168        if ((mode & AXIS_PULL_BEFORE) != 0) {
169            return start + adj;
170        }
171
172        if ((mode & AXIS_PULL_AFTER) != 0) {
173            return end - size - adj;
174        }
175
176        return start + ((end - start - size)/2) + adj;
177    }
178}
179
180