• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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.dialer.util;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.graphics.Paint;
22 import android.graphics.Point;
23 import android.os.PowerManager;
24 import android.provider.Settings;
25 import android.provider.Settings.Global;
26 import android.support.annotation.NonNull;
27 import android.text.TextUtils;
28 import android.util.TypedValue;
29 import android.view.Display;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
33 import android.view.ViewTreeObserver.OnPreDrawListener;
34 import android.view.WindowManager;
35 import android.widget.TextView;
36 import java.util.Locale;
37 
38 /** Provides static functions to work with views */
39 public class ViewUtil {
40 
ViewUtil()41   private ViewUtil() {}
42 
43   /** Similar to {@link Runnable} but takes a View parameter to operate on */
44   public interface ViewRunnable {
run(@onNull View view)45     void run(@NonNull View view);
46   }
47 
48   /**
49    * Returns the width as specified in the LayoutParams
50    *
51    * @throws IllegalStateException Thrown if the view's width is unknown before a layout pass s
52    */
getConstantPreLayoutWidth(View view)53   public static int getConstantPreLayoutWidth(View view) {
54     // We haven't been layed out yet, so get the size from the LayoutParams
55     final ViewGroup.LayoutParams p = view.getLayoutParams();
56     if (p.width < 0) {
57       throw new IllegalStateException(
58           "Expecting view's width to be a constant rather " + "than a result of the layout pass");
59     }
60     return p.width;
61   }
62 
63   /**
64    * Returns a boolean indicating whether or not the view's layout direction is RTL
65    *
66    * @param view - A valid view
67    * @return True if the view's layout direction is RTL
68    */
isViewLayoutRtl(View view)69   public static boolean isViewLayoutRtl(View view) {
70     return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
71   }
72 
isRtl()73   public static boolean isRtl() {
74     return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
75   }
76 
resizeText(TextView textView, int originalTextSize, int minTextSize)77   public static void resizeText(TextView textView, int originalTextSize, int minTextSize) {
78     final Paint paint = textView.getPaint();
79     final int width = textView.getWidth();
80     if (width == 0) {
81       return;
82     }
83     textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, originalTextSize);
84     float ratio = width / paint.measureText(textView.getText().toString());
85     if (ratio <= 1.0f) {
86       textView.setTextSize(
87           TypedValue.COMPLEX_UNIT_PX, Math.max(minTextSize, originalTextSize * ratio));
88     }
89   }
90 
91   /** Runs a piece of code just before the next draw, after layout and measurement */
doOnPreDraw( @onNull final View view, final boolean drawNextFrame, final Runnable runnable)92   public static void doOnPreDraw(
93       @NonNull final View view, final boolean drawNextFrame, final Runnable runnable) {
94     view.getViewTreeObserver()
95         .addOnPreDrawListener(
96             new OnPreDrawListener() {
97               @Override
98               public boolean onPreDraw() {
99                 view.getViewTreeObserver().removeOnPreDrawListener(this);
100                 runnable.run();
101                 return drawNextFrame;
102               }
103             });
104   }
105 
doOnPreDraw( @onNull final View view, final boolean drawNextFrame, final ViewRunnable runnable)106   public static void doOnPreDraw(
107       @NonNull final View view, final boolean drawNextFrame, final ViewRunnable runnable) {
108     view.getViewTreeObserver()
109         .addOnPreDrawListener(
110             new OnPreDrawListener() {
111               @Override
112               public boolean onPreDraw() {
113                 view.getViewTreeObserver().removeOnPreDrawListener(this);
114                 runnable.run(view);
115                 return drawNextFrame;
116               }
117             });
118   }
119 
doOnGlobalLayout(@onNull final View view, final ViewRunnable runnable)120   public static void doOnGlobalLayout(@NonNull final View view, final ViewRunnable runnable) {
121     view.getViewTreeObserver()
122         .addOnGlobalLayoutListener(
123             new OnGlobalLayoutListener() {
124               @Override
125               public void onGlobalLayout() {
126                 view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
127                 runnable.run(view);
128               }
129             });
130   }
131 
132   /**
133    * Returns {@code true} if animations should be disabled.
134    *
135    * <p>Animations should be disabled if {@link
136    * android.provider.Settings.Global#ANIMATOR_DURATION_SCALE} is set to 0 through system settings
137    * or the device is in power save mode.
138    */
areAnimationsDisabled(Context context)139   public static boolean areAnimationsDisabled(Context context) {
140     ContentResolver contentResolver = context.getContentResolver();
141     PowerManager powerManager = context.getSystemService(PowerManager.class);
142     return Settings.Global.getFloat(contentResolver, Global.ANIMATOR_DURATION_SCALE, 1.0f) == 0
143         || powerManager.isPowerSaveMode();
144   }
145 
146   /**
147    * Get navigation bar height by calculating difference between app usable size and real screen
148    * size. Note that this won't work in multi-window mode so it's caller's responsibility to check
149    * if the app is in multi-window mode before using this.
150    *
151    * @param context Context
152    * @return Navigation bar height
153    */
getNavigationBarHeight(Context context)154   public static int getNavigationBarHeight(Context context) {
155     WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
156     Display display = windowManager.getDefaultDisplay();
157     Point appUsableSize = getAppUsableScreenSize(display);
158     Point realScreenSize = getRealScreenSize(display);
159 
160     // Navigation bar on the right.
161     if (appUsableSize.x < realScreenSize.x) {
162       return appUsableSize.y;
163     }
164 
165     // Navigation bar at the bottom.
166     if (appUsableSize.y < realScreenSize.y) {
167       return realScreenSize.y - appUsableSize.y;
168     }
169 
170     // Navigation bar is not present.
171     return 0;
172   }
173 
getAppUsableScreenSize(Display display)174   private static Point getAppUsableScreenSize(Display display) {
175     Point size = new Point();
176     display.getSize(size);
177     return size;
178   }
179 
getRealScreenSize(Display display)180   private static Point getRealScreenSize(Display display) {
181     Point size = new Point();
182     display.getRealSize(size);
183 
184     return size;
185   }
186 }
187