TextViewCompat.java revision bf14265885d1cb7ecd6db9b0109a8b033181747b
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.widget;
18
19import android.graphics.drawable.Drawable;
20import android.os.Build;
21import android.support.annotation.DrawableRes;
22import android.support.annotation.NonNull;
23import android.support.annotation.Nullable;
24import android.support.annotation.StyleRes;
25import android.widget.TextView;
26
27/**
28 * Helper for accessing features in {@link TextView} introduced after API level
29 * 4 in a backwards compatible fashion.
30 */
31public final class TextViewCompat {
32
33    // Hide constructor
34    private TextViewCompat() {}
35
36    interface TextViewCompatImpl {
37        void setCompoundDrawablesRelative(@NonNull TextView textView,
38                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
39                @Nullable Drawable bottom);
40        void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
41                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
42                @Nullable Drawable bottom);
43        void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
44                @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
45                @DrawableRes int bottom);
46        int getMaxLines(TextView textView);
47        int getMinLines(TextView textView);
48        void setTextAppearance(@NonNull TextView textView, @StyleRes int resId);
49        Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView);
50    }
51
52    static class BaseTextViewCompatImpl implements TextViewCompatImpl {
53        @Override
54        public void setCompoundDrawablesRelative(@NonNull TextView textView,
55                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
56                @Nullable Drawable bottom) {
57            textView.setCompoundDrawables(start, top, end, bottom);
58        }
59
60        @Override
61        public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
62                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
63                @Nullable Drawable bottom) {
64            textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
65        }
66
67        @Override
68        public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
69                @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
70                @DrawableRes int bottom) {
71            textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
72        }
73
74        @Override
75        public int getMaxLines(TextView textView) {
76            return TextViewCompatGingerbread.getMaxLines(textView);
77        }
78
79        @Override
80        public int getMinLines(TextView textView) {
81            return TextViewCompatGingerbread.getMinLines(textView);
82        }
83
84        @Override
85        public void setTextAppearance(TextView textView, @StyleRes int resId) {
86            TextViewCompatGingerbread.setTextAppearance(textView, resId);
87        }
88
89        @Override
90        public Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView) {
91            return TextViewCompatGingerbread.getCompoundDrawablesRelative(textView);
92        }
93    }
94
95    static class JbTextViewCompatImpl extends BaseTextViewCompatImpl {
96        @Override
97        public int getMaxLines(TextView textView) {
98            return TextViewCompatJb.getMaxLines(textView);
99        }
100
101        @Override
102        public int getMinLines(TextView textView) {
103            return TextViewCompatJb.getMinLines(textView);
104        }
105    }
106
107    static class JbMr1TextViewCompatImpl extends JbTextViewCompatImpl {
108        @Override
109        public void setCompoundDrawablesRelative(@NonNull TextView textView,
110                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
111                @Nullable Drawable bottom) {
112            TextViewCompatJbMr1.setCompoundDrawablesRelative(textView, start, top, end, bottom);
113        }
114
115        @Override
116        public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
117                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
118                @Nullable Drawable bottom) {
119            TextViewCompatJbMr1.setCompoundDrawablesRelativeWithIntrinsicBounds(textView,
120                    start, top, end, bottom);
121        }
122
123        @Override
124        public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
125                @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
126                @DrawableRes int bottom) {
127            TextViewCompatJbMr1.setCompoundDrawablesRelativeWithIntrinsicBounds(textView,
128                    start, top, end, bottom);
129        }
130
131        @Override
132        public Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView) {
133            return TextViewCompatJbMr1.getCompoundDrawablesRelative(textView);
134        }
135    }
136
137    static class JbMr2TextViewCompatImpl extends JbMr1TextViewCompatImpl {
138        @Override
139        public void setCompoundDrawablesRelative(@NonNull TextView textView,
140                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
141                @Nullable Drawable bottom) {
142            TextViewCompatJbMr2.setCompoundDrawablesRelative(textView, start, top, end, bottom);
143        }
144
145        @Override
146        public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
147                @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
148                @Nullable Drawable bottom) {
149            TextViewCompatJbMr2
150                    .setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end,
151                            bottom);
152        }
153
154        @Override
155        public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
156                @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
157                @DrawableRes int bottom) {
158            TextViewCompatJbMr2.setCompoundDrawablesRelativeWithIntrinsicBounds(textView,
159                    start, top, end, bottom);
160        }
161    }
162
163    static class Api23TextViewCompatImpl extends JbMr2TextViewCompatImpl {
164        @Override
165        public void setTextAppearance(@NonNull TextView textView, @StyleRes int resId) {
166            TextViewCompatApi23.setTextAppearance(textView, resId);
167        }
168    }
169
170    static final TextViewCompatImpl IMPL;
171
172    static {
173        final int version = Build.VERSION.SDK_INT;
174        if (version >= 23) {
175            IMPL = new Api23TextViewCompatImpl();
176        } else if (version >= 18) {
177            IMPL = new JbMr2TextViewCompatImpl();
178        } else if (version >= 17) {
179            IMPL = new JbMr1TextViewCompatImpl();
180        } else if (version >= 16) {
181            IMPL = new JbTextViewCompatImpl();
182        } else {
183            IMPL = new BaseTextViewCompatImpl();
184        }
185    }
186
187    /**
188     * Sets the Drawables (if any) to appear to the start of, above, to the end
189     * of, and below the text. Use {@code null} if you do not want a Drawable
190     * there. The Drawables must already have had {@link Drawable#setBounds}
191     * called.
192     * <p/>
193     * Calling this method will overwrite any Drawables previously set using
194     * {@link TextView#setCompoundDrawables} or related methods.
195     *
196     * @param textView The TextView against which to invoke the method.
197     * @attr name android:drawableStart
198     * @attr name android:drawableTop
199     * @attr name android:drawableEnd
200     * @attr name android:drawableBottom
201     */
202    public static void setCompoundDrawablesRelative(@NonNull TextView textView,
203            @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
204            @Nullable Drawable bottom) {
205        IMPL.setCompoundDrawablesRelative(textView, start, top, end, bottom);
206    }
207
208    /**
209     * Sets the Drawables (if any) to appear to the start of, above, to the end
210     * of, and below the text. Use {@code null} if you do not want a Drawable
211     * there. The Drawables' bounds will be set to their intrinsic bounds.
212     * <p/>
213     * Calling this method will overwrite any Drawables previously set using
214     * {@link TextView#setCompoundDrawables} or related methods.
215     *
216     * @param textView The TextView against which to invoke the method.
217     * @attr name android:drawableStart
218     * @attr name android:drawableTop
219     * @attr name android:drawableEnd
220     * @attr name android:drawableBottom
221     */
222    public static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
223            @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
224            @Nullable Drawable bottom) {
225        IMPL.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end, bottom);
226    }
227
228    /**
229     * Sets the Drawables (if any) to appear to the start of, above, to the end
230     * of, and below the text. Use 0 if you do not want a Drawable there. The
231     * Drawables' bounds will be set to their intrinsic bounds.
232     * <p/>
233     * Calling this method will overwrite any Drawables previously set using
234     * {@link TextView#setCompoundDrawables} or related methods.
235     *
236     * @param textView The TextView against which to invoke the method.
237     * @param start    Resource identifier of the start Drawable.
238     * @param top      Resource identifier of the top Drawable.
239     * @param end      Resource identifier of the end Drawable.
240     * @param bottom   Resource identifier of the bottom Drawable.
241     * @attr name android:drawableStart
242     * @attr name android:drawableTop
243     * @attr name android:drawableEnd
244     * @attr name android:drawableBottom
245     */
246    public static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
247            @DrawableRes int start, @DrawableRes int top, @DrawableRes int end,
248            @DrawableRes int bottom) {
249        IMPL.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end, bottom);
250    }
251
252    /**
253     * Returns the maximum number of lines displayed in the given TextView, or -1 if the maximum
254     * height was set in pixels instead.
255     */
256    public static int getMaxLines(@NonNull TextView textView) {
257        return IMPL.getMaxLines(textView);
258    }
259
260    /**
261     * Returns the minimum number of lines displayed in the given TextView, or -1 if the minimum
262     * height was set in pixels instead.
263     */
264    public static int getMinLines(@NonNull TextView textView) {
265        return IMPL.getMinLines(textView);
266    }
267
268    /**
269     * Sets the text appearance from the specified style resource.
270     * <p>
271     * Use a framework-defined {@code TextAppearance} style like
272     * {@link android.R.style#TextAppearance_Material_Body1 @android:style/TextAppearance.Material.Body1}.
273     *
274     * @param textView The TextView against which to invoke the method.
275     * @param resId    The resource identifier of the style to apply.
276     */
277    public static void setTextAppearance(@NonNull TextView textView, @StyleRes int resId) {
278        IMPL.setTextAppearance(textView, resId);
279    }
280
281    /**
282     * Returns drawables for the start, top, end, and bottom borders from the given text view.
283     */
284    public static Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView) {
285        return IMPL.getCompoundDrawablesRelative(textView);
286    }
287}
288