PopupWindow与状态栏之小米适配

it2025-11-09  10

目录

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

我手中的红米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 内容的,可能就不行了

期待大佬来补充!

最新回复(0)