1 /* 2 * Copyright (C) 2013 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 17 18 package android.support.v4.view; 19 20 import android.graphics.Rect; 21 import android.os.Build; 22 import android.view.Gravity; 23 24 /** 25 * Compatibility shim for accessing newer functionality from {@link android.view.Gravity}. 26 */ 27 public class GravityCompat { 28 interface GravityCompatImpl { getAbsoluteGravity(int gravity, int layoutDirection)29 int getAbsoluteGravity(int gravity, int layoutDirection); apply(int gravity, int w, int h, Rect container, Rect outRect, int layoutDirection)30 void apply(int gravity, int w, int h, Rect container, Rect outRect, int layoutDirection); apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, Rect outRect, int layoutDirection)31 void apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, 32 Rect outRect, int layoutDirection); applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection)33 void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection); 34 } 35 36 static class GravityCompatImplBase implements GravityCompatImpl { 37 @Override getAbsoluteGravity(int gravity, int layoutDirection)38 public int getAbsoluteGravity(int gravity, int layoutDirection) { 39 // Just strip off the relative bit to get LEFT/RIGHT. 40 return gravity & ~RELATIVE_LAYOUT_DIRECTION; 41 } 42 43 @Override apply(int gravity, int w, int h, Rect container, Rect outRect, int layoutDirection)44 public void apply(int gravity, int w, int h, Rect container, Rect outRect, 45 int layoutDirection) { 46 Gravity.apply(gravity, w, h, container, outRect); 47 } 48 49 @Override apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, Rect outRect, int layoutDirection)50 public void apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, 51 Rect outRect, int layoutDirection) { 52 Gravity.apply(gravity, w, h, container, xAdj, yAdj, outRect); 53 } 54 55 @Override applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection)56 public void applyDisplay(int gravity, Rect display, Rect inoutObj, 57 int layoutDirection) { 58 Gravity.applyDisplay(gravity, display, inoutObj); 59 } 60 } 61 62 static class GravityCompatImplJellybeanMr1 implements GravityCompatImpl { 63 @Override getAbsoluteGravity(int gravity, int layoutDirection)64 public int getAbsoluteGravity(int gravity, int layoutDirection) { 65 return GravityCompatJellybeanMr1.getAbsoluteGravity(gravity, layoutDirection); 66 } 67 68 @Override apply(int gravity, int w, int h, Rect container, Rect outRect, int layoutDirection)69 public void apply(int gravity, int w, int h, Rect container, Rect outRect, 70 int layoutDirection) { 71 GravityCompatJellybeanMr1.apply(gravity, w, h, container, outRect, layoutDirection); 72 } 73 74 @Override apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, Rect outRect, int layoutDirection)75 public void apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, 76 Rect outRect, int layoutDirection) { 77 GravityCompatJellybeanMr1.apply(gravity, w, h, container, xAdj, yAdj, outRect, 78 layoutDirection); 79 } 80 81 @Override applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection)82 public void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) { 83 GravityCompatJellybeanMr1.applyDisplay(gravity, display, inoutObj, layoutDirection); 84 } 85 } 86 87 static final GravityCompatImpl IMPL; 88 static { 89 final int version = Build.VERSION.SDK_INT; 90 if (version >= 17) { 91 IMPL = new GravityCompatImplJellybeanMr1(); 92 } else { 93 IMPL = new GravityCompatImplBase(); 94 } 95 } 96 97 /** Raw bit controlling whether the layout direction is relative or not (START/END instead of 98 * absolute LEFT/RIGHT). 99 */ 100 public static final int RELATIVE_LAYOUT_DIRECTION = 0x00800000; 101 102 /** Push object to x-axis position at the start of its container, not changing its size. */ 103 public static final int START = RELATIVE_LAYOUT_DIRECTION | Gravity.LEFT; 104 105 /** Push object to x-axis position at the end of its container, not changing its size. */ 106 public static final int END = RELATIVE_LAYOUT_DIRECTION | Gravity.RIGHT; 107 108 /** 109 * Binary mask for the horizontal gravity and script specific direction bit. 110 */ 111 public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = START | END; 112 113 /** 114 * Apply a gravity constant to an object and take care if layout direction is RTL or not. 115 * 116 * @param gravity The desired placement of the object, as defined by the 117 * constants in this class. 118 * @param w The horizontal size of the object. 119 * @param h The vertical size of the object. 120 * @param container The frame of the containing space, in which the object 121 * will be placed. Should be large enough to contain the 122 * width and height of the object. 123 * @param outRect Receives the computed frame of the object in its 124 * container. 125 * @param layoutDirection The layout direction. 126 * 127 * @see ViewCompat#LAYOUT_DIRECTION_LTR 128 * @see ViewCompat#LAYOUT_DIRECTION_RTL 129 */ apply(int gravity, int w, int h, Rect container, Rect outRect, int layoutDirection)130 public static void apply(int gravity, int w, int h, Rect container, 131 Rect outRect, int layoutDirection) { 132 IMPL.apply(gravity, w, h, container, outRect, layoutDirection); 133 } 134 135 /** 136 * Apply a gravity constant to an object. 137 * 138 * @param gravity The desired placement of the object, as defined by the 139 * constants in this class. 140 * @param w The horizontal size of the object. 141 * @param h The vertical size of the object. 142 * @param container The frame of the containing space, in which the object 143 * will be placed. Should be large enough to contain the 144 * width and height of the object. 145 * @param xAdj Offset to apply to the X axis. If gravity is LEFT this 146 * pushes it to the right; if gravity is RIGHT it pushes it to 147 * the left; if gravity is CENTER_HORIZONTAL it pushes it to the 148 * right or left; otherwise it is ignored. 149 * @param yAdj Offset to apply to the Y axis. If gravity is TOP this pushes 150 * it down; if gravity is BOTTOM it pushes it up; if gravity is 151 * CENTER_VERTICAL it pushes it down or up; otherwise it is 152 * ignored. 153 * @param outRect Receives the computed frame of the object in its 154 * container. 155 * @param layoutDirection The layout direction. 156 * 157 * @see ViewCompat#LAYOUT_DIRECTION_LTR 158 * @see ViewCompat#LAYOUT_DIRECTION_RTL 159 */ apply(int gravity, int w, int h, Rect container, int xAdj, int yAdj, Rect outRect, int layoutDirection)160 public static void apply(int gravity, int w, int h, Rect container, 161 int xAdj, int yAdj, Rect outRect, int layoutDirection) { 162 IMPL.apply(gravity, w, h, container, xAdj, yAdj, outRect, layoutDirection); 163 } 164 165 /** 166 * Apply additional gravity behavior based on the overall "display" that an 167 * object exists in. This can be used after 168 * {@link android.view.Gravity#apply(int, int, int, Rect, int, int, Rect)} to place the object 169 * within a visible display. By default this moves or clips the object 170 * to be visible in the display; the gravity flags 171 * {@link android.view.Gravity#DISPLAY_CLIP_HORIZONTAL} and 172 * {@link android.view.Gravity#DISPLAY_CLIP_VERTICAL} can be used to change this behavior. 173 * 174 * @param gravity Gravity constants to modify the placement within the 175 * display. 176 * @param display The rectangle of the display in which the object is 177 * being placed. 178 * @param inoutObj Supplies the current object position; returns with it 179 * modified if needed to fit in the display. 180 * @param layoutDirection The layout direction. 181 * 182 * @see ViewCompat#LAYOUT_DIRECTION_LTR 183 * @see ViewCompat#LAYOUT_DIRECTION_RTL 184 */ applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection)185 public static void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) { 186 IMPL.applyDisplay(gravity, display, inoutObj, layoutDirection); 187 } 188 189 /** 190 * <p>Convert script specific gravity to absolute horizontal value.</p> 191 * 192 * if horizontal direction is LTR, then START will set LEFT and END will set RIGHT. 193 * if horizontal direction is RTL, then START will set RIGHT and END will set LEFT. 194 * 195 * 196 * @param gravity The gravity to convert to absolute (horizontal) values. 197 * @param layoutDirection The layout direction. 198 * @return gravity converted to absolute (horizontal) values. 199 */ getAbsoluteGravity(int gravity, int layoutDirection)200 public static int getAbsoluteGravity(int gravity, int layoutDirection) { 201 return IMPL.getAbsoluteGravity(gravity, layoutDirection); 202 } 203 } 204