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