TextViewBindingAdapter.java revision fead9ca09b117136b35bc5bf137340a754f9eddd
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 */
16package android.databinding.adapters;
17
18import android.databinding.BindingAdapter;
19import android.databinding.BindingMethod;
20import android.databinding.BindingMethods;
21import android.graphics.drawable.Drawable;
22import android.os.Build;
23import android.text.InputFilter;
24import android.text.InputType;
25import android.text.method.DialerKeyListener;
26import android.text.method.DigitsKeyListener;
27import android.text.method.KeyListener;
28import android.text.method.PasswordTransformationMethod;
29import android.text.method.TextKeyListener;
30import android.util.Log;
31import android.util.TypedValue;
32import android.widget.TextView;
33
34@BindingMethods({
35        @BindingMethod(type = "android.widget.TextView", attribute = "android:autoLink", method = "setAutoLinkMask"),
36        @BindingMethod(type = "android.widget.TextView", attribute = "android:drawablePadding", method = "setCompoundDrawablePadding"),
37        @BindingMethod(type = "android.widget.TextView", attribute = "android:editorExtras", method = "setInputExtras"),
38        @BindingMethod(type = "android.widget.TextView", attribute = "android:inputType", method = "setRawInputType"),
39        @BindingMethod(type = "android.widget.TextView", attribute = "android:scrollHorizontally", method = "setHorizontallyScrolling"),
40        @BindingMethod(type = "android.widget.TextView", attribute = "android:textAllCaps", method = "setAllCaps"),
41        @BindingMethod(type = "android.widget.TextView", attribute = "android:textColorHighlight", method = "setHighlightColor"),
42        @BindingMethod(type = "android.widget.TextView", attribute = "android:textColorHint", method = "setHintTextColor"),
43        @BindingMethod(type = "android.widget.TextView", attribute = "android:textColorLink", method = "setLinkTextColor"),
44})
45public class TextViewBindingAdapter {
46
47    private static final String TAG = "TextViewBindingAdapters";
48
49    public static final int INTEGER = 0x01;
50
51    public static final int SIGNED = 0x03;
52
53    public static final int DECIMAL = 0x05;
54
55    @BindingAdapter("android:autoText")
56    public static void setAutoText(TextView view, boolean autoText) {
57        KeyListener listener = view.getKeyListener();
58
59        TextKeyListener.Capitalize capitalize = TextKeyListener.Capitalize.NONE;
60
61        int inputType = listener != null ? listener.getInputType() : 0;
62        if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
63            capitalize = TextKeyListener.Capitalize.CHARACTERS;
64        } else if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0) {
65            capitalize = TextKeyListener.Capitalize.WORDS;
66        } else if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) {
67            capitalize = TextKeyListener.Capitalize.SENTENCES;
68        }
69        view.setKeyListener(TextKeyListener.getInstance(autoText, capitalize));
70    }
71
72    @BindingAdapter("android:capitalize")
73    public static void setCapitalize(TextView view, TextKeyListener.Capitalize capitalize) {
74        KeyListener listener = view.getKeyListener();
75
76        int inputType = listener.getInputType();
77        boolean autoText = (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) != 0;
78        view.setKeyListener(TextKeyListener.getInstance(autoText, capitalize));
79    }
80
81    @BindingAdapter("android:bufferType")
82    public static void setBufferType(TextView view, TextView.BufferType bufferType) {
83        view.setText(view.getText(), bufferType);
84    }
85
86    @BindingAdapter("android:digits")
87    public static void setDigits(TextView view, CharSequence digits) {
88        if (digits != null) {
89            view.setKeyListener(DigitsKeyListener.getInstance(digits.toString()));
90        } else if (view.getKeyListener() instanceof DigitsKeyListener) {
91            view.setKeyListener(null);
92        }
93    }
94
95    @BindingAdapter("android:numeric")
96    public static void setNumeric(TextView view, int numeric) {
97        view.setKeyListener(DigitsKeyListener.getInstance((numeric & SIGNED) != 0,
98                (numeric & DECIMAL) != 0));
99    }
100
101    @BindingAdapter("android:phoneNumber")
102    public static void setPhoneNumber(TextView view, boolean phoneNumber) {
103        if (phoneNumber) {
104            view.setKeyListener(DialerKeyListener.getInstance());
105        } else if (view.getKeyListener() instanceof DialerKeyListener) {
106            view.setKeyListener(null);
107        }
108    }
109
110    @BindingAdapter("android:drawableBottom")
111    public static void setDrawableBottom(TextView view, Drawable drawable) {
112        Drawable[] drawables = view.getCompoundDrawables();
113        view.setCompoundDrawables(drawables[0], drawables[1], drawables[2], drawable);
114    }
115
116    @BindingAdapter("android:drawableLeft")
117    public static void setDrawableLeft(TextView view, Drawable drawable) {
118        Drawable[] drawables = view.getCompoundDrawables();
119        view.setCompoundDrawables(drawable, drawables[1], drawables[2], drawables[3]);
120    }
121
122    @BindingAdapter("android:drawableRight")
123    public static void setDrawableRight(TextView view, Drawable drawable) {
124        Drawable[] drawables = view.getCompoundDrawables();
125        view.setCompoundDrawables(drawables[0], drawables[1], drawable, drawables[3]);
126    }
127
128    @BindingAdapter("android:drawableTop")
129    public static void setDrawableTop(TextView view, Drawable drawable) {
130        Drawable[] drawables = view.getCompoundDrawables();
131        view.setCompoundDrawables(drawables[0], drawable, drawables[2], drawables[3]);
132    }
133
134    @BindingAdapter("android:drawableStart")
135    public static void setDrawableStart(TextView view, Drawable drawable) {
136        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
137            setDrawableLeft(view, drawable);
138        } else {
139            Drawable[] drawables = view.getCompoundDrawablesRelative();
140            view.setCompoundDrawablesRelative(drawable, drawables[1], drawables[2], drawables[3]);
141        }
142    }
143
144    @BindingAdapter("android:drawableEnd")
145    public static void setDrawableEnd(TextView view, Drawable drawable) {
146        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
147            setDrawableRight(view, drawable);
148        } else {
149            Drawable[] drawables = view.getCompoundDrawablesRelative();
150            view.setCompoundDrawablesRelative(drawables[0], drawables[1], drawable, drawables[3]);
151        }
152    }
153
154    @BindingAdapter("android:imeActionLabel")
155    public static void setImeActionLabel(TextView view, CharSequence value) {
156        view.setImeActionLabel(value, view.getImeActionId());
157    }
158
159    @BindingAdapter("android:imeActionId")
160    public static void setImeActionLabel(TextView view, int value) {
161        view.setImeActionLabel(view.getImeActionLabel(), value);
162    }
163
164    @BindingAdapter("android:inputMethod")
165    public static void setInputMethod(TextView view, CharSequence inputMethod) {
166        try {
167            Class<?> c = Class.forName(inputMethod.toString());
168            view.setKeyListener((KeyListener) c.newInstance());
169        } catch (ClassNotFoundException e) {
170            Log.e(TAG, "Could not create input method: " + inputMethod, e);
171        } catch (InstantiationException e) {
172            Log.e(TAG, "Could not create input method: " + inputMethod, e);
173        } catch (IllegalAccessException e) {
174            Log.e(TAG, "Could not create input method: " + inputMethod, e);
175        }
176    }
177
178    @BindingAdapter("android:lineSpacingExtra")
179    public static void setLineSpacingExtra(TextView view, float value) {
180        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
181            view.setLineSpacing(value, view.getLineSpacingMultiplier());
182        } else {
183            view.setLineSpacing(value, 1);
184        }
185    }
186
187    @BindingAdapter("android:lineSpacingMultiplier")
188    public static void setLineSpacingMultiplier(TextView view, float value) {
189        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
190            view.setLineSpacing(view.getLineSpacingExtra(), value);
191        } else {
192            view.setLineSpacing(0, value);
193        }
194    }
195
196    @BindingAdapter("android:maxLength")
197    public static void setMaxLength(TextView view, int value) {
198        InputFilter[] filters = view.getFilters();
199        if (filters == null) {
200            filters = new InputFilter[]{
201                    new InputFilter.LengthFilter(value)
202            };
203        } else {
204            boolean foundMaxLength = false;
205            for (int i = 0; i < filters.length; i++) {
206                InputFilter filter = filters[i];
207                if (filter instanceof InputFilter.LengthFilter) {
208                    foundMaxLength = true;
209                    boolean replace = true;
210                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
211                        replace = ((InputFilter.LengthFilter) filter).getMax() != value;
212                    }
213                    if (replace) {
214                        filters[i] = new InputFilter.LengthFilter(value);
215                    }
216                    break;
217                }
218            }
219            if (!foundMaxLength) {
220                // can't use Arrays.copyOf -- it shows up in API 9
221                InputFilter[] oldFilters = filters;
222                filters = new InputFilter[oldFilters.length + 1];
223                System.arraycopy(oldFilters, 0, filters, 0, oldFilters.length);
224                filters[filters.length - 1] = new InputFilter.LengthFilter(value);
225            }
226        }
227        view.setFilters(filters);
228    }
229
230    @BindingAdapter("android:password")
231    public static void setPassword(TextView view, boolean password) {
232        if (password) {
233            view.setTransformationMethod(PasswordTransformationMethod.getInstance());
234        } else if (view.getTransformationMethod() instanceof PasswordTransformationMethod) {
235            view.setTransformationMethod(null);
236        }
237    }
238
239    @BindingAdapter("android:shadowColor")
240    public static void setShadowColor(TextView view, int color) {
241        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
242            float dx = view.getShadowDx();
243            float dy = view.getShadowDy();
244            float r = view.getShadowRadius();
245            view.setShadowLayer(r, dx, dy, color);
246        }
247    }
248
249    @BindingAdapter("android:shadowDx")
250    public static void setShadowDx(TextView view, float dx) {
251        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
252            int color = view.getShadowColor();
253            float dy = view.getShadowDy();
254            float r = view.getShadowRadius();
255            view.setShadowLayer(r, dx, dy, color);
256        }
257    }
258
259    @BindingAdapter("android:shadowDy")
260    public static void setShadowDy(TextView view, float dy) {
261        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
262            int color = view.getShadowColor();
263            float dx = view.getShadowDx();
264            float r = view.getShadowRadius();
265            view.setShadowLayer(r, dx, dy, color);
266        }
267    }
268
269    @BindingAdapter("android:shadowRadius")
270    public static void setShadowRadius(TextView view, float r) {
271        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
272            int color = view.getShadowColor();
273            float dx = view.getShadowDx();
274            float dy = view.getShadowDy();
275            view.setShadowLayer(r, dx, dy, color);
276        }
277    }
278
279    @BindingAdapter("android:textSize")
280    public static void setTextSize(TextView view, float size) {
281        view.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
282    }
283}
284