内容简介:起因:Iphone X掀起的一波刘海屏手机潮(虽然个人觉得很丑),国内各大手机厂商纷纷效仿,导致我们的小游戏各种黑边奇丑无比翻阅CSDN大神奉献的博文参考:踩坑历程一:
起因:Iphone X掀起的一波刘海屏手机潮(虽然个人觉得很丑),国内各大手机厂商纷纷效仿,导致我们的小游戏各种黑边奇丑无比
翻阅CSDN大神奉献的博文参考: android 兼容所有刘海屏的方案大全
踩坑历程一: 项目经理要求不适配了,简单处理,让游戏界面显示状态栏。
1.判断手机是否为刘海屏手机,根据 android 兼容所有刘海屏的方案大全 可以获取华为、小米、VO的刘海屏标志。
2.刘海屏手机下:
a.启动Activity保持全屏不变
b.游戏Activity,如果为竖屏状态,需要退出全屏,显示状态栏(退出全屏),并且隐藏虚拟按键,如果为横屏状态:
c.横竖屏切换时游戏Activity需要全屏,并且GLSurfaceView的大小改变,并偏移。
竖屏->横屏 屏幕全屏,GLSurfaceView宽度= 屏幕宽度-状态栏高度, GLSurfaceView高度= 屏幕高度
横屏->竖屏 退出屏幕全屏,GLSurfaceView宽度= 屏幕宽度, GLSurfaceView高度= 屏幕高度-状态栏高度
d.第三方支付SDK初始化时自动弹出登入Activity,导致状态栏被迫显示,返回游戏Activity需要重新设置。
………..N种情况,不在详细列举
3.游戏场景横竖屏切换,需要操作两个步骤
a.调用Activity的强制旋转。
b.游戏内glview需要重新设置FrameSize() auto glview = Director::getInstance()->getOpenGLView();
涉及代码:
判断刘海屏情况
package com.pdragon.common.utils; import java.lang.reflect.Method; import com.pdragon.common.UserApp; import com.pdragon.common.UserSystemProperties; import android.content.Context; /** * 全面屏 * @author Administrator * */ @SuppressWarnings("rawtypes") public class NotchInScreen { public final static String TAG = "NotchInScreen"; //屏幕类型 public static enum ScreenType{ LIUHAI, //刘海屏 LOUKONG, //镂空屏 }; public int top_height = 0; //顶部高度 public int top_width = 0; //顶部隐藏部分的宽度 public int bottom_height = 0; //底部高度 public int bottom_width = 0; //底部隐藏部分的宽度 public boolean hasNotchInScreen = false; public boolean needSetGamePadding = false;//是否需要设置游戏Layout的padding,由于华为和小米在Manifes当中设置当前App是否需要绘制全面屏。所以这个类里面的的代码需要做相应的调整 private static NotchInScreen instance = null; public static synchronized NotchInScreen getInstance(Context ctx){ if(instance== null){ synchronized (NotchInScreen.class) { if(instance== null){ instance = new NotchInScreen(ctx); } } } return instance; } public NotchInScreen(Context ctx){ int[] ret = new int[] {0, 0, 0, 0}; if(hasNotchInScreenHuawei(ctx)){ hasNotchInScreen = true; needSetGamePadding = false; ret = getNotchSizeHuawei(ctx); } else if(hasNotchInScreenOppo(ctx)){ hasNotchInScreen = true; needSetGamePadding = true; ret = getNotchSizeOppo(ctx); } else if(hasNotchInScreenVivo(ctx)){ hasNotchInScreen = true; needSetGamePadding = false; ret = getNotchSizeVivo(ctx); } else if(hasNotchInScreenXiaomi(ctx)){ hasNotchInScreen = true; needSetGamePadding = false; ret = getNotchSizeXiaomi(ctx); } if(hasNotchInScreen){ top_width = ret[0]; top_height = ret[1]; bottom_width = ret[2]; bottom_height = ret[3]; } UserApp.LogD(String.format("needSetGamePadding = %b, hasNotchInScreen=%b, {%d, %d, %d, %d}", needSetGamePadding, hasNotchInScreen, top_width, top_height, bottom_width, bottom_height)); } /** * 判断是否是刘海屏 */ @SuppressWarnings("finally") public static boolean hasNotchInScreenHuawei(Context ctx) { boolean ret = false; try { ClassLoader cl = ctx.getClassLoader(); Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil"); Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen"); ret = TypeUtil.ObjectToBooleanDef(get.invoke(HwNotchSizeUtil, null), false); } catch (Exception e) { UserApp.LogD(TAG, "huawei hasNotchInScreen Exception"); } finally { UserApp.LogD(TAG, "huawei hasNotchInScreen:" + ret); return ret; } } // 获取刘海的高宽 @SuppressWarnings("finally") public static int[] getNotchSizeHuawei(Context ctx) { int[] ret = new int[] {0, 0, 0, 0}; int[] ret_huawei = new int[]{0, 0}; try { ClassLoader cl = ctx.getClassLoader(); Class<?> HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil"); Method get = HwNotchSizeUtil.getMethod("getNotchSize"); ret_huawei = (int[]) get.invoke(HwNotchSizeUtil); ret[0] = ret_huawei[0]; ret[1] = ret_huawei[1]; } catch (Exception e) { UserApp.LogD(TAG, "huawei getNotchSize Exception"); } finally { return ret; } } //判断是否是刘海屏 public static boolean hasNotchInScreenOppo(Context ctx) { boolean ret = ctx.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism"); //UserApp.LogD(TAG, "Oppo hasNotchInScreenHuawei:" + ret); return ret; } // 获取刘海的高宽 public static int[] getNotchSizeOppo(Context ctx) { int[] ret = new int[] {324, 80, 0, 0}; return ret; } public static final int NOTCH_IN_SCREEN_VOIO=0x00000020;//是否有凹槽 public static final int ROUNDED_IN_SCREEN_VOIO=0x00000008;//是否有圆角 //判断是否是刘海屏 public static boolean hasNotchInScreenVivo(Context ctx) { boolean ret = false; try { ClassLoader cl = ctx.getClassLoader(); Class FtFeature = cl.loadClass("android.util.FtFeature"); Method get = FtFeature.getMethod("isFeatureSupport", int.class); ret = Boolean.parseBoolean(TypeUtil.ObjectToString(get.invoke(FtFeature, NOTCH_IN_SCREEN_VOIO))); }catch (Exception e) { UserApp.LogD(TAG, "vivo hasNotchInScreen Exception"); } finally { UserApp.LogD(TAG, "vivo hasNotchInScreen:" + ret); return ret; } } // 获取刘海的高宽 public static int[] getNotchSizeVivo(Context ctx) { int height = CommonUtil.dip2px(ctx, 50); int width = CommonUtil.getScreenWidth(ctx); int[] ret = new int[] {width, height, width, height}; return ret; } //判断是否是刘海屏 public static boolean hasNotchInScreenXiaomi(Context ctx) { if(UserSystemProperties.getInt("ro.miui.notch", 0) == 1){ return true; } return false; } // 获取刘海的高宽 public static int[] getNotchSizeXiaomi(Context ctx) { int status_bar_height = 0; int resourceId = ctx.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { status_bar_height = ctx.getResources().getDimensionPixelSize(resourceId); } int[] ret = new int[] {0, status_bar_height, 0, 0}; return ret; } }
/** * 隐藏虚拟系统按键 */ @TargetApi(Build.VERSION_CODES.KITKAT) public static void hideVirtualNavigation(Activity act) { if(!UserApp.curApp().isGameApp()){ return;//应用类App不隐藏虚拟按键 } if (Build.VERSION.SDK_INT >= 19) { if (Build.VERSION.SDK_INT >= 21) { act.getWindow().setNavigationBarColor(Color.TRANSPARENT); } NotchInScreen inScreen = NotchInScreen.getInstance(act); if(inScreen.hasNotchInScreen){//存在凹凸屏 //声明当前屏幕状态的参数并获取 act.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } else{//不存在凹凸屏 act.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } } } /** * 设置全屏 */ public static void setFullScreen(Activity act) { // 设置全屏的相关属性,获取当前的屏幕状态,然后设置全屏 act.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 全屏下的状态码:1098974464 // 窗口下的状态吗:1098973440 } /** * 退出全屏 */ public static void quitFullScreen(Activity act) { // 声明当前屏幕状态的参数并获取 Window window = act.getWindow(); final WindowManager.LayoutParams attrs = window.getAttributes(); attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); window.setAttributes(attrs); window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); }
经历以上历程,会发现,很多的情况并非理想中的情况,总有兼容性问题。经过多方测试,最终放弃。
踩坑历程二:游戏内全部适配刘海屏,所有手机均全屏显示:
1.小米需要在Manifest中设置绘制刘海屏
<meta-data android:name="notch.config" android:value="portrait|landscape"/>
2.华为手机需要在Manifest中设置绘制刘海屏
<meta-data android:name="android.notch_support" android:value="true"/>
3.vivo只要设置了全面屏即可,然而,在8.01的设备上,系统内部bug,导致设置了之后,不生效(和vivo的开发人员沟通得出的结果),唯一的途径就是,给vivo的人在服务器设置白名单,只有服务器设置了之后,我们的App才会在进入时绘制刘海屏(此处巨坑)。
全面屏适配:
<meta-data android:name="android.max_aspect" android:value="2.4" />
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- iOS12适配及兼容问题解决
- 微信模块 Oejia_wx v0.6.3 发布,多项兼容优化,即将全面适配 Odoo14
- flutter 屏幕尺寸适配 字体大小适配
- 前端适配:移动端/web端适配方案
- iOS 关于全面屏适配的方案及UI在不同尺寸下适配方案
- iOS 关于全面屏适配的方案及UI在不同尺寸下适配方案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。