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