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 getSpanTypeIdInternal(); 140 } 141 142 /** @hide */ getSpanTypeIdInternal()143 public int getSpanTypeIdInternal() { 144 return TextUtils.TEXT_APPEARANCE_SPAN; 145 } 146 describeContents()147 public int describeContents() { 148 return 0; 149 } 150 writeToParcel(Parcel dest, int flags)151 public void writeToParcel(Parcel dest, int flags) { 152 writeToParcelInternal(dest, flags); 153 } 154 155 /** @hide */ writeToParcelInternal(Parcel dest, int flags)156 public void writeToParcelInternal(Parcel dest, int flags) { 157 dest.writeString(mTypeface); 158 dest.writeInt(mStyle); 159 dest.writeInt(mTextSize); 160 if (mTextColor != null) { 161 dest.writeInt(1); 162 mTextColor.writeToParcel(dest, flags); 163 } else { 164 dest.writeInt(0); 165 } 166 if (mTextColorLink != null) { 167 dest.writeInt(1); 168 mTextColorLink.writeToParcel(dest, flags); 169 } else { 170 dest.writeInt(0); 171 } 172 } 173 174 /** 175 * Returns the typeface family specified by this span, or <code>null</code> 176 * if it does not specify one. 177 */ getFamily()178 public String getFamily() { 179 return mTypeface; 180 } 181 182 /** 183 * Returns the text color specified by this span, or <code>null</code> 184 * if it does not specify one. 185 */ getTextColor()186 public ColorStateList getTextColor() { 187 return mTextColor; 188 } 189 190 /** 191 * Returns the link color specified by this span, or <code>null</code> 192 * if it does not specify one. 193 */ getLinkTextColor()194 public ColorStateList getLinkTextColor() { 195 return mTextColorLink; 196 } 197 198 /** 199 * Returns the text size specified by this span, or <code>-1</code> 200 * if it does not specify one. 201 */ getTextSize()202 public int getTextSize() { 203 return mTextSize; 204 } 205 206 /** 207 * Returns the text style specified by this span, or <code>0</code> 208 * if it does not specify one. 209 */ getTextStyle()210 public int getTextStyle() { 211 return mStyle; 212 } 213 214 @Override updateDrawState(TextPaint ds)215 public void updateDrawState(TextPaint ds) { 216 updateMeasureState(ds); 217 218 if (mTextColor != null) { 219 ds.setColor(mTextColor.getColorForState(ds.drawableState, 0)); 220 } 221 222 if (mTextColorLink != null) { 223 ds.linkColor = mTextColorLink.getColorForState(ds.drawableState, 0); 224 } 225 } 226 227 @Override updateMeasureState(TextPaint ds)228 public void updateMeasureState(TextPaint ds) { 229 if (mTypeface != null || mStyle != 0) { 230 Typeface tf = ds.getTypeface(); 231 int style = 0; 232 233 if (tf != null) { 234 style = tf.getStyle(); 235 } 236 237 style |= mStyle; 238 239 if (mTypeface != null) { 240 tf = Typeface.create(mTypeface, style); 241 } else if (tf == null) { 242 tf = Typeface.defaultFromStyle(style); 243 } else { 244 tf = Typeface.create(tf, style); 245 } 246 247 int fake = style & ~tf.getStyle(); 248 249 if ((fake & Typeface.BOLD) != 0) { 250 ds.setFakeBoldText(true); 251 } 252 253 if ((fake & Typeface.ITALIC) != 0) { 254 ds.setTextSkewX(-0.25f); 255 } 256 257 ds.setTypeface(tf); 258 } 259 260 if (mTextSize > 0) { 261 ds.setTextSize(mTextSize); 262 } 263 } 264 } 265