1 /* 2 * Copyright (C) 2015 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 package android.support.v17.leanback.widget; 15 16 import android.support.v7.widget.RecyclerView; 17 import android.view.View; 18 19 /** 20 * Optional facet provided by {@link RecyclerView.Adapter} or {@link RecyclerView.ViewHolder} for 21 * use in {@link HorizontalGridView} and {@link VerticalGridView}. Apps using {@link Presenter} may 22 * set facet using {@link Presenter#setFacet(Class, Object)} or 23 * {@link Presenter.ViewHolder#setFacet(Class, Object)}. Facet on ViewHolder has a higher priority 24 * than Presenter or Adapter. 25 * <p> 26 * ItemAlignmentFacet contains single or multiple {@link ItemAlignmentDef}s. First 27 * {@link ItemAlignmentDef} describes the default alignment position for ViewHolder, it also 28 * overrides the default item alignment settings on {@link VerticalGridView} and 29 * {@link HorizontalGridView} (see {@link BaseGridView#setItemAlignmentOffset(int)} etc). One 30 * ItemAlignmentFacet can have multiple {@link ItemAlignmentDef}s, e.g. having two aligned positions 31 * when child1 gets focus or child2 gets focus. Grid view will visit focused view and its 32 * ancestors till the root of ViewHolder to match {@link ItemAlignmentDef}s' 33 * {@link ItemAlignmentDef#getItemAlignmentFocusViewId()}. Once a match found, the 34 * {@link ItemAlignmentDef} is used to calculate alignment position. 35 */ 36 public final class ItemAlignmentFacet { 37 38 /** 39 * Value indicates that percent is not used. Equivalent to 0. 40 */ 41 public final static float ITEM_ALIGN_OFFSET_PERCENT_DISABLED = -1; 42 43 /** 44 * Definition of an alignment position under a view. 45 */ 46 public static class ItemAlignmentDef { 47 int mViewId = View.NO_ID; 48 int mFocusViewId = View.NO_ID; 49 int mOffset = 0; 50 float mOffsetPercent = 50f; 51 boolean mOffsetWithPadding = false; 52 private boolean mAlignToBaseline; 53 54 /** 55 * Sets number of pixels to the end of low edge. Supports right to left layout direction. 56 * @param offset In left to right or vertical case, it's the offset added to left/top edge. 57 * In right to left case, it's the offset subtracted from right edge. 58 */ setItemAlignmentOffset(int offset)59 public final void setItemAlignmentOffset(int offset) { 60 mOffset = offset; 61 } 62 63 /** 64 * Returns number of pixels to the end of low edge. Supports right to left layout direction. 65 * In left to right or vertical case, it's the offset added to left/top edge. In right to 66 * left case, it's the offset subtracted from right edge. 67 * @return Number of pixels to the end of low edge. 68 */ getItemAlignmentOffset()69 public final int getItemAlignmentOffset() { 70 return mOffset; 71 } 72 73 /** 74 * Sets whether applies padding to item alignment when 75 * {@link #getItemAlignmentOffsetPercent()} is 0 or 100. 76 * <p>When true: 77 * Applies start/top padding if {@link #getItemAlignmentOffsetPercent()} is 0. 78 * Applies end/bottom padding if {@link #getItemAlignmentOffsetPercent()} is 100. 79 * Does not apply padding if {@link #getItemAlignmentOffsetPercent()} is neither 0 nor 100. 80 * </p> 81 * <p>When false: does not apply padding</p> 82 */ setItemAlignmentOffsetWithPadding(boolean withPadding)83 public final void setItemAlignmentOffsetWithPadding(boolean withPadding) { 84 mOffsetWithPadding = withPadding; 85 } 86 87 /** 88 * Returns true if applies padding to item alignment when 89 * {@link #getItemAlignmentOffsetPercent()} is 0 or 100; returns false otherwise. 90 * <p>When true: 91 * Applies start/top padding when {@link #getItemAlignmentOffsetPercent()} is 0. 92 * Applies end/bottom padding when {@link #getItemAlignmentOffsetPercent()} is 100. 93 * Does not apply padding if {@link #getItemAlignmentOffsetPercent()} is neither 0 nor 100. 94 * </p> 95 * <p>When false: does not apply padding</p> 96 */ isItemAlignmentOffsetWithPadding()97 public final boolean isItemAlignmentOffsetWithPadding() { 98 return mOffsetWithPadding; 99 } 100 101 /** 102 * Sets the offset percent for item alignment in addition to offset. E.g., 40 103 * means 40% of width/height from the low edge. In the right to left case, it's the 40% 104 * width from right edge. Use {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED} to disable. 105 */ setItemAlignmentOffsetPercent(float percent)106 public final void setItemAlignmentOffsetPercent(float percent) { 107 if ((percent < 0 || percent > 100) 108 && percent != ITEM_ALIGN_OFFSET_PERCENT_DISABLED) { 109 throw new IllegalArgumentException(); 110 } 111 mOffsetPercent = percent; 112 } 113 114 /** 115 * Gets the offset percent for item alignment in addition to offset. E.g., 40 116 * means 40% of the width from the low edge. In the right to left case, it's the 40% from 117 * right edge. Use {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED} to disable. 118 */ getItemAlignmentOffsetPercent()119 public final float getItemAlignmentOffsetPercent() { 120 return mOffsetPercent; 121 } 122 123 /** 124 * Sets Id of which child view to be aligned. View.NO_ID refers to root view and should 125 * be only used in first one. Different view ids of {@link ItemAlignmentFacet 126 * #getAlignmentDefs()} define multiple alignment steps within one itemView, e.g. there are 127 * two child views R.id.child1 and R.id.child2. App may allocated two 128 * {@link ItemAlignmentDef}s, one with view id R.id.child1, the other with view id 129 * R.id.child2. Note this id may or may not be same as the child view that takes focus. 130 * 131 * @param viewId The id of child view that will be aligned to. 132 * @see #setItemAlignmentFocusViewId(int) 133 */ setItemAlignmentViewId(int viewId)134 public final void setItemAlignmentViewId(int viewId) { 135 mViewId = viewId; 136 } 137 138 /** 139 * Returns Id of which child view to be aligned. View.NO_ID refers to root view and should 140 * be only used in first one. Different view ids of {@link ItemAlignmentFacet 141 * #getAlignmentDefs()} define multiple alignment steps within one itemView, e.g. there are 142 * two child views R.id.child1 and R.id.child2. App may allocated two 143 * {@link ItemAlignmentDef}s, one with view id R.id.child1, the other with view id 144 * R.id.child2. Note this id may or may not be same as the child view that takes focus. 145 * 146 * @see #setItemAlignmentFocusViewId(int) 147 */ getItemAlignmentViewId()148 public final int getItemAlignmentViewId() { 149 return mViewId; 150 } 151 152 /** 153 * Sets Id of which child view take focus for alignment. When not set, it will use 154 * use same id of {@link #getItemAlignmentViewId()}. 155 * @param viewId The id of child view that will be focused to. 156 */ setItemAlignmentFocusViewId(int viewId)157 public final void setItemAlignmentFocusViewId(int viewId) { 158 mFocusViewId = viewId; 159 } 160 161 /** 162 * Returns Id of which child view take focus for alignment. When not set, it will use 163 * use same id of {@link #getItemAlignmentViewId()} 164 */ getItemAlignmentFocusViewId()165 public final int getItemAlignmentFocusViewId() { 166 return mFocusViewId != View.NO_ID ? mFocusViewId : mViewId; 167 } 168 169 /** 170 * When true, align to {@link View#getBaseline()} for the view of with id equals 171 * {@link #getItemAlignmentViewId()}; false otherwise. 172 * @param alignToBaseline Boolean indicating whether to align to view baseline. 173 */ setAlignedToTextViewBaseline(boolean alignToBaseline)174 public final void setAlignedToTextViewBaseline(boolean alignToBaseline) { 175 this.mAlignToBaseline = alignToBaseline; 176 } 177 178 /** 179 * Returns true when View should be aligned to {@link View#getBaseline()} 180 */ isAlignedToTextViewBaseLine()181 public boolean isAlignedToTextViewBaseLine() { 182 return mAlignToBaseline; 183 } 184 } 185 186 private ItemAlignmentDef[] mAlignmentDefs = new ItemAlignmentDef[]{new ItemAlignmentDef()}; 187 isMultiAlignment()188 public boolean isMultiAlignment() { 189 return mAlignmentDefs.length > 1; 190 } 191 192 /** 193 * Sets definitions of alignment positions. 194 */ setAlignmentDefs(ItemAlignmentDef[] defs)195 public void setAlignmentDefs(ItemAlignmentDef[] defs) { 196 if (defs == null || defs.length < 1) { 197 throw new IllegalArgumentException(); 198 } 199 mAlignmentDefs = defs; 200 } 201 202 /** 203 * Returns read only definitions of alignment positions. 204 */ getAlignmentDefs()205 public ItemAlignmentDef[] getAlignmentDefs() { 206 return mAlignmentDefs; 207 } 208 209 } 210