ItemAlignmentFacet.java revision 50c611b216a4b2c8eb2bbd2a2848bb6da34677be
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 */
14package android.support.v17.leanback.widget;
15
16import android.view.View;
17
18import static android.support.v17.leanback.widget.BaseGridView.ITEM_ALIGN_OFFSET_PERCENT_DISABLED;
19
20import android.support.v7.widget.RecyclerView;
21
22/**
23 * Optional facet provided by {@link RecyclerView.Adapter} or {@link RecyclerView.ViewHolder} for
24 * use in {@link HorizontalGridView} and {@link VerticalGridView}. Apps using {@link Presenter} may
25 * set facet using {@link Presenter#setFacet(Class, Object)} or
26 * {@link Presenter.ViewHolder#setFacet(Class, Object)}. Facet on ViewHolder has a higher priority
27 * than Presenter or Adapter.
28 * <p>
29 * ItemAlignmentFacet contains single or multiple {@link ItemAlignmentDef}s. First
30 * {@link ItemAlignmentDef} describes the default alignment position for ViewHolder, it also
31 * overrides the default item alignment settings on {@link VerticalGridView} and
32 * {@link HorizontalGridView}. When there are multiple {@link ItemAlignmentDef}s, the extra
33 * {@link ItemAlignmentDef}s are used to calculate deltas from first alignment position. When a
34 * descendant view is focused within the ViewHolder, grid view will visit focused view and its
35 * ancestors till the root of ViewHolder to match extra {@link ItemAlignmentDef}s'
36 * {@link ItemAlignmentDef#getItemAlignmentViewId()}. Once a match found, the
37 * {@link ItemAlignmentDef} is used to adjust a scroll delta from default alignment position.
38 */
39public final class ItemAlignmentFacet {
40
41    /**
42     * Value indicates that percent is not used.
43     */
44    public final static float ITEM_ALIGN_OFFSET_PERCENT_DISABLED = -1;
45
46    /**
47     * Definition of an alignment position under a view.
48     */
49    public static class ItemAlignmentDef {
50        int mViewId = View.NO_ID;
51        int mFocusViewId = View.NO_ID;
52        int mOffset = 0;
53        float mOffsetPercent = 50f;
54        boolean mOffsetWithPadding = false;
55        private boolean mAlignToBaseline;
56
57        /**
58         * Sets number of pixels to offset. Can be negative for alignment from the high edge, or
59         * positive for alignment from the low edge.
60         */
61        public final void setItemAlignmentOffset(int offset) {
62            mOffset = offset;
63        }
64
65        /**
66         * Gets number of pixels to offset. Can be negative for alignment from the high edge, or
67         * positive for alignment from the low edge.
68         */
69        public final int getItemAlignmentOffset() {
70            return mOffset;
71        }
72
73        /**
74         * Sets whether to include left/top padding for positive item offset, include
75         * right/bottom padding for negative item offset.
76         */
77        public final void setItemAlignmentOffsetWithPadding(boolean withPadding) {
78            mOffsetWithPadding = withPadding;
79        }
80
81        /**
82         * When it is true: we include left/top padding for positive item offset, include
83         * right/bottom padding for negative item offset.
84         */
85        public final boolean isItemAlignmentOffsetWithPadding() {
86            return mOffsetWithPadding;
87        }
88
89        /**
90         * Sets the offset percent for item alignment in addition to offset.  E.g., 40
91         * means 40% of the width from the low edge. Use {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED}
92         * to disable.
93         */
94        public final void setItemAlignmentOffsetPercent(float percent) {
95            if ( (percent < 0 || percent > 100) &&
96                    percent != ITEM_ALIGN_OFFSET_PERCENT_DISABLED) {
97                throw new IllegalArgumentException();
98            }
99            mOffsetPercent = percent;
100        }
101
102        /**
103         * Gets the offset percent for item alignment in addition to offset. E.g., 40
104         * means 40% of the width from the low edge. Use {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED}
105         * to disable.
106         */
107        public final float getItemAlignmentOffsetPercent() {
108            return mOffsetPercent;
109        }
110
111        /**
112         * Sets Id of which child view to be aligned.  View.NO_ID refers to root view and should
113         * be only used in first one.  Extra ItemAlignmentDefs should provide view id to match
114         * currently focused view.
115         */
116        public final void setItemAlignmentViewId(int viewId) {
117            mViewId = viewId;
118        }
119
120        /**
121         * Gets Id of which child view to be aligned.  View.NO_ID refers to root view and should
122         * be only used in first one.  Extra ItemAlignmentDefs should provide view id to match
123         * currently focused view.
124         */
125        public final int getItemAlignmentViewId() {
126            return mViewId;
127        }
128
129        /**
130         * Sets Id of which child view take focus for alignment.  When not set, it will use
131         * use same id of {@link #getItemAlignmentViewId()}
132         */
133        public final void setItemAlignmentFocusViewId(int viewId) {
134            mFocusViewId = viewId;
135        }
136
137        /**
138         * Returns Id of which child view take focus for alignment.  When not set, it will use
139         * use same id of {@link #getItemAlignmentViewId()}
140         */
141        public final int getItemAlignmentFocusViewId() {
142            return mFocusViewId != View.NO_ID ? mFocusViewId : mViewId;
143        }
144
145        /**
146         * Align to baseline if {@link #getItemAlignmentViewId()} is a TextView and
147         * alignToBaseline is true.
148         * @param alignToBaseline Boolean indicating whether to align the text to baseline.
149         */
150        public final void setAlignedToTextViewBaseline(boolean alignToBaseline) {
151            this.mAlignToBaseline = alignToBaseline;
152        }
153
154        /**
155         * Returns true when TextView should be aligned to the baseline.
156         */
157        public boolean isAlignedToTextViewBaseLine() {
158            return mAlignToBaseline;
159        }
160    }
161
162    private ItemAlignmentDef[] mAlignmentDefs = new ItemAlignmentDef[]{new ItemAlignmentDef()};
163
164    public boolean isMultiAlignment() {
165        return mAlignmentDefs.length > 1;
166    }
167
168    /**
169     * Sets definitions of alignment positions.
170     */
171    public void setAlignmentDefs(ItemAlignmentDef[] defs) {
172        if (defs == null || defs.length < 1) {
173            throw new IllegalArgumentException();
174        }
175        mAlignmentDefs = defs;
176    }
177
178    /**
179     * Returns read only definitions of alignment positions.
180     */
181    public ItemAlignmentDef[] getAlignmentDefs() {
182        return mAlignmentDefs;
183    }
184
185}
186