Android P版本 (六)刘海屏适配 与WindowInsets,DisplayCutout使用

深度解析Android Q cutout刘海屏 1.在 Settings/System/Developer options/DRAWING 里面看到有 “Display cutout” 菜单 2.根据这个字符串找到 packages/apps/Settings/res/values/strings.xml <string name="display_cutout_emulation">Display cutout</string> 3.然后根据 display_cutout_emulation 字符串找到在 packages/a 阅读详情

Android P版本的发布,引入了刘海屏的概念,像华为nova 3e,vivo X21等手机厂商也纷纷推出自己的刘海屏手机,我们先预览下HUAWEI nova 3e的机照
这里写图片描述

从这张图中我们可以看出,所谓的刘海屏实际上是安装在状态栏的一块玻璃屏幕,刘海屏的高度等于状态栏的高度

如果我们的的app没有适配android p的刘海屏,那么在显示的时候变会出现问题,
1)如没有状态栏,全屏显示的App,那么在Android P版本中显示如下
这里写图片描述
2)如果有状态栏,全屏显示的App,那么在Android P版本中显示如下,你会发现UI出现了黑边,页码也看不清了
这里写图片描述

以上都是基于标准的刘海屏设计出现的情况,还有一些厂商自定义了刘海屏,即刘海屏的高度大于了状态栏,那么就会产生类似的问题,如下
1)状态栏背景高度写死的问题
这里写图片描述

因此如果你想让你的App在Android P版本中完美运行,你应该知道怎么去适配他


默认的Android P的模拟器是关闭刘海屏的,首先看下如何开启Android P的模拟器中的刘海屏,

1)启用开发者选项和调试
-> 打开 Settings 应用。
-> 选择 System。
-> 滚动到底部,然后选择 About phone。
-> 滚动到底部,点按 Build number 7 次。
-> 返回上一屏幕,在底部附近可找到 Developer options

2)在 Developer options 屏幕中,向下滚动至 Drawing 部分并选择 Simulate a display with a cutout

3)选择屏幕缺口的大小

如图所示,Google提供了四种刘海屏选择方案
这里写图片描述
对应上面4中选择
第一种,很显然没有刘海屏
第二种到第四种,只不过是刘海屏宽度不一样罢了,我这里选择的是Tall display cutout模式,如下图所示
这里写图片描述

这里需要注意一个问题:使用Android P模拟器的时候,这里的模拟凹口屏的四个选项其实实质只改变了刘海屏的位置和宽度,高度(系统刘海屏不会超过状态栏),但是在真机中,这四个选项有可能对应不同的操作,请参阅如下链接
四种刘海屏的真机样式


既然看到了google搞的刘海屏,那google针对刘海屏有什么自适配策略?,google总不能说一个老的app上来就直接在刘海屏上显示错乱吧?
先上一段代码

public class AndroidPDemoActivity extends Activity{

    private TextView mTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_android_p_demo_layout);
        mTv = (TextView)this.findViewById(R.id.android_p_demo_tv);
    }
}

这段代码很简单,就是给Activity设置为无title,全屏显示,这段代码在无刘海屏显示效果如下
这里写图片描述

但是如果切换到刘海屏,则显示就出现了异常,如下图
这里写图片描述
可以发现原先正常的App出现了黑边

所以Google默认的适配刘海屏策略是这样的
1) 如果应用未适配刘海屏,需要系统对全屏显示的应用界面做特殊移动处理(竖屏下移处理,横屏右移处),因此此处出现了黑边的现象;如果应用页面布局不能做到自适应,就会出现布局问题;如果应用布局能够做到自适应,也会有黑边无法全屏显示的体验问题
2)如果有状态栏的App,则不受刘海屏的影响(有状态肯定不是全屏,那么就不会有下移的风险)


知晓了google是如何适配刘海屏的策略,那么我们看下在Android P版本中,如何去适配这个刘海屏;

在Android P版本中,通过DisplayCutout 类,可以确定非功能区域(刘海屏)的位置和形状

第一种方案:使用layoutInDisplayCutoutMode来进行适配,他的作用是在有刘海屏的时候,如何布局窗口,默认为LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT,他有以下几种模式

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默认情况下,全屏窗口不会使用到刘海区域,非全屏窗口可正常使用刘海区域
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:窗口不允许和刘海屏重叠
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:the window is always allowed to extend into the DisplayCutout areas on the short edges of the screen

我们通过代码看下效果:LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT

public class AndroidPDemoActivity extends Activity{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        WindowManager.LayoutParams lp = this.getWindow().getAttributes();
        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
        this.getWindow().setAttributes(lp);
        setContentView(R.layout.activity_android_p_demo_layout);
    }
}

这里写图片描述
从图中可以看出,这个并不是完美的适配方案

在来看第二种样式:LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

public class AndroidPDemoActivity extends Activity{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        WindowManager.LayoutParams lp = this.getWindow().getAttributes();
        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
        this.getWindow().setAttributes(lp);
        setContentView(R.layout.activity_android_p_demo_layout);
    }
}

这里写图片描述
可以看出显示效果和DEFAULT是一致的,LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER是不允许使用刘海屏区域,而LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT全屏窗口不允许使用刘海屏区域

在来看LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

public class AndroidPDemoActivity extends Activity{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        WindowManager.LayoutParams lp = this.getWindow().getAttributes();
        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        this.getWindow().setAttributes(lp);
        setContentView(R.layout.activity_android_p_demo_layout);
    }
}

这里写图片描述
可以看出LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES已经允许全屏app使用刘海屏了,只不过状态栏那边是白色。


那我们要如何修复这个问题?采用沉浸式布局即可,即设置DecorView为SYSTEM_UI_FLAG_FULLSCREEN模式。

那何为沉浸式布局?这是Android 4.4 (API Level 19)引入一个新的概念,即真正的全屏模式:SystemUI(StatusBar和NavigationBar)也都被隐藏

直接上代码

//主activity类
package com.hwj.android.learning;

import android.app.Activity;
import android.os.Bundle;

public class AndroidPDemoActivity extends Activity{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DisplayCutoutDemo displayCutoutDemo = new DisplayCutoutDemo(this);
        displayCutoutDemo.openFullScreenModel();
        setContentView(R.layout.activity_android_p_demo_layout);
    }
}
package com.hwj.android.learning;

import android.app.Activity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

/**
 * 功能描述: 刘海屏控制
 */
public class DisplayCutoutDemo {

    private Activity mAc;

    public DisplayCutoutDemo(Activity ac) {
        mAc = ac;
    }


    //在使用LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES的时候,状态栏会显示为白色,这和主内容区域颜色冲突,
    //所以我们要开启沉浸式布局模式,即真正的全屏模式,以实现状态和主体内容背景一致
    public void openFullScreenModel(){
        mAc.requestWindowFeature(Window.FEATURE_NO_TITLE);
        WindowManager.LayoutParams lp = mAc.getWindow().getAttributes();
        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        mAc.getWindow().setAttributes(lp);
        View decorView = mAc.getWindow().getDecorView();
        int systemUiVisibility = decorView.getSystemUiVisibility();
        int flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN;
        systemUiVisibility |= flags;
        mAc.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibility);
    }

}

显示效果如下
这里写图片描述

可以看出我们已经可以较完美的适配刘海屏了


那我们布局的时候,你总不能在刘海屏区域内部放控件吧,所以这个时候我们就要计算状态栏高度了,在布局时候,要刻意避开这个区域

    //获取状态栏高度
    public int getStatusBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height","dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        Log.d("hwj","**getStatusBarHeight**" + result);
        return result;
    }

通过上述代码,我们就可以计算出状态栏高度,在我的模拟器中,这个高度是126,单位PX
因此为了更完美的布局我们的App,则布局文件应该做如下调整

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/holo_blue_bright"
    tools:context="com.hwj.android.learning.AndroidPDemoActivity">

    <!--这里layout_marginTop="126px"是因为我提前用DisplayCutoutDemo.java中的getStatusBarHeight方法
    提前获得状态栏高度为126,单位为PX
    因此在设置的时候,直接设置距离上面126px了
    这样就能完美的避开刘海屏区域-->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="126px"/>

    <TextView
        android:id="@+id/android_p_demo_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>

</LinearLayout>

效果显示如下
这里写图片描述

现在是不是UI已经有了更多的优化了?呵呵


那有的人非要在刘海屏那块填充控件咋整?

那我们就得借助DisplayCutout类了,其基本思路如下
1):通过DisplayCutout类提供的API去获取刘海屏的坐标位置
2):在布局的时候,因为已知刘海屏的坐标,因此控件可以很方便的避开这个位置

直接上代码

//主activity
package com.hwj.android.learning;

import android.app.Activity;
import android.os.Bundle;

public class AndroidPDemoActivity extends Activity{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DisplayCutoutDemo displayCutoutDemo = new DisplayCutoutDemo(this);
        displayCutoutDemo.openFullScreenModel();
        setContentView(R.layout.activity_android_p_demo_layout);
        displayCutoutDemo.controlView();
    }
}
package com.hwj.android.learning;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.DisplayCutout;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;

/**
 * 功能描述: 刘海屏控制
 */
public class DisplayCutoutDemo {

    private Activity mAc;

    public DisplayCutoutDemo(Activity ac) {
        mAc = ac;
    }


    //在使用LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES的时候,状态栏会显示为白色,这和主内容区域颜色冲突,
    //所以我们要开启沉浸式布局模式,即真正的全屏模式,以实现状态和主体内容背景一致
    public void openFullScreenModel(){
        mAc.requestWindowFeature(Window.FEATURE_NO_TITLE);
        WindowManager.LayoutParams lp = mAc.getWindow().getAttributes();
        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        mAc.getWindow().setAttributes(lp);
        View decorView = mAc.getWindow().getDecorView();
        int systemUiVisibility = decorView.getSystemUiVisibility();
        int flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN;
        systemUiVisibility |= flags;
        mAc.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibility);
    }

    //获取状态栏高度
    public int getStatusBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height","dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        Log.d("hwj","**getStatusBarHeight**" + result);
        return result;
    }

    public void controlView(){
        View decorView = mAc.getWindow().getDecorView();
        if(decorView != null){
            Log.d("hwj", "**controlView**" + android.os.Build.VERSION.SDK_INT);
            Log.d("hwj", "**controlView**" + android.os.Build.VERSION_CODES.P);
            WindowInsets windowInsets = decorView.getRootWindowInsets();
            if(windowInsets != null){
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                    DisplayCutout displayCutout = windowInsets.getDisplayCutout();
                    //getBoundingRects返回List<Rect>,没一个list表示一个不可显示的区域,即刘海屏,可以遍历这个list中的Rect,
                    //即可以获得每一个刘海屏的坐标位置,当然你也可以用类似getSafeInsetBottom的api
                    Log.d("hwj", "**controlView**" + displayCutout.getBoundingRects());
                    Log.d("hwj", "**controlView**" + displayCutout.getSafeInsetBottom());
                    Log.d("hwj", "**controlView**" + displayCutout.getSafeInsetLeft());
                    Log.d("hwj", "**controlView**" + displayCutout.getSafeInsetRight());
                    Log.d("hwj", "**controlView**" + displayCutout.getSafeInsetTop());
                }
            }
        }
    }
}
<!--布局文件-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/holo_blue_bright"
    tools:context="com.hwj.android.learning.AndroidPDemoActivity">

    <!--假设我们已经通过DisplayCutoutDemo.java的controlView方法提前
     获得了刘海屏的坐标,则这里坐边距就可以设置了-->
    <!--在你实际使用android p模拟器的时候,你会发现android.os.Build.VERSION_CODES.P的值居然等于10000
     顾你是无法通过模拟器去实际使用DisplayCutoutDemo类的-->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="800px"/>

    <TextView
        android:id="@+id/android_p_demo_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>

</LinearLayout>

显示效果如下
这里写图片描述

以上全部的demo和代码的build.gradle如下

apply plugin: 'com.android.application'

android {
    compileSdkVersion 'android-P'



    defaultConfig {
        applicationId "com.hwj.android.learning"
        minSdkVersion 27
        versionCode 1
        versionName "1.0"
        targetSdkVersion 'P'
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
repositories {
    mavenCentral()
}

其实只要注意如下两个属性就好,只有如下设置,才能正确使用Android P版本,其他的build.gradle的配置可以视自己的as版本自定义即可

compileSdkVersion ‘android-P’
targetSdkVersion ‘P’

这里有一个需要关注的问题,在使用Android P模拟器的时,android.os.Build.VERSION_CODES.P的值居然等于10000,这说明在实际使用过程中你是无法通过模拟器去实际使用DisplayCutoutDemo类的,也就是无法去获取刘海屏的具体坐标

究其原因,我猜测是Android P版本还未正式发布,这只是一个debug版本,待正式发布,这个bug应该就会修复掉了。
但是只要我们掌握了适配原理,那就不用担心了

但是我们应该遵循的一个原则就是:不要在刘海屏那一栏显示内容,那一块我们称为非安全区域,尽量在安全区域去绘制UI

综述刘海屏的适配:
1)设置LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES模式
2)设置沉浸式布局模式
3)计算状态栏高度,进行布局;如果有特殊UI要求,则可以使用DisplayCutoutDemo类去获取刘海屏的坐标,完成UI

下面的链接是华为和VIVO的自己的适配刘海屏方案
华为适配刘海屏
VIVO适配刘海屏

虽然各大厂商均有自己额适配方案和API,但是只要你遵循Google的适配刘海屏方案,即我博文上述的方法,各厂商的手机显示也是不会有问题的,如华为P版本会同时兼容谷歌和华为的方案,在android p版本发布之前,我们还是得遵循华为或者VIVO的适配方案去适配刘海屏;

SystemUi状态栏客制化功能和常见问题分析 一.多图标成点 当系统图标区域或者通知图标区域图标过多,而区域不够时,就会将多余的图标隐藏,并显示一个点,如下图所示。 介绍此功能之前先看一下图标的初始化过程,从中可以看到有个config_statusBarIcons参数,这个参数定义了所有的系统图标由低到高显示优先级顺序。 点图标是通过设置图标的状态为STATE_DOT来实现的,在状态更新后会 applyToView,然后在图标类中setVisibleState来刷新图标,大致流程如下图所示。 二.图标反色 我们可以看到当状态栏背. 阅读详情

相关推荐

Android 9.0+异形屏适配避坑指南:从LAYOUT_IN_DISPLAY_CUTOUT_MODE到安全区域处理

本文深入解析了Android 9.0及以上版本中异形屏适配的官方方案。详细探讨了从LAYOUT_IN_DISPLAY_CUTOUT_MODE三种模式的选择策略,到如何通过WindowInsets和DisplayCutout API动态计算与处理安全区域,确保应用内容不被刘海、水滴屏等异形区域遮挡,并提供横竖屏切换、兼容性处理及实战代码示例。

p8q9r0的博客 287

Android P (9.0)刘海屏(DisplayCutout)适配方法

简介 Android P版本提供了统一的刘海屏方案和三方适配刘海屏方案: 对于有状态栏的页面,不会受到刘海屏特性的影响 全屏显示的页面,系统刘海屏方案会对应用界面做下移处理,避开刘海区显示 已经适配Android P应用的全屏页面可以通过谷歌提供的适配方案使用刘海区,真正做到全屏显示。 Android P 为最新的刘海屏,提供了专门的Api来支持:DisplayCu...

限量发行的专栏 7286

Android适配刘海屏(华为Pro20等)

前言 公司最近要适配华为Pro20,没办法 – 。– 一、AndroidP的适配方案 上来我最先找到的就是AndroidP,就先以这个入手了。 首先看下谷歌给出的api,大致就分为两种。 1.设置全屏模式 WindowManager.LayoutParams lp =getWindow().getAttributes(); lp.layoutIn...

li15225271052的博客 1万+

支持刘海屏

支持刘海屏 带刘海屏的设备 刘海屏是指某些设备显示屏上的一个区域延伸到显示面,这样既能为用户提供全面屏体验,又能为设备正面的重要传感器留出空间。Android 在搭载 Android 9(API 级别 28)及更高版本的设备上正式支持刘海屏。请注意,设备制造商也可以选择在搭载 Android 8.1 或更低版本的设备上支持刘海屏。 本主题介绍如何实现对带刘海屏的设备的支持,包括如何处理“刘海区域”,即显示面上包含刘海的无边框矩形。 在带刘海屏的设备上有什么要求 为了确保一致性和应用兼容性,搭载 Andro

weixin_42803953的博客 911

Android沉浸式体验全解析:从WindowInsets到布局适配的实战指南

在移动应用开发中,系统状态栏和导航栏的视觉协调是提升用户体验的关键技术点。其核心原理在于通过窗口管理系统,控制应用内容与系统UI层的绘制关系,实现界面一体化。从技术价值看,这不仅能消除视觉割裂感,更能为视频播放、阅读、游戏等场景提供沉浸式体验。在Android系统中,WindowInsets机制是处理此类问题的基石,它精确描述了系统栏占用的屏幕空间信息,为布局适配提供可靠依据。随着API演进,从传统的View.setSystemUiVisibility到现代的WindowInsetsController,开

weixin_30443731的博客 595

Android Q刘海屏适配实战:从系统设置到Overlay机制全解析

本文深入解析Android Q刘海屏适配的全过程,从系统设置到Overlay机制的实现细节。通过DisplayCutout API和OverlayManagerService的动态覆盖技术,开发者可以灵活应对不同刘海形态的显示挑战,确保应用兼容性和用户体验。文章还提供了厂商定制实践方案和疑难问题排查指南,助力开发者高效完成刘海屏适配。

weixin_28455801的博客 421

Android P版本 刘海屏适配 与WindowInsets,DisplayCutout使用

Android P版本的发布,引入了刘海屏的概念,像华为nova 3e,vivo X21等手机厂商也纷纷推出自己的刘海屏手机,我们先预览下HUAWEI nova 3e的机照 从这张图中我们可以看出,所谓的刘海屏实际上是安装在状态栏的一块玻璃屏幕,刘海屏的高度等于状态栏的高度 如果我们的的app没有适配android p的刘海屏,那么在显示的时候变会出现问题, 1)如没有状态栏,全屏显示的...

Mydtudysy的博客 3716

Android异形屏全屏适配实战:从官方API到厂商兼容方案

本文深入解析Android异形屏全屏适配的核心挑战与实战方案。首先明确适配目标在于利用长屏空间并防止内容被刘海、挖孔等缺口遮挡。文章详细介绍了Android 9.0+的官方DisplayCutout API应用,包括关键窗口属性设置、安全区域获取,并重点提供了华为、小米、OPPO等主流厂商在Android O系统上的兼容方案与代码封装策略,最后总结了横竖屏场景下的代码示例与核心避坑指南,帮助开发者实现完美的沉浸式体验。

weixin_29200741的博客 412

安卓应用开发中刘海屏/挖孔屏适配详解

摘要: 本文详细解析了安卓应用开发中刘海屏/挖孔屏的适配问题及解决方案。主要内容包括: 问题现象:UI元素被遮挡、内容显示不全等常见问题。 原因分析:硬件特性导致显示凹口(DisplayCutout),系统默认行为可能造成布局偏移。 解决方案: 通过windowLayoutInDisplayCutoutMode设置窗口布局模式(推荐shortEdges)。 使用WindowInsets动态获取刘海区域并调整布局。 兼容横屏模式下的挖孔位置,适配不同厂商设备。 测试与调试:利用Android Studio预览

深山技术宅的博客 1224

Android屏幕尺寸获取全解析:从基础概念到实战适配方案

在Android应用开发中,屏幕适配是构建良好用户体验的基础,其核心在于准确获取屏幕尺寸信息。理解屏幕宽高、状态栏高度和导航栏高度等概念,是解决UI布局错位、元素遮挡等问题的关键。从技术原理层面,Android系统通过DisplayMetrics、WindowManager和资源系统等API提供这些尺寸数据,开发者需要掌握不同API的适用场景与兼容性差异。这些技术的工程价值在于为沉浸式状态栏、全屏弹窗、复杂滚动布局等常见场景提供精确的布局计算依据。例如,通过组合使用资源获取与视图计算策略,可以稳定获取状态栏

weixin_30873847的博客 385

深入解析WindowInsets:从基础概念到实战应用

本文深入解析Android中的WindowInsets概念,从基础原理到实战应用全面覆盖。详细介绍了WindowInsets的分发机制、系统UI遮挡处理方案,以及全面屏和动态键盘等进阶适配技巧,帮助开发者解决常见布局问题,提升应用兼容性。

weixin_28720767的博客 170

阔比例屏幕适配全解析:从技术原理到Android/iOS/Web开发实践

屏幕适配是移动开发与前端开发中的基础技术概念,其核心原理在于确保应用界面在不同尺寸和比例的显示设备上都能正确渲染与交互。随着全面屏技术的普及,屏幕长宽比从传统的16:9演进至18:9、20:9乃至21:9等更“阔”的比例,这直接关系到应用的用户体验与市场兼容性。从技术价值看,适配阔比例屏幕不仅是避免UI错乱和内容遮挡的必要措施,更是充分利用屏幕显示面积、提升信息密度和沉浸感的关键。在应用场景上,它深刻影响着移动应用开发、网页设计、游戏界面和视频播放等众多领域。本文聚焦于这一趋势,深入探讨了Android平台

weixin_30740581的博客 956

Cadence创建异形焊盘教程(详细操作)

背景:一些常见的矩形/圆形焊盘,设置参数就可。碰到非规则的一些焊盘,那只能用Cadence Allegro PCB来画咯。 一、新建图形 【File】——>【New…】 弹出如下窗口,选择绘制的类型Shape symbol、路径,输入名字 二、设置参数 【Setup】——>【Design Parameters…】 Enhanced display modes:增强型显示模型。全部勾选上。 在【Design】设置单位为mm 设置偏移量(-50,-50) 三、绘制图形 1、找到原点,即参考

qq_42057393的博客 2万+

Android沉浸式状态栏(透明状态栏)最佳实现和刘海屏的适配

参考链接 Android沉浸式状态栏(透明状态栏)最佳实现

a_sid的博客 3625

VC Spyglass CDC实战:如何快速定位和解决重汇聚问题(附详细调试步骤)

本文深入探讨了在SoC设计中利用VC Spyglass进行CDC验证时,如何高效定位和解决棘手的重汇聚问题。通过实战演练,详细解析了重汇聚的本质、VC Spyglass的检测逻辑,并提供了从报告筛选、GUI原理图分析到制定设计修复或约束豁免方案的全套调试步骤,帮助工程师快速攻克这一常见验证难题。

weixin_29219539的博客 754

数字IC后端设计实战:从floorplan到powerplan的优化策略

本文深入探讨了数字IC后端设计中从Floorplan到Powerplan的核心优化策略。文章强调了Floorplan作为布局基础的重要性,并详细解析了Powerplan规划,特别是针对低功耗设计中MTCMOS的应用与IR Drop分析。通过实战经验分享,提供了从模块摆放到电源网络构建、再到IR Drop问题层层递进的解决方案,旨在帮助后端工程师构建稳健高效的芯片物理设计。

weixin_28338005的博客 349

阔比例手机屏幕适配:从沉浸体验到开发实践的全方位解析

屏幕纵横比是移动设备硬件形态演进的核心指标之一,它定义了屏幕宽度与高度的比例关系。随着全面屏技术的普及,18:9、19.5:9乃至21:9等阔比例屏幕逐渐成为主流,其原理在于通过改变物理尺寸比例来扩展可视区域。这种变化的技术价值在于显著提升影音娱乐的沉浸感、优化多任务分屏效率,并为游戏等应用提供更宽广的视野。在实际应用场景中,开发者需要面对不同屏幕比例和异形屏(如刘海屏、挖孔屏)带来的适配挑战,确保界面元素不被遮挡、内容显示正常。阔比例屏幕的适配涉及响应式布局、安全区域处理等关键技术,通过合理使用系统API

chuange6363的博客 1210

WRF中使用ERA5再分析数据

   本人在做一些实例时,需要用到最新的ERA5再分析数据集,其中我下载的是ERA5 hourly data on pressure levels form 1979 to present和ERA5 hourly data on single levels from 1979 to present中的3天数据。 1、注册climate copernicus账号 下载ERA5数据前先要注册其账号 2、选择变量    WRF中对于气象数据的字段有具体的要求, ......

GIS 8171

Android 9.0+异形屏适配实战:从黑边到全屏显示的完整代码解决方案

本文详细解析了Android 9.0+异形屏适配的官方方案,提供从黑边到全屏显示的完整代码解决方案。通过核心原理、窗口级适配策略、视图级安全区域处理等多维度技术路径,帮助开发者解决刘海屏、水滴屏等设备的显示问题,提升应用视觉体验。重点介绍了DisplayCutout API的使用和兼容性处理方案。

weixin_29234509的博客 280

2024最新版Anaconda Navigator安装使用指南

本文简要介绍如何下载安装Anaconda Navigator最新版,以及如何使用Python内核搭载来完成应用程序开发。

jackson_lingua的博客 1万+

YOLO26科研优化:多损失函数(EIoU、SIoU等)融合,让边界框回归精度再上台阶

将原有损失函数替换为我们编写的MultiLoss。例如,在bbox_loss。

LXY_LOVE36的博客 172

Android异形屏全场景适配实战:从官方API到厂商兼容方案

本文深入探讨Android异形屏全场景适配的实战方案,从官方API到各厂商兼容方案全面解析。针对华为、小米、OPPO/VIVO等主流设备的特殊处理提供详细代码示例,涵盖全屏游戏、视频播放、电子书阅读等典型场景,帮助开发者解决刘海屏、挖孔屏等异形屏适配难题,提升应用兼容性和用户体验。

weixin_42525582的博客 214

python爬虫项目(一百九十八):电商平台用户行为数据分析与推荐系统、爬取电商平台用户行为数据

本文详细介绍了如何通过爬虫技术抓取电商平台的用户行为数据,并结合数据分析技术,构建一个简单的推荐系统。使用Selenium模拟用户操作抓取动态网页数据,并通过API接口直接获取用户行为数据,能够为后续的用户行为分析提供基础数据。我们结合了基于用户协同过滤、基于商品协同过滤和矩阵分解等方法,构建了不同的推荐系统。实际应用中,可以进一步优化推荐算法,利用更复杂的深度学习技术和更高效的数据处理方法,提升推荐的准确性和个性化程度。

斌擎科技 2362

Android游戏异形屏适配全攻略:从安全区域到UI布局的实战指南

在Android应用开发中,屏幕适配是确保应用在不同设备上提供一致体验的基础技术。其核心原理在于处理多样化的屏幕尺寸、比例和显示特性,通过系统提供的窗口管理、视图层级和资源匹配机制来实现。这项技术的工程价值在于能够最大化利用硬件显示区域,同时保证关键内容的可访问性和交互性,直接影响用户沉浸感和应用评分。尤其在游戏开发、视频播放和全屏应用等场景中,适配的精细度直接关系到核心功能体验。本文聚焦于Android游戏开发中的异形屏适配挑战,深入解析如何通过处理显示切口和安全区域,结合沉浸式全屏技术,确保游戏画面完美

weixin_30633405的博客 392

【Qt开发】管理OpenGL上下文QOpenGLContext类及应用实践示例代码

QOpenGLContext 提供了一个简单、高效的接口来管理 OpenGL 上下文。本文详细介绍了 QOpenGLContext 的基本功能、常用方法、信号槽机制、高级应用技巧及常见问题的解决方法。通过这些介绍,读者可以更好地掌握和利用 QOpenGLContext 进行 OpenGL 渲染和管理实验。对于有特殊需求的开发者,也可以通过探索更多高级设置和优化策略,以满足具体的应用场景。

科技改变人类,技术成就未来 1873

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Android版本差异适配方案(5.0-11.0)

Android版本差异适配方案(5.0-9.0) 一个好的APP最好支持90%设备,由于不同版本系统提供的API可能不同,所以了解不同版本间系统差异很重要,这样才能更好的适配更多的智能设备。你的应用足不足够健壮要看你的应用在主流版本运行是否流畅。这篇文章记录开发过程中遇到的相对重要以及常用的适配方案,希望对读者有所帮助。 Android 版本号及对应的版本名 版本号 版本名 中文名 ...

博由心生,福泽一生 6715

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: Android P版本 新功能介绍和兼容性处理(五)利用 Wi-Fi RTT进行室内定位
下一篇: Gradle问题: AAPT2 error和"aapt.exe'' finished with non-zero exit value 1或者AAPT2与Robelectric不兼容
yi_master
博客等级 码龄10年 283粉丝 104原创
评论 19
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值