1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.qs.tileimpl; 16 17 import android.content.Context; 18 import android.content.res.Configuration; 19 import android.service.quicksettings.Tile; 20 import android.text.SpannableStringBuilder; 21 import android.text.TextUtils; 22 import android.text.style.ForegroundColorSpan; 23 import android.view.Gravity; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.widget.ImageView; 28 import android.widget.TextView; 29 30 import com.android.systemui.FontSizeUtils; 31 import com.android.systemui.R; 32 import com.android.systemui.plugins.qs.QSIconView; 33 import com.android.systemui.plugins.qs.QSTile; 34 35 import java.util.Objects; 36 37 /** View that represents a standard quick settings tile. **/ 38 public class QSTileView extends QSTileBaseView { 39 private static final int MAX_LABEL_LINES = 2; 40 private static final boolean DUAL_TARGET_ALLOWED = false; 41 private View mDivider; 42 protected TextView mLabel; 43 protected TextView mSecondLine; 44 private ImageView mPadLock; 45 private int mState; 46 private ViewGroup mLabelContainer; 47 private View mExpandIndicator; 48 private View mExpandSpace; 49 50 public QSTileView(Context context, QSIconView icon) { 51 this(context, icon, false); 52 } 53 54 public QSTileView(Context context, QSIconView icon, boolean collapsedView) { 55 super(context, icon, collapsedView); 56 57 setClipChildren(false); 58 setClipToPadding(false); 59 60 setClickable(true); 61 setId(View.generateViewId()); 62 createLabel(); 63 setOrientation(VERTICAL); 64 setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); 65 } 66 67 TextView getLabel() { 68 return mLabel; 69 } 70 71 @Override 72 protected void onConfigurationChanged(Configuration newConfig) { 73 super.onConfigurationChanged(newConfig); 74 FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size); 75 FontSizeUtils.updateFontSize(mSecondLine, R.dimen.qs_tile_text_size); 76 } 77 78 @Override 79 public int getDetailY() { 80 return getTop() + mLabelContainer.getTop() + mLabelContainer.getHeight() / 2; 81 } 82 83 protected void createLabel() { 84 mLabelContainer = (ViewGroup) LayoutInflater.from(getContext()) 85 .inflate(R.layout.qs_tile_label, this, false); 86 mLabelContainer.setClipChildren(false); 87 mLabelContainer.setClipToPadding(false); 88 mLabel = mLabelContainer.findViewById(R.id.tile_label); 89 mPadLock = mLabelContainer.findViewById(R.id.restricted_padlock); 90 mDivider = mLabelContainer.findViewById(R.id.underline); 91 mExpandIndicator = mLabelContainer.findViewById(R.id.expand_indicator); 92 mExpandSpace = mLabelContainer.findViewById(R.id.expand_space); 93 mSecondLine = mLabelContainer.findViewById(R.id.app_label); 94 addView(mLabelContainer); 95 } 96 97 @Override 98 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 99 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 100 101 // Remeasure view if the primary label requires more then 2 lines or the secondary label 102 // text will be cut off. 103 if (mLabel.getLineCount() > MAX_LABEL_LINES || !TextUtils.isEmpty(mSecondLine.getText()) 104 && mSecondLine.getLineHeight() > mSecondLine.getHeight()) { 105 mLabel.setSingleLine(); 106 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 107 } 108 } 109 110 @Override 111 protected void handleStateChanged(QSTile.State state) { 112 super.handleStateChanged(state); 113 if (!Objects.equals(mLabel.getText(), state.label) || mState != state.state) { 114 if (state.state == Tile.STATE_UNAVAILABLE) { 115 int color = QSTileImpl.getColorForState(getContext(), state.state); 116 state.label = new SpannableStringBuilder().append(state.label, 117 new ForegroundColorSpan(color), 118 SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE); 119 } 120 mState = state.state; 121 mLabel.setText(state.label); 122 } 123 if (!Objects.equals(mSecondLine.getText(), state.secondaryLabel)) { 124 mSecondLine.setText(state.secondaryLabel); 125 mSecondLine.setVisibility(TextUtils.isEmpty(state.secondaryLabel) ? View.GONE 126 : View.VISIBLE); 127 } 128 boolean dualTarget = DUAL_TARGET_ALLOWED && state.dualTarget; 129 mExpandIndicator.setVisibility(dualTarget ? View.VISIBLE : View.GONE); 130 mExpandSpace.setVisibility(dualTarget ? View.VISIBLE : View.GONE); 131 mLabelContainer.setContentDescription(dualTarget ? state.dualLabelContentDescription 132 : null); 133 if (dualTarget != mLabelContainer.isClickable()) { 134 mLabelContainer.setClickable(dualTarget); 135 mLabelContainer.setLongClickable(dualTarget); 136 mLabelContainer.setBackground(dualTarget ? newTileBackground() : null); 137 } 138 mLabel.setEnabled(!state.disabledByPolicy); 139 mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE); 140 } 141 142 @Override 143 public void init(OnClickListener click, OnClickListener secondaryClick, 144 OnLongClickListener longClick) { 145 super.init(click, secondaryClick, longClick); 146 mLabelContainer.setOnClickListener(secondaryClick); 147 mLabelContainer.setOnLongClickListener(longClick); 148 mLabelContainer.setClickable(false); 149 mLabelContainer.setLongClickable(false); 150 } 151 } 152