1 /* 2 * Copyright (C) 2020 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 com.android.tv.settings.widget; 18 19 import android.content.Context; 20 import android.graphics.Canvas; 21 import android.graphics.Paint; 22 import android.graphics.drawable.Drawable; 23 import android.text.style.DynamicDrawableSpan; 24 25 import androidx.annotation.DrawableRes; 26 27 /** 28 * A customized dynamic drawable span which aligns to the center of the text. This assumes that 29 * the text is smaller than the image, which will be the case most of the time. 30 * This class is mirrored from Setup. 31 * 32 * NOTE: For icon that is considerably larger than the text around it (taller than the distance 33 * between the font's top and bottom), the icon could be cut off if it is in the first or last line 34 * of a TextView. Please consider using smaller icon or adding blank lines before and after the 35 * paragraph. 36 */ 37 public class CenterAlignedDynamicDrawableSpan extends DynamicDrawableSpan { 38 39 private final Context mContext; 40 private final int mResourceId; 41 CenterAlignedDynamicDrawableSpan(Context context, @DrawableRes int resourceId)42 public CenterAlignedDynamicDrawableSpan(Context context, @DrawableRes int resourceId) { 43 super(); 44 this.mContext = context; 45 this.mResourceId = resourceId; 46 } 47 48 @Override getSize( Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm)49 public int getSize( 50 Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 51 super.getSize(paint, text, start, end, fm); 52 53 if (fm != null) { 54 fm.ascent = paint.getFontMetricsInt().ascent; 55 fm.descent = paint.getFontMetricsInt().descent; 56 fm.top = fm.ascent; 57 fm.bottom = fm.descent; 58 } 59 60 return getDrawable().getBounds().right; 61 } 62 63 @Override draw( Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)64 public void draw( 65 Canvas canvas, 66 CharSequence text, 67 int start, 68 int end, 69 float x, 70 int top, 71 int y, 72 int bottom, 73 Paint paint) { 74 Drawable drawable = getDrawable(); 75 canvas.save(); 76 77 Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); 78 int fontHeight = fmPaint.descent - fmPaint.ascent; 79 80 // Align text descent (bottom most part) to bottom of drawable 81 int transY = bottom - drawable.getBounds().bottom; 82 // Translate half of the extra space between the drawable and the font to center. 83 transY += (drawable.getIntrinsicHeight() - fontHeight) / 2; 84 85 canvas.translate(x, transY); 86 drawable.draw(canvas); 87 canvas.restore(); 88 } 89 90 @Override getDrawable()91 public Drawable getDrawable() { 92 Drawable drawable = mContext.getDrawable(mResourceId); 93 drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 94 return drawable; 95 } 96 } 97