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 41 private ViewUtil() {} 42 43 /** Similar to {@link Runnable} but takes a View parameter to operate on */ 44 public interface ViewRunnable { 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 */ 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 */ 69 public static boolean isViewLayoutRtl(View view) { 70 return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 71 } 72 73 public static boolean isRtl() { 74 return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL; 75 } 76 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 */ 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 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 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 */ 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 */ 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 174 private static Point getAppUsableScreenSize(Display display) { 175 Point size = new Point(); 176 display.getSize(size); 177 return size; 178 } 179 180 private static Point getRealScreenSize(Display display) { 181 Point size = new Point(); 182 display.getRealSize(size); 183 184 return size; 185 } 186 } 187