androidx 中的 enableEdgeToEdge()

770 阅读2分钟

2024.12 Android 新项目中 多了些新代码

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    enableEdgeToEdge() //官方默认加入沉侵式状态栏适配,
    setContentView(binding.root)
    ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
        val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(0, systemBars.top, 0, 0)
        insets
    }//不修改状态栏下 跟布局需要 Padding下状态栏高度 应该写在具体实现UI Fragment中
}

enableEdgeToEdge() 中的实现 就是个版本实现状态栏相关的适配

fun ComponentActivity.enableEdgeToEdge(
    statusBarStyle: SystemBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT),
    navigationBarStyle: SystemBarStyle = SystemBarStyle.auto(DefaultLightScrim, DefaultDarkScrim)
) {
    val view = window.decorView
    val statusBarIsDark = statusBarStyle.detectDarkMode(view.resources)
    val navigationBarIsDark = navigationBarStyle.detectDarkMode(view.resources)
    val impl = Impl ?: if (Build.VERSION.SDK_INT >= 29) {
        EdgeToEdgeApi29()
    } else if (Build.VERSION.SDK_INT >= 26) {
        EdgeToEdgeApi26()
    } else if (Build.VERSION.SDK_INT >= 23) {
        EdgeToEdgeApi23()
    } else if (Build.VERSION.SDK_INT >= 21) {
        EdgeToEdgeApi21()
    } else {
        EdgeToEdgeBase()
    }.also { Impl = it }
    impl.setUp(
        statusBarStyle, navigationBarStyle, window, view, statusBarIsDark, navigationBarIsDark
    )
}

之前我们实现沉侵式状态栏 StatusBarTool

/**
 * 修改状态栏颜色,支持4.4以上版本
 * @param colorId 颜色
 */
public static void setStatusBarColor(Activity activity, int colorId) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = activity.getWindow();
        window.setStatusBarColor(colorId);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        //使用SystemBarTintManager,需要先将状态栏设置为透明
        setTranslucentStatus(activity);
        SystemBarTintManager systemBarTintManager = new SystemBarTintManager(activity);
        systemBarTintManager.setStatusBarTintEnabled(true);//显示状态栏
        systemBarTintManager.setStatusBarTintColor(colorId);//设置状态栏颜色
    }
}

/**
 * 设置状态栏透明
 */
@TargetApi(19)
public static void setTranslucentStatus(Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        //5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
        Window window = activity.getWindow();
        View decorView = window.getDecorView();
        //两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
        //导航栏颜色也可以正常设置
        //window.setNavigationBarColor(Color.TRANSPARENT);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Window window = activity.getWindow();
        WindowManager.LayoutParams attributes = window.getAttributes();
        int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        attributes.flags |= flagTranslucentStatus;
        //int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; //attributes.flags |= flagTranslucentNavigation;
        window.setAttributes(attributes);
    }
}

/**
 * 代码实现android:fitsSystemWindows
 *
 * @param activity
 */
@SuppressLint("ObsoleteSdkInt")
public static void setRootViewFitsSystemWindows(Activity activity, boolean fitSystemWindows) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        ViewGroup winContent = (ViewGroup) activity.findViewById(android.R.id.content);
        if (winContent.getChildCount() > 0) {
            ViewGroup rootView = (ViewGroup) winContent.getChildAt(0);
            if (rootView != null) {
                rootView.setFitsSystemWindows(fitSystemWindows);
            }
        }
    }
}

/**
 * 设置状态栏深色浅色切换
 */
public static boolean setStatusBarDarkTheme(Activity activity, boolean dark) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            setStatusBarFontIconDark(activity, TYPE_M, dark);
        } else if (OSUtils.isMiui()) {
            setStatusBarFontIconDark(activity, TYPE_MIUI, dark);
        } else if (OSUtils.isFlyme()) {
            setStatusBarFontIconDark(activity, TYPE_FLYME, dark);
        } else {//其他情况
            return false;
        }
        return true;
    }
    return false;
}

/**
 * 设置 状态栏深色浅色切换
 */
public static boolean setStatusBarFontIconDark(Activity activity, @ViewType int type, boolean dark) {
    switch (type) {
        case TYPE_MIUI:
            return setMiuiUI(activity, dark);
        case TYPE_FLYME:
            return setFlymeUI(activity, dark);
        case TYPE_M:
        default:
            return setCommonUI(activity, dark);
    }
}

//设置6.0 状态栏深色浅色切换
public static boolean setCommonUI(Activity activity, boolean dark) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        View decorView = activity.getWindow().getDecorView();
        if (decorView != null) {
            int vis = decorView.getSystemUiVisibility();
            if (dark) {
                vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
            if (decorView.getSystemUiVisibility() != vis) {
                decorView.setSystemUiVisibility(vis);
            }
            return true;
        }
    }
    return false;
}

//设置Flyme 状态栏深色浅色切换
public static boolean setFlymeUI(Activity activity, boolean dark) {
    try {
        Window window = activity.getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();
        Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
        Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
        darkFlag.setAccessible(true);
        meizuFlags.setAccessible(true);
        int bit = darkFlag.getInt(null);
        int value = meizuFlags.getInt(lp);
        if (dark) {
            value |= bit;
        } else {
            value &= ~bit;
        }
        meizuFlags.setInt(lp, value);
        window.setAttributes(lp);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

//设置MIUI 状态栏深色浅色切换
public static boolean setMiuiUI(Activity activity, boolean dark) {
    try {
        Window window = activity.getWindow();
        Class<?> clazz = activity.getWindow().getClass();
        @SuppressLint("PrivateApi") Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
        Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
        int darkModeFlag = field.getInt(layoutParams);
        Method extraFlagField = clazz.getDeclaredMethod("setExtraFlags", int.class, int.class);
        extraFlagField.setAccessible(true);
        if (dark) {    //状态栏亮色且黑色字体.
            extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
        } else {
            extraFlagField.invoke(window, 0, darkModeFlag);
        }
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
    val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
    v.setPadding(0, systemBars.top, 0, 0)
    insets
}

v.setPadding(0, systemBars.top, 0, 0)等效于

binding.getRoot().setPadding(0, StatusBarTool.getStatusBarHeight(requireActivity()), 0, 0);