1 /* 2 * Copyright (C) 2014 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mail.browse; 19 20 import android.graphics.Canvas; 21 import android.graphics.Paint; 22 import android.graphics.Paint.FontMetricsInt; 23 import android.graphics.RectF; 24 import android.text.Spanned; 25 import android.text.TextPaint; 26 import android.text.style.CharacterStyle; 27 import android.text.style.ReplacementSpan; 28 29 /** 30 * A replacement span to use when displaying a badge in a conversation list item. 31 * A badge will be some piece of text with a colored background and rounded 32 * corners. 33 */ 34 public class BadgeSpan extends ReplacementSpan { 35 36 public interface BadgeSpanDimensions { 37 /** 38 * Returns the padding value that corresponds to one side of the 39 * horizontal padding surrounding the text inside the background color. 40 */ 41 int getHorizontalPadding(); 42 43 /** 44 * Returns the radius to use for the rounded corners on the background rect. 45 */ 46 float getRoundedCornerRadius(); 47 } 48 49 private TextPaint mWorkPaint = new TextPaint(); 50 /** 51 * A reference to the enclosing Spanned object to collect other CharacterStyle spans and take 52 * them into account when drawing. 53 */ 54 private final Spanned mSpanned; 55 private final BadgeSpanDimensions mDims; 56 57 public BadgeSpan(Spanned spanned, BadgeSpanDimensions dims) { 58 mSpanned = spanned; 59 mDims = dims; 60 } 61 62 @Override 63 public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { 64 if (fm != null) { 65 paint.getFontMetricsInt(fm); 66 // The magic set of measurements to vertically center text within a colored region! 67 fm.top = fm.ascent; 68 } 69 return measureWidth(paint, text, start, end); 70 } 71 72 private int measureWidth(Paint paint, CharSequence text, int start, int end) { 73 return (int) paint.measureText(text, start, end) + 2 * mDims.getHorizontalPadding(); 74 } 75 76 @Override 77 public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, 78 int y, int bottom, Paint paint) { 79 80 mWorkPaint.set(paint); 81 82 // take into account the foreground/background color spans when painting 83 final CharacterStyle[] otherSpans = mSpanned.getSpans(start, end, CharacterStyle.class); 84 for (CharacterStyle otherSpan : otherSpans) { 85 otherSpan.updateDrawState(mWorkPaint); 86 } 87 88 // paint a background if present 89 if (mWorkPaint.bgColor != 0) { 90 final int prevColor = mWorkPaint.getColor(); 91 final Paint.Style prevStyle = mWorkPaint.getStyle(); 92 93 mWorkPaint.setColor(mWorkPaint.bgColor); 94 mWorkPaint.setStyle(Paint.Style.FILL); 95 96 final int bgWidth = measureWidth(mWorkPaint, text, start, end); 97 final RectF rect = new RectF(x, top, x + bgWidth, bottom); 98 final float radius = mDims.getRoundedCornerRadius(); 99 canvas.drawRoundRect(rect, radius, radius, mWorkPaint); 100 101 mWorkPaint.setColor(prevColor); 102 mWorkPaint.setStyle(prevStyle); 103 } 104 105 canvas.drawText(text, start, end, x + mDims.getHorizontalPadding(), y, mWorkPaint); 106 } 107 } 108