TextAppearanceSpan.java revision d24b8183b93e781080b2c16c487e60d51c12da31
1/*
2 * Copyright (C) 2008 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.text.style;
18
19import android.content.Context;
20import android.content.res.ColorStateList;
21import android.content.res.TypedArray;
22import android.graphics.Typeface;
23import android.os.Parcel;
24import android.text.ParcelableSpan;
25import android.text.TextPaint;
26import android.text.TextUtils;
27
28/**
29 * Sets the text color, size, style, and typeface to match a TextAppearance
30 * resource.
31 */
32public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
33    private final String mTypeface;
34    private final int mStyle;
35    private final int mTextSize;
36    private final ColorStateList mTextColor;
37    private final ColorStateList mTextColorLink;
38
39    /**
40     * Uses the specified TextAppearance resource to determine the
41     * text appearance.  The <code>appearance</code> should be, for example,
42     * <code>android.R.style.TextAppearance_Small</code>.
43     */
44    public TextAppearanceSpan(Context context, int appearance) {
45        this(context, appearance, -1);
46    }
47
48    /**
49     * Uses the specified TextAppearance resource to determine the
50     * text appearance, and the specified text color resource
51     * to determine the color.  The <code>appearance</code> should be,
52     * for example, <code>android.R.style.TextAppearance_Small</code>,
53     * and the <code>colorList</code> should be, for example,
54     * <code>android.R.styleable.Theme_textColorDim</code>.
55     */
56    public TextAppearanceSpan(Context context, int appearance,
57                              int colorList) {
58        ColorStateList textColor;
59
60        TypedArray a =
61            context.obtainStyledAttributes(appearance,
62                                           com.android.internal.R.styleable.TextAppearance);
63
64        textColor = a.getColorStateList(com.android.internal.R.styleable.
65                                        TextAppearance_textColor);
66        mTextColorLink = a.getColorStateList(com.android.internal.R.styleable.
67                                        TextAppearance_textColorLink);
68        mTextSize = a.getDimensionPixelSize(com.android.internal.R.styleable.
69                                        TextAppearance_textSize, -1);
70
71        mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0);
72        int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);
73
74        switch (tf) {
75            case 1:
76                mTypeface = "sans";
77                break;
78
79            case 2:
80                mTypeface = "serif";
81                break;
82
83            case 3:
84                mTypeface = "monospace";
85                break;
86
87            default:
88                mTypeface = null;
89                break;
90        }
91
92        a.recycle();
93
94        if (colorList >= 0) {
95            a = context.obtainStyledAttributes(com.android.internal.R.style.Theme,
96                                            com.android.internal.R.styleable.Theme);
97
98            textColor = a.getColorStateList(colorList);
99            a.recycle();
100        }
101
102        mTextColor = textColor;
103    }
104
105    /**
106     * Makes text be drawn with the specified typeface, size, style,
107     * and colors.
108     */
109    public TextAppearanceSpan(String family, int style, int size,
110                              ColorStateList color, ColorStateList linkColor) {
111        mTypeface = family;
112        mStyle = style;
113        mTextSize = size;
114        mTextColor = color;
115        mTextColorLink = linkColor;
116    }
117
118    public TextAppearanceSpan(Parcel src) {
119        mTypeface = src.readString();
120        mStyle = src.readInt();
121        mTextSize = src.readInt();
122        if (src.readInt() != 0) {
123            mTextColor = ColorStateList.CREATOR.createFromParcel(src);
124        } else {
125            mTextColor = null;
126        }
127        if (src.readInt() != 0) {
128            mTextColorLink = ColorStateList.CREATOR.createFromParcel(src);
129        } else {
130            mTextColorLink = null;
131        }
132    }
133
134    public int getSpanTypeId() {
135        return TextUtils.TEXT_APPEARANCE_SPAN;
136    }
137
138    public int describeContents() {
139        return 0;
140    }
141
142    public void writeToParcel(Parcel dest, int flags) {
143        dest.writeString(mTypeface);
144        dest.writeInt(mStyle);
145        dest.writeInt(mTextSize);
146        if (mTextColor != null) {
147            dest.writeInt(1);
148            mTextColor.writeToParcel(dest, flags);
149        } else {
150            dest.writeInt(0);
151        }
152        if (mTextColorLink != null) {
153            dest.writeInt(1);
154            mTextColorLink.writeToParcel(dest, flags);
155        } else {
156            dest.writeInt(0);
157        }
158    }
159
160    /**
161     * Returns the typeface family specified by this span, or <code>null</code>
162     * if it does not specify one.
163     */
164    public String getFamily() {
165        return mTypeface;
166    }
167
168    /**
169     * Returns the text color specified by this span, or <code>null</code>
170     * if it does not specify one.
171     */
172    public ColorStateList getTextColor() {
173        return mTextColor;
174    }
175
176    /**
177     * Returns the link color specified by this span, or <code>null</code>
178     * if it does not specify one.
179     */
180    public ColorStateList getLinkTextColor() {
181        return mTextColorLink;
182    }
183
184    /**
185     * Returns the text size specified by this span, or <code>-1</code>
186     * if it does not specify one.
187     */
188    public int getTextSize() {
189        return mTextSize;
190    }
191
192    /**
193     * Returns the text style specified by this span, or <code>0</code>
194     * if it does not specify one.
195     */
196    public int getTextStyle() {
197        return mStyle;
198    }
199
200    @Override
201    public void updateDrawState(TextPaint ds) {
202        updateMeasureState(ds);
203
204        if (mTextColor != null) {
205            ds.setColor(mTextColor.getColorForState(ds.drawableState, 0));
206        }
207
208        if (mTextColorLink != null) {
209            ds.linkColor = mTextColor.getColorForState(ds.drawableState, 0);
210        }
211    }
212
213    @Override
214    public void updateMeasureState(TextPaint ds) {
215        if (mTypeface != null || mStyle != 0) {
216            Typeface tf = ds.getTypeface();
217            int style = 0;
218
219            if (tf != null) {
220                style = tf.getStyle();
221            }
222
223            style |= mStyle;
224
225            if (mTypeface != null) {
226                tf = Typeface.create(mTypeface, style);
227            } else if (tf == null) {
228                tf = Typeface.defaultFromStyle(style);
229            } else {
230                tf = Typeface.create(tf, style);
231            }
232
233            int fake = style & ~tf.getStyle();
234
235            if ((fake & Typeface.BOLD) != 0) {
236                ds.setFakeBoldText(true);
237            }
238
239            if ((fake & Typeface.ITALIC) != 0) {
240                ds.setTextSkewX(-0.25f);
241            }
242
243            ds.setTypeface(tf);
244        }
245
246        if (mTextSize > 0) {
247            ds.setTextSize(mTextSize);
248        }
249    }
250}
251