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