Home | History | Annotate | Download | only in widget
      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          */
     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          */
     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          */
     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          */
     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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    182         public boolean isAlignedToTextViewBaseLine() {
    183             return mAlignToBaseline;
    184         }
    185     }
    186 
    187     private ItemAlignmentDef[] mAlignmentDefs = new ItemAlignmentDef[]{new ItemAlignmentDef()};
    188 
    189     public boolean isMultiAlignment() {
    190         return mAlignmentDefs.length > 1;
    191     }
    192 
    193     /**
    194      * Sets definitions of alignment positions.
    195      */
    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      */
    206     public ItemAlignmentDef[] getAlignmentDefs() {
    207         return mAlignmentDefs;
    208     }
    209 
    210 }
    211