WindowAlignment.java revision 08a42433300b4617bad27bda1214e12ca7854adc
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15package android.support.v17.leanback.widget; 16 17import static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_LOW_EDGE; 18import static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_HIGH_EDGE; 19import static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_BOTH_EDGE; 20import static android.support.v17.leanback.widget.BaseGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED; 21 22import static android.support.v7.widget.RecyclerView.HORIZONTAL; 23 24/** 25 * Maintains Window Alignment information of two axis. 26 */ 27class WindowAlignment { 28 29 /** 30 * Maintains alignment information in one direction. 31 */ 32 public static class Axis { 33 /** 34 * mScrollCenter is used to calculate dynamic transformation based on how far a view 35 * is from the mScrollCenter. For example, the views with center close to mScrollCenter 36 * will be scaled up. 37 */ 38 private float mScrollCenter; 39 /** 40 * Right or bottom edge of last child. 41 */ 42 private int mMaxEdge; 43 /** 44 * Left or top edge of first child, typically should be zero. 45 */ 46 private int mMinEdge; 47 /** 48 * Max Scroll value 49 */ 50 private int mMaxScroll; 51 /** 52 * Min Scroll value 53 */ 54 private int mMinScroll; 55 56 private int mWindowAlignment = WINDOW_ALIGN_BOTH_EDGE; 57 58 private int mWindowAlignmentOffset = 0; 59 60 private float mWindowAlignmentOffsetPercent = 50f; 61 62 private int mSize; 63 64 private int mPaddingLow; 65 66 private int mPaddingHigh; 67 68 private String mName; // for debugging 69 70 public Axis(String name) { 71 reset(); 72 mName = name; 73 } 74 75 final public int getWindowAlignment() { 76 return mWindowAlignment; 77 } 78 79 final public void setWindowAlignment(int windowAlignment) { 80 mWindowAlignment = windowAlignment; 81 } 82 83 final public int getWindowAlignmentOffset() { 84 return mWindowAlignmentOffset; 85 } 86 87 final public void setWindowAlignmentOffset(int offset) { 88 mWindowAlignmentOffset = offset; 89 } 90 91 final public void setWindowAlignmentOffsetPercent(float percent) { 92 if ((percent < 0 || percent > 100) 93 && percent != WINDOW_ALIGN_OFFSET_PERCENT_DISABLED) { 94 throw new IllegalArgumentException(); 95 } 96 mWindowAlignmentOffsetPercent = percent; 97 } 98 99 final public float getWindowAlignmentOffsetPercent() { 100 return mWindowAlignmentOffsetPercent; 101 } 102 103 final public int getScrollCenter() { 104 return (int) mScrollCenter; 105 } 106 107 /** set minEdge, Integer.MIN_VALUE means unknown*/ 108 final public void setMinEdge(int minEdge) { 109 mMinEdge = minEdge; 110 } 111 112 final public int getMinEdge() { 113 return mMinEdge; 114 } 115 116 /** set minScroll, Integer.MIN_VALUE means unknown*/ 117 final public void setMinScroll(int minScroll) { 118 mMinScroll = minScroll; 119 } 120 121 final public int getMinScroll() { 122 return mMinScroll; 123 } 124 125 final public void invalidateScrollMin() { 126 mMinEdge = Integer.MIN_VALUE; 127 mMinScroll = Integer.MIN_VALUE; 128 } 129 130 /** update max edge, Integer.MAX_VALUE means unknown*/ 131 final public void setMaxEdge(int maxEdge) { 132 mMaxEdge = maxEdge; 133 } 134 135 final public int getMaxEdge() { 136 return mMaxEdge; 137 } 138 139 /** update max scroll, Integer.MAX_VALUE means unknown*/ 140 final public void setMaxScroll(int maxScroll) { 141 mMaxScroll = maxScroll; 142 } 143 144 final public int getMaxScroll() { 145 return mMaxScroll; 146 } 147 148 final public void invalidateScrollMax() { 149 mMaxEdge = Integer.MAX_VALUE; 150 mMaxScroll = Integer.MAX_VALUE; 151 } 152 153 final public float updateScrollCenter(float scrollTarget) { 154 mScrollCenter = scrollTarget; 155 return scrollTarget; 156 } 157 158 private void reset() { 159 mScrollCenter = Integer.MIN_VALUE; 160 mMinEdge = Integer.MIN_VALUE; 161 mMaxEdge = Integer.MAX_VALUE; 162 } 163 164 final public boolean isMinUnknown() { 165 return mMinEdge == Integer.MIN_VALUE; 166 } 167 168 final public boolean isMaxUnknown() { 169 return mMaxEdge == Integer.MAX_VALUE; 170 } 171 172 final public void setSize(int size) { 173 mSize = size; 174 } 175 176 final public int getSize() { 177 return mSize; 178 } 179 180 final public void setPadding(int paddingLow, int paddingHigh) { 181 mPaddingLow = paddingLow; 182 mPaddingHigh = paddingHigh; 183 } 184 185 final public int getPaddingLow() { 186 return mPaddingLow; 187 } 188 189 final public int getPaddingHigh() { 190 return mPaddingHigh; 191 } 192 193 final public int getClientSize() { 194 return mSize - mPaddingLow - mPaddingHigh; 195 } 196 197 final public int getSystemScrollPos(boolean isFirst, boolean isLast) { 198 return getSystemScrollPos((int) mScrollCenter, isFirst, isLast); 199 } 200 201 final public int getSystemScrollPos(int scrollCenter, boolean isFirst, boolean isLast) { 202 int middlePosition; 203 if (mWindowAlignmentOffset >= 0) { 204 middlePosition = mWindowAlignmentOffset - mPaddingLow; 205 } else { 206 middlePosition = mSize + mWindowAlignmentOffset - mPaddingLow; 207 } 208 if (mWindowAlignmentOffsetPercent != WINDOW_ALIGN_OFFSET_PERCENT_DISABLED) { 209 middlePosition += (int) (mSize * mWindowAlignmentOffsetPercent / 100); 210 } 211 int clientSize = getClientSize(); 212 int afterMiddlePosition = clientSize - middlePosition; 213 boolean isMinUnknown = isMinUnknown(); 214 boolean isMaxUnknown = isMaxUnknown(); 215 if (!isMinUnknown && !isMaxUnknown && 216 (mWindowAlignment & WINDOW_ALIGN_BOTH_EDGE) == WINDOW_ALIGN_BOTH_EDGE) { 217 if (mMaxEdge - mMinEdge <= clientSize) { 218 // total children size is less than view port and we want to align 219 // both edge: align first child to left edge of view port 220 return mMinEdge - mPaddingLow; 221 } 222 } 223 if (!isMinUnknown) { 224 if ((mWindowAlignment & WINDOW_ALIGN_LOW_EDGE) != 0 && 225 (isFirst || scrollCenter - mMinEdge <= middlePosition)) { 226 // scroll center is within half of view port size: align the left edge 227 // of first child to the left edge of view port 228 return mMinEdge - mPaddingLow; 229 } 230 } 231 if (!isMaxUnknown) { 232 if ((mWindowAlignment & WINDOW_ALIGN_HIGH_EDGE) != 0 && 233 (isLast || mMaxEdge - scrollCenter <= afterMiddlePosition)) { 234 // scroll center is very close to the right edge of view port : align the 235 // right edge of last children (plus expanded size) to view port's right 236 return mMaxEdge -mPaddingLow - (clientSize); 237 } 238 } 239 // else put scroll center in middle of view port 240 return scrollCenter - middlePosition - mPaddingLow; 241 } 242 243 @Override 244 public String toString() { 245 return "center: " + mScrollCenter + " min:" + mMinEdge + 246 " max:" + mMaxEdge; 247 } 248 249 } 250 251 private int mOrientation = HORIZONTAL; 252 253 final public Axis vertical = new Axis("vertical"); 254 255 final public Axis horizontal = new Axis("horizontal"); 256 257 private Axis mMainAxis = horizontal; 258 259 private Axis mSecondAxis = vertical; 260 261 final public Axis mainAxis() { 262 return mMainAxis; 263 } 264 265 final public Axis secondAxis() { 266 return mSecondAxis; 267 } 268 269 final public void setOrientation(int orientation) { 270 mOrientation = orientation; 271 if (mOrientation == HORIZONTAL) { 272 mMainAxis = horizontal; 273 mSecondAxis = vertical; 274 } else { 275 mMainAxis = vertical; 276 mSecondAxis = horizontal; 277 } 278 } 279 280 final public int getOrientation() { 281 return mOrientation; 282 } 283 284 final public void reset() { 285 mainAxis().reset(); 286 } 287 288 @Override 289 public String toString() { 290 return new StringBuffer().append("horizontal=") 291 .append(horizontal.toString()) 292 .append("vertical=") 293 .append(vertical.toString()) 294 .toString(); 295 } 296 297} 298