1 /*
2  * Copyright (C) 2019 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.car.apps.common;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.graphics.Rect;
22 import android.text.method.TransformationMethod;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.widget.TextView;
26 
27 /**
28  * UX Restrictions compliant TextView.
29  * This class will automatically listen to Car UXRestrictions and truncate text accordingly.
30  *
31  * Attributes that trigger {@link TextView#setTransformationMethod} should NOT be set and calls to
32  * the method should NOT be made to prevent overriding UX Restrictions.
33  * This includes, but is not limited to:
34  * {@link TextView#setInputType}
35  * {@link TextView#setAllCaps}
36  * {@link TextView#setSingleLine}
37  * android:inputType="textPassword"
38  * android:textAllCaps="true"
39  * android:singleLine="true"
40  */
41 public class UxrTextView extends TextView {
42     private CarUxRestrictionsUtil mCarUxRestrictionsUtil;
43     private CarUxRestrictions mCarUxRestrictions;
44     private CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener;
45 
UxrTextView(Context context)46     public UxrTextView(Context context) {
47         super(context);
48         init(context);
49     }
50 
UxrTextView(Context context, AttributeSet attrs)51     public UxrTextView(Context context, AttributeSet attrs) {
52         super(context, attrs);
53         init(context);
54     }
55 
UxrTextView(Context context, AttributeSet attrs, int defStyleAttr)56     public UxrTextView(Context context, AttributeSet attrs, int defStyleAttr) {
57         super(context, attrs, defStyleAttr);
58         init(context);
59     }
60 
UxrTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)61     public UxrTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
62         super(context, attrs, defStyleAttr, defStyleRes);
63         init(context);
64     }
65 
init(Context context)66     private void init(Context context) {
67         mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
68         mListener = this::updateCarUxRestrictions;
69     }
70 
updateCarUxRestrictions(CarUxRestrictions carUxRestrictions)71     private void updateCarUxRestrictions(CarUxRestrictions carUxRestrictions) {
72         mCarUxRestrictions = carUxRestrictions;
73 
74         // setTransformationMethod doesn't do anything when passed the same instance...
75         setTransformationMethod(new UXRTransformationMethod());
76     }
77 
78     @Override
onAttachedToWindow()79     protected void onAttachedToWindow() {
80         super.onAttachedToWindow();
81         mCarUxRestrictionsUtil.register(mListener);
82     }
83 
84     @Override
onDetachedFromWindow()85     protected void onDetachedFromWindow() {
86         super.onDetachedFromWindow();
87         mCarUxRestrictionsUtil.unregister(mListener);
88     }
89 
90     @Override
setAllCaps(boolean b)91     public void setAllCaps(boolean b) {
92         // NOP
93     }
94 
95     @Override
setSingleLine(boolean b)96     public void setSingleLine(boolean b) {
97         // NOP
98     }
99 
100     @Override
setInputType(int i)101     public void setInputType(int i) {
102         // NOP
103     }
104 
105     private class UXRTransformationMethod implements TransformationMethod {
106         @Override
getTransformation(CharSequence source, View view)107         public CharSequence getTransformation(CharSequence source, View view) {
108             if (source == null) {
109                 return "";
110             }
111             return CarUxRestrictionsUtil.complyString(getContext(), source.toString(),
112                     mCarUxRestrictions);
113         }
114 
115         @Override
onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect)116         public void onFocusChanged(View view, CharSequence sourceText, boolean focused,
117                 int direction, Rect previouslyFocusedRect) {
118             // Not used
119         }
120     }
121 }
122