Home | History | Annotate | Download | only in notification
      1 /*
      2  * Copyright (C) 2016 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.systemui.statusbar.notification;
     18 
     19 import android.text.Layout;
     20 import android.text.Spanned;
     21 import android.text.TextUtils;
     22 import android.util.Pools;
     23 import android.view.View;
     24 import android.widget.TextView;
     25 
     26 /**
     27  * A transform state of a mText view.
     28 */
     29 public class TextViewTransformState extends TransformState {
     30 
     31     private static Pools.SimplePool<TextViewTransformState> sInstancePool
     32             = new Pools.SimplePool<>(40);
     33     private TextView mText;
     34 
     35     @Override
     36     public void initFrom(View view, TransformInfo transformInfo) {
     37         super.initFrom(view, transformInfo);
     38         mText = (TextView) view;
     39     }
     40 
     41     @Override
     42     protected boolean sameAs(TransformState otherState) {
     43         if (super.sameAs(otherState)) {
     44             return true;
     45         }
     46         if (otherState instanceof TextViewTransformState) {
     47             TextViewTransformState otherTvs = (TextViewTransformState) otherState;
     48             if(TextUtils.equals(otherTvs.mText.getText(), mText.getText())) {
     49                 int ownEllipsized = getEllipsisCount();
     50                 int otherEllipsized = otherTvs.getEllipsisCount();
     51                 return ownEllipsized == otherEllipsized
     52                         && mText.getLineCount() == otherTvs.mText.getLineCount()
     53                         && hasSameSpans(otherTvs);
     54             }
     55         }
     56         return false;
     57     }
     58 
     59     private boolean hasSameSpans(TextViewTransformState otherTvs) {
     60         boolean hasSpans = mText instanceof Spanned;
     61         boolean otherHasSpans = otherTvs.mText instanceof Spanned;
     62         if (hasSpans != otherHasSpans) {
     63             return false;
     64         } else if (!hasSpans) {
     65             return true;
     66         }
     67         // Actually both have spans, let's try to compare them
     68         Spanned ownSpanned = (Spanned) mText;
     69         Object[] spans = ownSpanned.getSpans(0, ownSpanned.length(), Object.class);
     70         Spanned otherSpanned = (Spanned) otherTvs.mText;
     71         Object[] otherSpans = otherSpanned.getSpans(0, otherSpanned.length(), Object.class);
     72         if (spans.length != otherSpans.length) {
     73             return false;
     74         }
     75         for (int i = 0; i < spans.length; i++) {
     76             Object span = spans[i];
     77             Object otherSpan = otherSpans[i];
     78             if (!span.getClass().equals(otherSpan.getClass())) {
     79                 return false;
     80             }
     81             if (ownSpanned.getSpanStart(span) != otherSpanned.getSpanStart(otherSpan)
     82                     || ownSpanned.getSpanEnd(span) != otherSpanned.getSpanEnd(otherSpan)) {
     83                 return false;
     84             }
     85         }
     86         return true;
     87     }
     88 
     89     @Override
     90     protected boolean transformScale(TransformState otherState) {
     91         if (!(otherState instanceof TextViewTransformState)) {
     92             return false;
     93         }
     94         TextViewTransformState otherTvs = (TextViewTransformState) otherState;
     95         if (!TextUtils.equals(mText.getText(), otherTvs.mText.getText())) {
     96             return false;
     97         }
     98         int lineCount = mText.getLineCount();
     99         return lineCount == 1 && lineCount == otherTvs.mText.getLineCount()
    100                 && getEllipsisCount() == otherTvs.getEllipsisCount()
    101                 && getViewHeight() != otherTvs.getViewHeight();
    102     }
    103 
    104     @Override
    105     protected int getViewWidth() {
    106         Layout l = mText.getLayout();
    107         if (l != null) {
    108             return (int) l.getLineWidth(0);
    109         }
    110         return super.getViewWidth();
    111     }
    112 
    113     @Override
    114     protected int getViewHeight() {
    115         return mText.getLineHeight();
    116     }
    117 
    118     private int getInnerHeight(TextView text) {
    119         return text.getHeight() - text.getPaddingTop() - text.getPaddingBottom();
    120     }
    121 
    122     private int getEllipsisCount() {
    123         Layout l = mText.getLayout();
    124         if (l != null) {
    125             int lines = l.getLineCount();
    126             if (lines > 0) {
    127                 // we only care about the first line
    128                 return l.getEllipsisCount(0);
    129             }
    130         }
    131         return 0;
    132     }
    133 
    134     public static TextViewTransformState obtain() {
    135         TextViewTransformState instance = sInstancePool.acquire();
    136         if (instance != null) {
    137             return instance;
    138         }
    139         return new TextViewTransformState();
    140     }
    141 
    142     @Override
    143     public void recycle() {
    144         super.recycle();
    145         sInstancePool.release(this);
    146     }
    147 
    148     @Override
    149     protected void reset() {
    150         super.reset();
    151         mText = null;
    152     }
    153 }
    154