PopupWindow与状态栏之小米适配

目录

在Android手机中页面对状态栏做了侵入式展示,但是弹窗的时候,PopupWindow并没有进入状态栏,导致状态栏别具一格的颜色。

解决方法一、适用于大多数手机,但是小米新机型例外

解决方法二:把状态栏颜色改成与Toolbar颜色一致(假全屏)

解决方法三:以上代码只是假性实现了全屏,但是针对那些侧拉,下拉的,或者状态栏中需要显示popupwindow 内容的,可能就不行了

期待大佬来补充第三条!


 

在Android手机中页面对状态栏做了侵入式展示,但是弹窗的时候,PopupWindow并没有进入状态栏,导致状态栏别具一格的颜色。

 

 

解决方法一、适用于大多数手机,但是小米新机型例外

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 
    popupWindow.setIsLaidOutInScreen(true);
 } else {
    fitPopupWindowOverStatusBar(popupWindow, true);
 }
    public static void fitPopupWindowOverStatusBar(PopupWindow mPopupWindow, boolean needFullScreen) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            try {
                Field mLayoutInScreen = PopupWindow.class.getDeclaredField("mLayoutInScreen");
                mLayoutInScreen.setAccessible(needFullScreen);
                mLayoutInScreen.set(mPopupWindow, needFullScreen);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                Log.i("DeviceInfoPopupwindow", "" + e.toString());
                e.printStackTrace();
            }

        }
    }

我手中用的红米Note7,状态栏用了N种方法都没法被遮住,很显眼的一条高亮的色泽。

解决方法二:把状态栏颜色改成与Toolbar颜色一致

因为我的Popupwindow 从底部弹出,上半部分是半透明的样式,所以我针对小米手机设置了一下状态栏色颜色,为那个被阴影遮挡之后的颜色,以下为效果

popupwindow 适配小米

我手中的红米NOTE 7跟其他小米手机还不太一样,他有一条黑线,是因为popupwindow高度进入了状态栏四个像素(可能属于MIUI  的BUG)

针对这个机型可以专门设置一下高度 在popupwindow布局文件中距离顶部距离2dp就好了

 View view = View.inflate(activity, R.layout.my_dialog_run_mode2, null);

             PopupWindow   popupWindow = new PopupWindow(view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, false);
                popupWindow.setTouchable(true);
                popupWindow.setBackgroundDrawable(new BitmapDrawable(activity.getResources(), (Bitmap) null));
                popupWindow.setAnimationStyle(R.style.popupAnimation);
                popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
                    @Override
                    public void onDismiss() {
                        try {
                            if (Rom.isMiui()) {
                                if (activity instanceof BaseActivity) {
                                    WindowsUtil.setStatusBarColor(activity, ((BaseActivity) activity).lastStatusBarTintColor);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
                if (Rom.isMiui()) {
                    WindowsUtil.setStatusBarColor(activity, R.color.alph_status);
                } else {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        popupWindow.setIsLaidOutInScreen(true);
                    } else {
                        fitPopupWindowOverStatusBar(popupWindow, true);
                    }
                }  
                popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);

--------下面是判断机型的代码



import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author: jjf
 * @date: 2019/8/28
 * @describe:
 */
public class Rom {

    private static final String TAG = "Rom";

    public static final String ROM_MIUI = "MIUI";
    public static final String ROM_EMUI = "EMUI";
    public static final String ROM_FLYME = "FLYME";//魅族
    public static final String ROM_OPPO = "OPPO";
    public static final String ROM_SMARTISAN = "SMARTISAN";
    public static final String ROM_VIVO = "VIVO";
    public static final String ROM_QIKU = "QIKU";
    public static final String ROM_NOKIA = "Nokia";//诺基亚
     public static final String ROM_SAMSUNG = "samsung";//诺基亚

    private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
    private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
    private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
    private static final String KEY_VERSION_EMUI = "ro.build.version.emui";
    private static final String KEY_VERSION_OPPO = "ro.build.version.opporom";
    private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version";
    private static final String KEY_VERSION_VIVO = "ro.vivo.os.version";

    private static String sName;
    private static String sVersion;

    /**
     * 华为
     * @return
     */
    public static boolean isEmui() {
        return check(ROM_EMUI);
    }

    /**
     * 小米
     * @return
     */
    public static boolean isMiui() {
        return check(ROM_MIUI);
    }

    public static boolean isVivo() {
        return check(ROM_VIVO);
    }

    public static boolean isOppo() {
        return check(ROM_OPPO);
    }

    public static boolean isFlyme() {
        return check(ROM_FLYME);
    }
    public static boolean isNokia() {
        return check(ROM_NOKIA);
    }

    public static boolean is360() {
        return check(ROM_QIKU) || check("360");
    }

    public static boolean isSmartisan() {
        return check(ROM_SMARTISAN);
    }

    public static String getName() {
        if (sName == null) {
            check("");
        }
        return sName;
    }

    public static String getVersion() {
        if (sVersion == null) {
            check("");
        }
        return sVersion;
    }

    public static boolean check(String rom) {
        if (sName != null) {
            return sName.equalsIgnoreCase(rom);
        }

        if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
            sName = ROM_MIUI;
        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) {
            sName = ROM_EMUI;
        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) {
            sName = ROM_OPPO;
        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) {
            sName = ROM_VIVO;
        } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) {
            sName = ROM_SMARTISAN;
        } else {
            sVersion = Build.DISPLAY;
            if (sVersion.toUpperCase().contains(ROM_FLYME)) {
                sName = ROM_FLYME;
            } else {
                sVersion = Build.UNKNOWN;
                sName = Build.MANUFACTURER.toUpperCase();
            }
        }
        return sName.equals(rom);
    }

    public static String getProp(String name) {
        String line = null;
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("getprop " + name);
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            line = input.readLine();
            input.close();
        } catch (IOException ex) {
            Log.e(TAG, "Unable to read prop " + name, ex);
            return null;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return line;
    }
}

------下面是Window工具类

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.DisplayCutout;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
 
import com.readystatesoftware.systembartint.SystemBarTintManager;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.List;
import java.util.logging.Logger;

import anet.channel.util.Utils;


/**
 * @author: jjf
 * @date: 2018/7/25
 * @describe:UI工具类
 */
public class WindowsUtil {

    /**
     * 获取屏幕宽度
     */
    public static int WindowsWidth(Activity context) {
        WindowManager manager = context.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);

        DisplayMetrics m = MainApplication.getAppContext().getResources().getDisplayMetrics();
        return m.widthPixels;

    }

    /**
     * 获取屏幕宽度
     */
    public static int WindowsWidth_dp(Activity context) {
        WindowManager manager = context.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);
        int screenWidth = (int) (outMetrics.widthPixels / outMetrics.density + 0.5f);  // 屏幕宽度(dp)
        return screenWidth;
    }

    public void getAndroiodScreenProperty(Activity context) {
        WindowManager wm = (WindowManager) context.getWindowManager();
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        int width = dm.widthPixels;         // 屏幕宽度(像素)
        int height = dm.heightPixels;       // 屏幕高度(像素)
        float density = dm.density;         // 屏幕密度(0.75 / 1.0 / 1.5)
        int densityDpi = dm.densityDpi;     // 屏幕密度dpi(120 / 160 / 240)
        // 屏幕宽度算法:屏幕宽度(像素)/屏幕密度
        int screenWidth = (int) (width / density);  // 屏幕宽度(dp)
        int screenHeight = (int) (height / density);// 屏幕高度(dp)


    }


    /**
     * 获取屏幕高度
     */
    public static int WindowsHeight(Activity context) {
        WindowManager manager = context.getWindowManager();

        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);

        return outMetrics.heightPixels;
    }

    //单位dp值转化为单位px值
    public static int dp2px(int dpVal) {
        return (int) dp2px((float) dpVal);
    }

    //单位dp值转化为单位px值
    public static float dp2px(float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, MainApplication.getAppContext().getResources().getDisplayMetrics());
    }

    public static float dp2px(Activity activity, float dpVal) {
        WindowManager manager = activity.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);
        float px1 = (dpVal * outMetrics.scaledDensity + 0.5f);
        float px2 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, MainApplication.getAppContext().getResources().getDisplayMetrics());
        float px3 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, activity.getResources().getDisplayMetrics());
        LogUtil.I(TAG, "px1= " + px1 + "  px2= " + px2 + "  px3= " + px3);
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, MainApplication.getAppContext().getResources().getDisplayMetrics());
    }

    public static int px2dip(Activity context, float pxValue) {
        WindowManager manager = context.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);
        final float scale1 = outMetrics.density;//

        final float scale3 = MainApplication.getAppContext().getResources().getDisplayMetrics().density;
        int dp1 = (int) (pxValue / scale1 + 0.5f);

        int dp3 = (int) (pxValue / scale3 + 0.5f);
        LogUtil.I(TAG, "dp1" + dp1 + " dp3" + dp3);
//        getNotchParams(context);
        return dp1;
//        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
//                dpVal, ScreenAdapter.lastMetrics); pxValue
    }


    /**
     * 将px值转换为sp值,保证文字大小不变
     *
     * @param pxValue
     * @return
     */
    public static int px2sp(Activity activity, float pxValue) {
        WindowManager manager = activity.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);
        final float fontScale = outMetrics.scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }

    /**
     * 将sp值转换为px值,保证文字大小不变
     *
     * @param spValue
     * @return
     */
    public static int sp2px(Activity activity, float spValue) {
        WindowManager manager = activity.getWindowManager();
        DisplayMetrics outMetrics = new DisplayMetrics();
        manager.getDefaultDisplay().getMetrics(outMetrics);

        final float fontScale = outMetrics.scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    /**
     * 根据传入控件的坐标和用户的焦点坐标,判断是否隐藏键盘,如果点击的位置在控件内,则不隐藏键盘
     *
     * @param view  控件view
     * @param event 焦点位置
     * @return 是否隐藏
     */
    public static void hideKeyboard(MotionEvent event, View view,
                                    Activity activity) {
        WeakReference<Activity> weakReference = new WeakReference<Activity>(activity);
        try {
            if (view != null && view instanceof EditText) {
                int[] location = {0, 0};
                view.getLocationInWindow(location);
                int left = location[0], top = location[1], right = left
                        + view.getWidth(), bootom = top + view.getHeight();
                // 判断焦点位置坐标是否在空间内,如果位置在控件外,则隐藏键盘
                if (event.getRawX() < left || event.getRawX() > right
                        || event.getY() < top || event.getRawY() > bootom) {
                    // 隐藏键盘
                    IBinder token = view.getWindowToken();
                    if (weakReference.get() != null) {
                        InputMethodManager inputMethodManager = (InputMethodManager) weakReference.get()
                                .getSystemService(Context.INPUT_METHOD_SERVICE);
                        inputMethodManager.hideSoftInputFromWindow(token,
                                InputMethodManager.HIDE_NOT_ALWAYS);
                    }
                }
            }
        } catch (Exception e) {
            LogUtil.I(TAG, "hideKeyboard() e=" + e.toString());
        }
    }

    private static String TAG = "WindowUtil";


    public static void getNotchParams(Activity activity) {
        final View decorView = activity.getWindow().getDecorView();

        decorView.post(new Runnable() {
            //            @RequiresApi(api = Build.VERSION_CODES.P)
            @Override
            public void run() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    WindowInsets rootWindowInsets = decorView.getRootWindowInsets();
                    if (rootWindowInsets == null) {
                        LogUtil.I("TAG", "rootWindowInsets为空了");
                        return;
                    }
                    DisplayCutout displayCutout = rootWindowInsets.getDisplayCutout();
                    if (displayCutout == null) {
                        LogUtil.I("TAG", "displayCutout为空了");
                        return;
                    }
                    LogUtil.I("TAG", "安全区域距离屏幕左边的距离 SafeInsetLeft:" + displayCutout.getSafeInsetLeft());

                    LogUtil.I("TAG", "安全区域距离屏幕右部的距离 SafeInsetRight:" + displayCutout.getSafeInsetRight());
                    LogUtil.I("TAG", "安全区域距离屏幕顶部的距离 SafeInsetTop:" + displayCutout.getSafeInsetTop());
                    LogUtil.I("TAG", "安全区域距离屏幕底部的距离 SafeInsetBottom:" + displayCutout.getSafeInsetBottom());

                    List<Rect> rects = displayCutout.getBoundingRects();
                    if (rects.size() == 0) {
                        LogUtil.I("TAG", "不是刘海屏");
                    } else {
                        LogUtil.I("TAG", "刘海屏数量:" + rects.size());
                        for (Rect rect : rects) {
                            LogUtil.I("TAG", "刘海屏区域:" + rect);
                        }
                    }
                }
            }
        });
    }

    /**
     * 获取状态栏高度
     *
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        try {
            Resources resources = context.getResources();
            int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
            int height = resources.getDimensionPixelSize(resourceId);
            return height;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 设置状态栏颜色
     *
     * @param activity
     * @param color
     */
    public static void setStatusBarColor(Activity activity, int color) {
        try {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            SystemBarTintManager tintManager = new SystemBarTintManager(activity);
            tintManager.setStatusBarTintColor(activity.getResources().getColor(color));//R.color.app_main_color
            tintManager.setStatusBarTintEnabled(true);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 更改状态栏 文本 颜色
     *
     * @param activity
     * @param dark
     */
    public static void setStatusBarTextColor(Activity activity, boolean dark) {
        View decor = activity.getWindow().getDecorView();
        if (dark) {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        } else {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        }
    }

    /**
     * @param activity
     * @param color
     */
    public static void setNavigationBarColor(Activity activity, int color) {
        try {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            SystemBarTintManager tintManager = new SystemBarTintManager(activity);
            if (ScreenUtils.getBottomStatusHeight(activity.getApplicationContext()) > 0) {
                tintManager.setNavigationBarTintColor(activity.getResources().getColor(color));
                tintManager.setNavigationBarTintEnabled(true);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 是否隐藏了导航键
     *
     * @param context
     * @return
     */
    public static boolean isNavBarHide(Context context) {
        try {
            String brand = Build.BRAND;
            // 这里做判断主要是不同的厂商注册的表不一样
            if (!StringUtils.isNullData(brand) && (Rom.isVivo() || Rom.isOppo())) {
                return Settings.Secure.getInt(context.getContentResolver(), getDeviceForceName(), 0) != 0;
            } else if (!StringUtils.isNullData(brand) && Rom.isNokia()) {
                //甚至 nokia 不同版本注册的表不一样, key 还不一样。。。
                return Settings.Secure.getInt(context.getContentResolver(), "swipe_up_to_switch_apps_enabled", 0) == 1
                        || Settings.System.getInt(context.getContentResolver(), "navigation_bar_can_hiden", 0) != 0;
            } else
                return Settings.Global.getInt(context.getContentResolver(), getDeviceForceName(), 0) != 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 各个手机厂商注册导航键相关的 key
     *
     * @return
     */
    public static String getDeviceForceName() {
        String brand = Build.BRAND;
        if (StringUtils.isNullData(brand))
            return "navigationbar_is_min";
        if (brand.equalsIgnoreCase("HUAWEI") || "HONOR".equals(brand)) {
            return "navigationbar_is_min";
        } else if (Rom.isMiui()||Rom.check("XIAOMI")) {
            return "force_fsg_nav_bar";
        } else if (Rom.isVivo()) {
            return "navigation_gesture_on";
        } else if (Rom.isOppo()) {
            return "hide_navigationbar_enable";
        } else if (Rom.check("samsung")) {
            return "navigationbar_hide_bar_enabled";
        } else if (brand.equalsIgnoreCase("Nokia")) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
                return "navigation_bar_can_hiden";
            } else {
                return "swipe_up_to_switch_apps_enabled";
            }
        } else {
            return "navigationbar_is_min";
        }
    }



}

解决方法三、以上代码只是假性实现了全屏,但是针对那些侧拉,下拉的,或者状态栏中需要显示popupwindow 内容的,可能就不行了

期待大佬来补充!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值