com.xxxifan.devbox.core.util.ViewUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.xxxifan.devbox.core.util.ViewUtils.java

Source

/*
 * Copyright(c) 2016 xxxifan
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xxxifan.devbox.core.util;

import android.app.Activity;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.afollestad.materialdialogs.MaterialDialog;
import com.xxxifan.devbox.core.Devbox;
import com.xxxifan.devbox.core.R;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import rx.Observable;
import rx.functions.Action0;

/**
 * Created by xifan on 4/6/16.
 */
public class ViewUtils {

    private static final String CONFIG_SHOW_NAVBAR = "config_showNavigationBar";
    private static final String CONFIG_FORCE_NAVBAR = "dev_force_show_navbar";
    private static final String CONFIG_TOOLBAR_HEIGHT = "status_bar_height";

    private static boolean sHasTranslucentNavBar;
    private static float sDensity = 0;
    private static float sScaledDensity = 0;
    private static int sStatusBarHeight;
    private static int sNavBarHeight;
    private static int sScreenHeight;
    private static int sScreenWidth;

    static {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // find custom settings first: force hardware key by build.prop or cm enabler
            IOUtils.runCmd(new String[] { "getprop", "qemu.hw.mainkeys" }, new IOUtils.CommandCallback() {
                public void done(String forceKey, IOException e) {
                    if (e != null) {
                        e.printStackTrace();
                        return;
                    }

                    if (forceKey.equals("0")) {
                        sHasTranslucentNavBar = true;
                        return;
                    }

                    Context context = Devbox.getAppDelegate();
                    // check cm settings
                    ContentResolver resolver = context.getContentResolver();
                    boolean forceCm = Settings.Secure.getInt(resolver, CONFIG_FORCE_NAVBAR, 0) == 1;

                    // fallback, use common method.
                    sHasTranslucentNavBar = forceCm || readInternalBoolean(CONFIG_SHOW_NAVBAR,
                            context.getResources(), !ViewConfiguration.get(context).hasPermanentMenuKey());
                }
            });
        }
    }

    protected ViewUtils() {
    }

    public static int dp2px(float dp) {
        return (int) (dp * getDensity() + 0.5f);
    }

    public static float sp2px(float sp) {
        getDensity();
        return sp * sScaledDensity;
    }

    public static float px2dp(int px) {
        return px / getDensity() + 0.5f;
    }

    public static int getDimenInt(@DimenRes int dimenId) {
        return Devbox.getAppDelegate().getResources().getDimensionPixelSize(dimenId);
    }

    public static float getDimen(@DimenRes int dimenId) {
        return Devbox.getAppDelegate().getResources().getDimension(dimenId);
    }

    public static boolean hasTranslucentNavBar() {
        return sHasTranslucentNavBar;
    }

    public static boolean hasTranslucentBar() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    }

    public static int getSystemBarHeight() {
        if (sStatusBarHeight == 0) {
            sStatusBarHeight = readInternalDimen(CONFIG_TOOLBAR_HEIGHT, Devbox.getAppDelegate().getResources(),
                    dp2px(24));
        }
        return sStatusBarHeight;
    }

    public static int getDeviceScreenHeight() {
        if (sScreenHeight == 0) {
            sScreenHeight = getDisplayMetrics().heightPixels;
        }
        return sScreenHeight;
    }

    public static int getDeviceScreenWidth() {
        if (sScreenWidth == 0) {
            sScreenWidth = getDisplayMetrics().widthPixels;
        }
        return sScreenWidth;
    }

    public static int getNavBarHeight() {
        if (sNavBarHeight == 0) {
            int deviceScreenHeight = getDeviceScreenHeight();
            int displayHeight = Devbox.getAppDelegate().getResources().getDisplayMetrics().heightPixels;
            sNavBarHeight = deviceScreenHeight - displayHeight;
            if (sNavBarHeight <= 0) {
                sNavBarHeight = dp2px(48);
            }
        }
        return sNavBarHeight;
    }

    public static int getWindowHeight() {
        return getDeviceScreenHeight() - getSystemBarHeight() - getNavBarHeight();
    }

    public static float getDensity() {
        if (sDensity == 0) {
            try {
                DisplayMetrics dm = Devbox.getAppDelegate().getResources().getDisplayMetrics();
                sDensity = dm.density;
                sScaledDensity = dm.scaledDensity;
            } catch (Exception e) {
                sDensity = sScaledDensity = 2f;
            }
        }
        return sDensity;
    }

    /**
     * set status bar icon to light theme, which is called dark mode.
     * should be called in onCreate()
     */
    public static void setStatusBarLightMode(Activity activity, boolean lightMode) {
        if (activity == null || activity.getWindow() == null) {
            return;
        }

        Window window = activity.getWindow();
        boolean changed = false;
        // try miui
        try {
            Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
            Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
            int darkIcon = field.getInt(layoutParams);
            Method extraFlagField = window.getClass().getMethod("setExtraFlags", int.class, int.class);
            extraFlagField.invoke(window, lightMode ? darkIcon : 0, darkIcon);
            changed = true;
        } catch (Exception ignored) {
        }

        // try flyme
        try {
            WindowManager.LayoutParams lp = window.getAttributes();
            Field darkIcon = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
            Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
            darkIcon.setAccessible(true);
            meizuFlags.setAccessible(true);
            int bit = darkIcon.getInt(null);
            int value = meizuFlags.getInt(lp);
            if (lightMode) {
                value |= bit;
            } else {
                value &= ~bit;
            }
            meizuFlags.setInt(lp, value);
            window.setAttributes(lp);
            changed = true;
        } catch (Exception ignored) {
        }

        if (!changed && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int visibility = window.getDecorView().getSystemUiVisibility();
            if (lightMode) {
                visibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                visibility &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
            window.getDecorView().setSystemUiVisibility(visibility);
        }
    }

    public static void closeKeyboard(Context context) {
        if (context != null) {
            View focus = ((Activity) context).getCurrentFocus();
            if (focus != null && focus instanceof EditText) {
                closeKeyboard((EditText) focus);
            }
        }
    }

    /**
     * @param editor one of EditText
     */
    public static void closeKeyboard(EditText editor) {
        ((InputMethodManager) editor.getContext().getSystemService(Context.INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(editor.getWindowToken(), 0);
    }

    public static void showKeyboard(EditText editor) {
        ((InputMethodManager) editor.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0,
                InputMethodManager.HIDE_NOT_ALWAYS);
        editor.requestFocus();
    }

    public static void addTextDelLine(TextView textView) {
        textView.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG);
    }

    public static void dismissDialog(Dialog dialog) {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    /**
     * Simple dialog builder with default buttons.
     */
    public static MaterialDialog.Builder getSimpleDialogBuilder(Context context, String text) {
        return new MaterialDialog.Builder(context).content(text).positiveText(android.R.string.ok)
                .negativeText(android.R.string.cancel);
    }

    public static MaterialDialog.Builder getSimpleDialogBuilder(Context context) {
        return new MaterialDialog.Builder(context).positiveText(android.R.string.ok)
                .negativeText(android.R.string.cancel);
    }

    public static MaterialDialog getLoadingDialog(Context context) {
        return getLoadingDialog(context, context.getString(R.string.msg_loading));
    }

    public static MaterialDialog getLoadingDialog(Context context, String loadingText) {
        return new MaterialDialog.Builder(context).progress(true, 0).content(loadingText).cancelable(false).build();
    }

    public static void showToast(@StringRes int resId, int duration) {
        Toast.makeText(Devbox.getAppDelegate(), resId, duration).show();
    }

    public static void showToast(String toastStr, int duration) {
        Toast.makeText(Devbox.getAppDelegate(), toastStr, duration).show();
    }

    public static void showToast(@StringRes int resId) {
        showToast(resId, Toast.LENGTH_SHORT);
    }

    public static void showToast(String toastStr) {
        showToast(toastStr, Toast.LENGTH_SHORT);
    }

    @ColorInt
    public static int getCompatColor(@ColorRes int color) {
        return ContextCompat.getColor(Devbox.getAppDelegate(), color);
    }

    public static Drawable getCompatDrawable(@DrawableRes int res) {
        return ContextCompat.getDrawable(Devbox.getAppDelegate(), res);
    }

    /**
     * transformer for Observables needs a loading dialog.
     * It's work in main thread, make sure it will be called after scheduler transformer
     */
    public static <T> Observable.Transformer<T, T> rxDialog(@NonNull final Context context) {
        return new Observable.Transformer<T, T>() {
            private MaterialDialog dialog = getLoadingDialog(context);

            @Override
            public Observable<T> call(Observable<T> observable) {
                return observable.doOnSubscribe(new Action0() {
                    @Override
                    public void call() {
                        dialog.show();
                    }
                }).doOnTerminate(new Action0() {
                    @Override
                    public void call() {
                        dismissDialog(dialog);
                        dialog = null;
                    }
                }).doOnUnsubscribe(new Action0() {
                    @Override
                    public void call() {
                        dismissDialog(dialog);
                        dialog = null;
                    }
                });
            }
        };
    }

    public static Bitmap toBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }

    // ############ Private #############

    private static int readInternalDimen(String key, Resources res, int fallback) {
        int resourceId = res.getIdentifier(key, "dimen", "android");
        return resourceId > 0 ? res.getDimensionPixelSize(resourceId) : fallback;
    }

    private static boolean readInternalBoolean(String key, Resources res, boolean fallback) {
        int resourceId = res.getIdentifier(key, "bool", "android");
        return resourceId != 0 ? res.getBoolean(resourceId) : fallback;
    }

    private static DisplayMetrics getDisplayMetrics() {
        Display display = ((WindowManager) Devbox.getAppDelegate().getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        DisplayMetrics metrics = new DisplayMetrics();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            ((WindowManager) Devbox.getAppDelegate().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
                    .getRealMetrics(metrics);
        } else {
            try {
                Method method = display.getClass().getMethod("getRealMetrics", DisplayMetrics.class);
                method.invoke(display, metrics);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return metrics;
    }
}