Android刘海屏适配历程,兼容Android8.0

栏目: IOS · Android · 发布时间: 5年前

内容简介:起因: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" />

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Web Application Hacker's Handbook

The Web Application Hacker's Handbook

Dafydd Stuttard、Marcus Pinto / Wiley / 2011-9-27 / USD 50.00

The highly successful security book returns with a new edition, completely updated Web applications are the front door to most organizations, exposing them to attacks that may disclose personal infor......一起来看看 《The Web Application Hacker's Handbook》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具