QSDualTileLabel.java revision 92d9b19e1bc5f93ef31c4e6eb3395eaf78a5c84e
1/* 2 * Copyright (C) 2014 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 com.android.systemui.qs; 18 19import android.content.Context; 20import android.graphics.Typeface; 21import android.graphics.drawable.Drawable; 22import android.text.TextUtils; 23import android.text.TextUtils.TruncateAt; 24import android.view.Gravity; 25import android.view.View; 26import android.widget.FrameLayout; 27import android.widget.TextView; 28 29import java.util.Objects; 30 31/** 32 * Text displayed over one or two lines, centered horizontally. A caret is always drawn at the end 33 * of the first line, and considered part of the content for centering purposes. 34 * 35 * Text overflow rules: 36 * First line: break on a word, unless a single word takes up the entire line - in which case 37 * truncate. 38 * Second line: ellipsis if necessary 39 */ 40public class QSDualTileLabel extends FrameLayout { 41 42 private static final String SPACING_TEXT = " "; 43 44 private final Context mContext; 45 private final TextView mFirstLine; 46 private final TextView mSecondLine; 47 48 private String mText; 49 50 public QSDualTileLabel(Context context) { 51 super(context); 52 mContext = context; 53 mFirstLine = initTextView(); 54 mSecondLine = initTextView(); 55 mSecondLine.setEllipsize(TruncateAt.END); 56 addOnLayoutChangeListener(new OnLayoutChangeListener() { 57 @Override 58 public void onLayoutChange(View v, int left, int top, int right, 59 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 60 if ((oldRight - oldLeft) != (right - left)) { 61 updateText(); 62 } 63 } 64 }); 65 } 66 67 public void setFirstLineBackground(Drawable d) { 68 mFirstLine.setBackground(d); 69 if (d != null) { 70 final LayoutParams lp = (LayoutParams) mSecondLine.getLayoutParams(); 71 lp.topMargin = d.getIntrinsicHeight() * 3 / 4; 72 mSecondLine.setLayoutParams(lp); 73 } 74 } 75 76 private TextView initTextView() { 77 final TextView tv = new TextView(mContext); 78 tv.setPadding(0, 0, 0, 0); 79 tv.setSingleLine(true); 80 tv.setClickable(false); 81 tv.setBackground(null); 82 final LayoutParams lp = 83 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 84 lp.gravity = Gravity.CENTER_HORIZONTAL; 85 addView(tv, lp); 86 return tv; 87 } 88 89 public void setText(CharSequence text) { 90 final String newText = text == null ? null : text.toString().trim(); 91 if (Objects.equals(newText, mText)) return; 92 mText = newText; 93 updateText(); 94 } 95 96 public String getText() { 97 return mText; 98 } 99 100 public void setTextSize(int unit, float size) { 101 mFirstLine.setTextSize(unit, size); 102 mSecondLine.setTextSize(unit, size); 103 } 104 105 public void setTextColor(int color) { 106 mFirstLine.setTextColor(color); 107 mSecondLine.setTextColor(color); 108 } 109 110 public void setTypeface(Typeface tf) { 111 mFirstLine.setTypeface(tf); 112 mSecondLine.setTypeface(tf); 113 } 114 115 private void updateText() { 116 if (getWidth() == 0) return; 117 if (TextUtils.isEmpty(mText)) { 118 mFirstLine.setText(null); 119 mSecondLine.setText(null); 120 return; 121 } 122 final float maxWidth = getWidth() - mFirstLine.getBackground().getIntrinsicWidth() 123 - getPaddingLeft() - getPaddingRight(); 124 float width = mFirstLine.getPaint().measureText(mText + SPACING_TEXT); 125 if (width <= maxWidth) { 126 mFirstLine.setText(mText + SPACING_TEXT); 127 mSecondLine.setText(null); 128 return; 129 } 130 final int n = mText.length(); 131 int lastWordBoundary = -1; 132 boolean inWhitespace = false; 133 int i = 0; 134 for (i = 1; i < n; i++) { 135 if (Character.isWhitespace(mText.charAt(i))) { 136 if (!inWhitespace) { 137 lastWordBoundary = i; 138 } 139 inWhitespace = true; 140 } else { 141 inWhitespace = false; 142 } 143 width = mFirstLine.getPaint().measureText(mText.substring(0, i) + SPACING_TEXT); 144 if (width > maxWidth) { 145 break; 146 } 147 } 148 if (lastWordBoundary == -1) { 149 lastWordBoundary = i - 1; 150 } 151 mFirstLine.setText(mText.substring(0, lastWordBoundary) + SPACING_TEXT); 152 mSecondLine.setText(mText.substring(lastWordBoundary).trim()); 153 } 154} 155