/*
|
* Copyright (C) 2014 The Android Open Source Project
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
package com.android.systemui.qs;
|
|
import android.content.Context;
|
import android.graphics.Typeface;
|
import android.graphics.drawable.Drawable;
|
import android.text.TextUtils;
|
import android.text.TextUtils.TruncateAt;
|
import android.view.Gravity;
|
import android.view.View;
|
import android.widget.ImageView;
|
import android.widget.LinearLayout;
|
import android.widget.TextView;
|
|
import com.android.systemui.R;
|
|
import java.util.Objects;
|
|
/**
|
* Text displayed over one or two lines, centered horizontally. A caret is always drawn at the end
|
* of the first line, and considered part of the content for centering purposes.
|
*
|
* Text overflow rules:
|
* First line: break on a word, unless a single word takes up the entire line - in which case
|
* truncate.
|
* Second line: ellipsis if necessary
|
*/
|
public class QSDualTileLabel extends LinearLayout {
|
|
private final Context mContext;
|
private final TextView mFirstLine;
|
private final ImageView mFirstLineCaret;
|
private final TextView mSecondLine;
|
private final int mHorizontalPaddingPx;
|
|
private String mText;
|
|
public QSDualTileLabel(Context context) {
|
super(context);
|
mContext = context;
|
setOrientation(LinearLayout.VERTICAL);
|
|
mHorizontalPaddingPx = mContext.getResources()
|
.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_horizontal);
|
|
mFirstLine = initTextView();
|
mFirstLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
|
final LinearLayout firstLineLayout = new LinearLayout(mContext);
|
firstLineLayout.setPadding(0, 0, 0, 0);
|
firstLineLayout.setOrientation(LinearLayout.HORIZONTAL);
|
firstLineLayout.setClickable(false);
|
firstLineLayout.setBackground(null);
|
firstLineLayout.addView(mFirstLine);
|
mFirstLineCaret = new ImageView(mContext);
|
mFirstLineCaret.setScaleType(ImageView.ScaleType.MATRIX);
|
mFirstLineCaret.setClickable(false);
|
firstLineLayout.addView(mFirstLineCaret);
|
addView(firstLineLayout, newLinearLayoutParams());
|
|
mSecondLine = initTextView();
|
mSecondLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
|
mSecondLine.setEllipsize(TruncateAt.END);
|
mSecondLine.setVisibility(GONE);
|
addView(mSecondLine, newLinearLayoutParams());
|
|
addOnLayoutChangeListener(new OnLayoutChangeListener() {
|
@Override
|
public void onLayoutChange(View v, int left, int top, int right,
|
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
if ((oldRight - oldLeft) != (right - left)) {
|
rescheduleUpdateText();
|
}
|
}
|
});
|
}
|
|
private static LayoutParams newLinearLayoutParams() {
|
final LayoutParams lp =
|
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
lp.gravity = Gravity.CENTER_HORIZONTAL;
|
return lp;
|
}
|
|
public void setFirstLineCaret(Drawable d) {
|
mFirstLineCaret.setImageDrawable(d);
|
if (d != null) {
|
final int h = d.getIntrinsicHeight();
|
mFirstLine.setMinHeight(h);
|
mFirstLine.setPadding(mHorizontalPaddingPx, 0, 0, 0);
|
}
|
}
|
|
private TextView initTextView() {
|
final TextView tv = new TextView(mContext);
|
tv.setPadding(0, 0, 0, 0);
|
tv.setGravity(Gravity.CENTER_VERTICAL);
|
tv.setSingleLine(true);
|
tv.setClickable(false);
|
tv.setBackground(null);
|
return tv;
|
}
|
|
public void setText(CharSequence text) {
|
final String newText = text == null ? null : text.toString().trim();
|
if (Objects.equals(newText, mText)) return;
|
mText = newText;
|
rescheduleUpdateText();
|
}
|
|
public String getText() {
|
return mText;
|
}
|
|
public void setTextSize(int unit, float size) {
|
mFirstLine.setTextSize(unit, size);
|
mSecondLine.setTextSize(unit, size);
|
rescheduleUpdateText();
|
}
|
|
public void setTextColor(int color) {
|
mFirstLine.setTextColor(color);
|
mSecondLine.setTextColor(color);
|
rescheduleUpdateText();
|
}
|
|
public void setTypeface(Typeface tf) {
|
mFirstLine.setTypeface(tf);
|
mSecondLine.setTypeface(tf);
|
rescheduleUpdateText();
|
}
|
|
private void rescheduleUpdateText() {
|
removeCallbacks(mUpdateText);
|
post(mUpdateText);
|
}
|
|
private void updateText() {
|
if (getWidth() == 0) return;
|
if (TextUtils.isEmpty(mText)) {
|
mFirstLine.setText(null);
|
mSecondLine.setText(null);
|
mSecondLine.setVisibility(GONE);
|
return;
|
}
|
final float maxWidth = getWidth() - mFirstLineCaret.getWidth() - mHorizontalPaddingPx
|
- getPaddingLeft() - getPaddingRight();
|
float width = mFirstLine.getPaint().measureText(mText);
|
if (width <= maxWidth) {
|
mFirstLine.setText(mText);
|
mSecondLine.setText(null);
|
mSecondLine.setVisibility(GONE);
|
return;
|
}
|
final int n = mText.length();
|
int lastWordBoundary = -1;
|
boolean inWhitespace = false;
|
int i = 0;
|
for (i = 1; i < n; i++) {
|
width = mFirstLine.getPaint().measureText(mText.substring(0, i));
|
final boolean done = width > maxWidth;
|
if (Character.isWhitespace(mText.charAt(i))) {
|
if (!inWhitespace && !done) {
|
lastWordBoundary = i;
|
}
|
inWhitespace = true;
|
} else {
|
inWhitespace = false;
|
}
|
if (done) {
|
break;
|
}
|
}
|
if (lastWordBoundary == -1) {
|
lastWordBoundary = i - 1;
|
}
|
mFirstLine.setText(mText.substring(0, lastWordBoundary));
|
mSecondLine.setText(mText.substring(lastWordBoundary).trim());
|
mSecondLine.setVisibility(VISIBLE);
|
}
|
|
private final Runnable mUpdateText = new Runnable() {
|
@Override
|
public void run() {
|
updateText();
|
}
|
};
|
}
|