Home | History | Annotate | Download | only in util
      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