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.IdRes; 23import android.support.annotation.NonNull; 24import android.support.annotation.Nullable; 25import android.support.annotation.StyleRes; 26import android.widget.TextView; 27 28/** 29 * Helper for accessing features in {@link TextView} introduced after API level 30 * 4 in a backwards compatible fashion. 31 */ 32public final class TextViewCompat { 33 34 // Hide constructor 35 private TextViewCompat() {} 36 37 interface TextViewCompatImpl { 38 void setCompoundDrawablesRelative(@NonNull TextView textView, 39 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 40 @Nullable Drawable bottom); 41 void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 42 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 43 @Nullable Drawable bottom); 44 void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 45 @DrawableRes int start, @DrawableRes int top, @DrawableRes int end, 46 @DrawableRes int bottom); 47 int getMaxLines(TextView textView); 48 int getMinLines(TextView textView); 49 void setTextAppearance(@NonNull TextView textView, @StyleRes int resId); 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 TextViewCompatDonut.getMaxLines(textView); 77 } 78 79 @Override 80 public int getMinLines(TextView textView) { 81 return TextViewCompatDonut.getMinLines(textView); 82 } 83 84 @Override 85 public void setTextAppearance(TextView textView, @StyleRes int resId) { 86 TextViewCompatDonut.setTextAppearance(textView, resId); 87 } 88 } 89 90 static class JbTextViewCompatImpl extends BaseTextViewCompatImpl { 91 @Override 92 public int getMaxLines(TextView textView) { 93 return TextViewCompatJb.getMaxLines(textView); 94 } 95 96 @Override 97 public int getMinLines(TextView textView) { 98 return TextViewCompatJb.getMinLines(textView); 99 } 100 } 101 102 static class JbMr1TextViewCompatImpl extends JbTextViewCompatImpl { 103 @Override 104 public void setCompoundDrawablesRelative(@NonNull TextView textView, 105 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 106 @Nullable Drawable bottom) { 107 TextViewCompatJbMr1.setCompoundDrawablesRelative(textView, start, top, end, bottom); 108 } 109 110 @Override 111 public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 112 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 113 @Nullable Drawable bottom) { 114 TextViewCompatJbMr1.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, 115 start, top, end, bottom); 116 } 117 118 @Override 119 public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 120 @DrawableRes int start, @DrawableRes int top, @DrawableRes int end, 121 @DrawableRes int bottom) { 122 TextViewCompatJbMr1.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, 123 start, top, end, bottom); 124 } 125 } 126 127 static class JbMr2TextViewCompatImpl extends JbMr1TextViewCompatImpl { 128 @Override 129 public void setCompoundDrawablesRelative(@NonNull TextView textView, 130 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 131 @Nullable Drawable bottom) { 132 TextViewCompatJbMr2.setCompoundDrawablesRelative(textView, start, top, end, bottom); 133 } 134 135 @Override 136 public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 137 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 138 @Nullable Drawable bottom) { 139 TextViewCompatJbMr2 140 .setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end, 141 bottom); 142 } 143 144 @Override 145 public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 146 @DrawableRes int start, @DrawableRes int top, @DrawableRes int end, 147 @DrawableRes int bottom) { 148 TextViewCompatJbMr2.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, 149 start, top, end, bottom); 150 } 151 } 152 153 static class Api23TextViewCompatImpl extends JbMr2TextViewCompatImpl { 154 @Override 155 public void setTextAppearance(@NonNull TextView textView, @StyleRes int resId) { 156 TextViewCompatApi23.setTextAppearance(textView, resId); 157 } 158 } 159 160 static final TextViewCompatImpl IMPL; 161 162 static { 163 final int version = Build.VERSION.SDK_INT; 164 if (version >= 23) { 165 IMPL = new Api23TextViewCompatImpl(); 166 } else if (version >= 18) { 167 IMPL = new JbMr2TextViewCompatImpl(); 168 } else if (version >= 17) { 169 IMPL = new JbMr1TextViewCompatImpl(); 170 } else if (version >= 16) { 171 IMPL = new JbTextViewCompatImpl(); 172 } else { 173 IMPL = new BaseTextViewCompatImpl(); 174 } 175 } 176 177 /** 178 * Sets the Drawables (if any) to appear to the start of, above, to the end 179 * of, and below the text. Use {@code null} if you do not want a Drawable 180 * there. The Drawables must already have had {@link Drawable#setBounds} 181 * called. 182 * <p/> 183 * Calling this method will overwrite any Drawables previously set using 184 * {@link TextView#setCompoundDrawables} or related methods. 185 * 186 * @param textView The TextView against which to invoke the method. 187 * @attr name android:drawableStart 188 * @attr name android:drawableTop 189 * @attr name android:drawableEnd 190 * @attr name android:drawableBottom 191 */ 192 public static void setCompoundDrawablesRelative(@NonNull TextView textView, 193 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 194 @Nullable Drawable bottom) { 195 IMPL.setCompoundDrawablesRelative(textView, start, top, end, bottom); 196 } 197 198 /** 199 * Sets the Drawables (if any) to appear to the start of, above, to the end 200 * of, and below the text. Use {@code null} if you do not want a Drawable 201 * there. The Drawables' bounds will be set to their intrinsic bounds. 202 * <p/> 203 * Calling this method will overwrite any Drawables previously set using 204 * {@link TextView#setCompoundDrawables} or related methods. 205 * 206 * @param textView The TextView against which to invoke the method. 207 * @attr name android:drawableStart 208 * @attr name android:drawableTop 209 * @attr name android:drawableEnd 210 * @attr name android:drawableBottom 211 */ 212 public static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 213 @Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end, 214 @Nullable Drawable bottom) { 215 IMPL.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end, bottom); 216 } 217 218 /** 219 * Sets the Drawables (if any) to appear to the start of, above, to the end 220 * of, and below the text. Use 0 if you do not want a Drawable there. The 221 * Drawables' bounds will be set to their intrinsic bounds. 222 * <p/> 223 * Calling this method will overwrite any Drawables previously set using 224 * {@link TextView#setCompoundDrawables} or related methods. 225 * 226 * @param textView The TextView against which to invoke the method. 227 * @param start Resource identifier of the start Drawable. 228 * @param top Resource identifier of the top Drawable. 229 * @param end Resource identifier of the end Drawable. 230 * @param bottom Resource identifier of the bottom Drawable. 231 * @attr name android:drawableStart 232 * @attr name android:drawableTop 233 * @attr name android:drawableEnd 234 * @attr name android:drawableBottom 235 */ 236 public static void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView, 237 @DrawableRes int start, @DrawableRes int top, @DrawableRes int end, 238 @DrawableRes int bottom) { 239 IMPL.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end, bottom); 240 } 241 242 /** 243 * Returns the maximum number of lines displayed in the given TextView, or -1 if the maximum 244 * height was set in pixels instead. 245 */ 246 public static int getMaxLines(@NonNull TextView textView) { 247 return IMPL.getMaxLines(textView); 248 } 249 250 /** 251 * Returns the minimum number of lines displayed in the given TextView, or -1 if the minimum 252 * height was set in pixels instead. 253 */ 254 public static int getMinLines(@NonNull TextView textView) { 255 return IMPL.getMinLines(textView); 256 } 257 258 /** 259 * Sets the text appearance from the specified style resource. 260 * <p> 261 * Use a framework-defined {@code TextAppearance} style like 262 * {@link android.R.style#TextAppearance_Material_Body1 @android:style/TextAppearance.Material.Body1} 263 * or see {@link android.R.styleable#TextAppearance TextAppearance} for the 264 * set of attributes that can be used in a custom style. 265 * 266 * @param textView The TextView against which to invoke the method. 267 * @param resId The resource identifier of the style to apply. 268 */ 269 public static void setTextAppearance(@NonNull TextView textView, @StyleRes int resId) { 270 IMPL.setTextAppearance(textView, resId); 271 } 272} 273