华为适配官网网址:http://developer.huawei.com/consumer/cn/devservice/doc/50114
小米适配官网网址:https://dev.mi.com/console/doc/detail?pId=1293
Oppo适配官网网址:https://open.oppomobile.com/service/message/detail?id=61876
Vivo适配官网网址:https://dev.vivo.com.cn/doc/document/info?id=103
1、获取手机型号和手机厂商
https://blog.csdn.net/id19870510/article/details/7727046
public class ScreenAdaptation {
public enum AndroidPhoneType {
NONE,
// 华为
HuaWei,
// 小米
XiaoMi,
//oppo
OPPO,
//vivo
VIVO
}
private static String LogTag = "ScreenAdapation";
public static final String DISPLAY_NOTCH_STATUS = "display_notch_status";
public static void StartScreenAdapation(Context curContext) {
Log.i(LogTag, "curContext:" + curContext);
String phoneModel = GetManufature();
Log.i(LogTag, "phoneModel:" + phoneModel);
AndroidPhoneType type = GetAndroidPhoneType(phoneModel);
switch (type) {
case HuaWei:
huaWeiScreenAdaptation(curContext);
break;
case XiaoMi:
xiaomiScreenAdaptation(curContext);
break;
case OPPO:
oppoScreenAdaptation(curContext);
break;
case VIVO:
vivoScreenAdaptation(curContext);
break;
default:
break;
}
}
private static AndroidPhoneType GetAndroidPhoneType(String phoneModel) {
AndroidPhoneType type = AndroidPhoneType.NONE;
String phoneUpperModel = phoneModel.toUpperCase();
Log.i(LogTag, "phoneUpperModel:" + phoneUpperModel);
if (phoneUpperModel.contains("HUAWEI")) {
type = AndroidPhoneType.HuaWei;
} else if (phoneUpperModel.contains("XIAOMI")) {
type = AndroidPhoneType.XiaoMi;
} else if (phoneUpperModel.contains("OPPO")) {
type = AndroidPhoneType.OPPO;
} else if (phoneUpperModel.contains("VIVO")) {
type = AndroidPhoneType.VIVO;
}
Log.i(LogTag, "type:" + type);
return type;
}
/*获取手机型号
*/
private static String GetModel() {
String str = android.os.Build.MODEL;
Log.i(LogTag, str);
return str;
}
/*获取手机制造商
*/
private static String GetManufature() {
String str = android.os.Build.MANUFACTURER;
Log.i(LogTag, str);
return str;
}
}
2、sdk manager下载Android P(API27,P preview)这个模拟器,便与测试
参考链接:https://blog.csdn.net/yi_master/article/details/80309757
如何在模拟器里面开启刘海屏设置。但是其实没什么用,没有测试后面判断刘海屏幕的代码无法执行。
3、eclipse创建一个安卓项目,发现android-support-v7-appcompat.jar里面没有AppCompatActivity.java脚本。最后放弃eclipse,更新太恶心了,更完后打开eclipse一堆sdk错误。
果断换android studio,下载快,模拟器也很方便。其实流程差不多,我重点拿华为的做例子吧,其他的就直接给代码。
1)关于华为适配:我用的是华为适配方案,感觉华为自己的方案肯定最好。而小米就直接照着写就可以了。
创建一个demo项目,创建一个ScreenAdaptation.java脚本,
private static void huaWeiScreenAdaptation(Context curContext) {
if (hasNotchInScreen_huawei(curContext)) {
int[] iwh = getNotchSize_huawei(curContext);
// 0表示“默认”,1表示“隐藏显示区域”
int mIsNotchSwitchOpen = Settings.Secure.getInt(curContext.getContentResolver(), DISPLAY_NOTCH_STATUS, 0);
Log.i(LogTag, iwh[0] + "|" + iwh[1] + ",mIsNotchSwitchOpen:" + mIsNotchSwitchOpen);
UnityPlayer.UnitySendMessage("ScreenAdapation", "ScreenAdaptation", iwh[0]+"|"+iwh[1]);
} else {
Log.i(LogTag, "不是刘海屏幕!");
}
}
/*
* 是否是刘海屏手机: true:是刘海屏 false:非刘海屏
*/
private static boolean hasNotchInScreen_huawei(Context context) {
boolean ret = false;
try {
ClassLoader cl = context.getClassLoader();
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
Object obj = get.invoke(HwNotchSizeUtil);
Log.e(LogTag, "000:"+obj.toString());
if(obj != null)
ret = obj.toString().toUpperCase().equals("TRUE") ? true : false;
Log.e(LogTag, "000:"+ret);
} catch (ClassNotFoundException e) {
Log.e(LogTag, "error hasNotchInScreen ClassNotFoundException");
} catch (NoSuchMethodException e) {
Log.e(LogTag, "error hasNotchInScreen NoSuchMethodException");
} catch (Exception e) {
Log.e(LogTag, "error hasNotchInScreen Exception:"+e.getMessage());
} finally {
return ret;
}
}
/*
* 获取刘海尺寸:width、height int[0]值为刘海宽度 int[1]值为刘海高度
*/
private static int[] getNotchSize_huawei(Context context) {
int[] ret = new int[]{0, 0};
try {
ClassLoader cl = context.getClassLoader();
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
Method get = HwNotchSizeUtil.getMethod("getNotchSize");
ret = (int[]) get.invoke(HwNotchSizeUtil);
} catch (ClassNotFoundException e) {
Log.e(LogTag, "error getNotchSize ClassNotFoundException");
} catch (NoSuchMethodException e) {
Log.e(LogTag, "error getNotchSize NoSuchMethodException");
} catch (Exception e) {
Log.e(LogTag, "error getNotchSize Exception:"+e.getMessage());
} finally {
return ret;
}
}
在模拟器上面测试,由于不是华为刘海屏的硬件设备,所以测试根本看不到表现,只能看一下
2)关于测试在Testin上测试:适配后效果对比,我们做刘海屏适配的是横屏幕,只考虑这个
华为P20上面:
没做适配前:左右两边都有黑色条形图
做了适配后:界面拉伸至全屏幕
3)问题:的确做了效果和华为官方一样,但是testin上面是没有刘海区域的,在真机上面可以发现红色区域按钮被刘海屏幕遮挡了。看了一下王者荣耀其他的游戏解决方案,他们改了UI界面,由于上限测试时间有限,为了统一处理,我们想把所有UI界面统一右移动处理。当然其他的游戏可以根据自己的游戏来一套解决方案,将刘海屏幕的区域改设计啥的。
思路: 在android项目的java代码里面:判断手机类型->判断是否是刘海屏幕(根据官网网址)->是的话,发送UnitySendMessage,告知刘海区域尺寸->untiyc#代码处理
要考虑屏幕翻转:
UI如何右移动:设置camera的ViewportRect的x数值
UI如何左移动:设置camera的ViewportRect的w数值
在游戏里面创建一个UICamera:所有UI都有它控制。
然后每个面板创建的时候,公司的游戏有统一处理函数,只要创建的时候给UICanvas,设置上UICamera就可以了。
相关代码:
关于设置右移动的相关代码:自己根据需求改,这个主要是测试的,屏幕尺寸自己可以得到,刘海屏尺寸传过来的自己解析:
CheckSwitchScreen.cs脚本代码如下:
using UnityEngine;
using System.Collections;
public class CheckSwitchScreen : MonoBehaviour {
public float OffsetX = 80f;
bool liuHai = false;
ScreenOrientation screenOrientationKind = ScreenOrientation.Unknown;
Rect rect;
float offsetRate = 0f;
static bool extra = false;
void Awake() {
if (extra) Destroy(gameObject);
else {
extra = true;
DontDestroyOnLoad(gameObject);
}
}
//void OnEnable() {
// ScreenAdaptation();
//}
void ScreenAdaptation(string size) {
Debug.Log("ScreenAdaptation:" + Screen.orientation);
Debug.Log("size:" + size);
offsetRate = OffsetX / 2280f;
liuHai = true;
screenOrientationKind = Screen.orientation;
//初始化一次
InitView();
}
void InitView() {
// home 在右边
if (screenOrientationKind == ScreenOrientation.LandscapeLeft) {
var uiCamera = GameMain.sharedInstance.uiCamera;
if (uiCamera != null)
uiCamera.rect = new Rect(offsetRate, 0, 1, 1f);
} else if (screenOrientationKind == ScreenOrientation.LandscapeRight) {
var uiCamera = GameMain.sharedInstance.uiCamera;
if (uiCamera != null)
uiCamera.rect = new Rect(0, 0, 1 - offsetRate, 1f);
}
}
void Update() {
if (liuHai && screenOrientationKind != Screen.orientation) {
screenOrientationKind = Screen.orientation;
InitView();
}
}
}
4.关于小米,vivo,oppo手机的处理:
private static void xiaomiScreenAdaptation(Context context) {
if (hasNotchInScreen_Xiaomi(context)) {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
int result = context.getResources().getDimensionPixelSize(resourceId);
Log.e(LogTag, "xiaomiScreenAdaptation:" + result);
UnityPlayer.UnitySendMessage("ScreenAdapation", "ScreenAdaptation", "");
}
Log.e(LogTag, "00000:" + resourceId);
} else {
Log.e(LogTag, "222222222");
}
}
private static boolean hasNotchInScreen_Xiaomi(Context context) {
boolean result = false;
try {
ClassLoader cl = context.getClassLoader();
Class systemPro = cl.loadClass("android.os.SystemProperties");
Method get = systemPro.getMethod("get", String.class);
Object obj = (get.invoke(systemPro, "ro.miui.notch"));
if(obj != null)
result = (String) obj == "1" ? true : false;
Log.e(LogTag, "curResult:"+result);
} catch (ClassNotFoundException e) {
Log.e(LogTag, "error hasNotchInScreen_Xiaomi ClassNotFoundException");
} catch (NoSuchMethodException e) {
Log.e(LogTag, "error hasNotchInScreen_Xiaomi NoSuchMethodException");
} catch (Exception e) {
Log.e(LogTag, "error hasNotchInScreen_Xiaomi Exception:" + e.getMessage());
} finally {
return result;
}
}
private static void oppoScreenAdaptation(Context context) {
if(context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism")) {
Log.i(LogTag, "oppoScreenAdaptation true");
UnityPlayer.UnitySendMessage("ScreenAdapation", "ScreenAdaptation", "");
}else{
Log.i(LogTag, "oppoScreenAdaptation false");
}
}
private static void vivoScreenAdaptation(Context context) {
if(hasNotchInScreen_Vivo(context)){
Log.e(LogTag, "vivoScreenAdaptation true");
}
else{
Log.e(LogTag, "vivoScreenAdaptation false");
}
}
private static final int NOTCH_IN_SCREEN_VOIO=0x00000020;//是否有凹槽
private static final int ROUNDED_IN_SCREEN_VOIO=0x00000008;//是否有圆角
private static boolean hasNotchInScreen_Vivo(Context context){
boolean ret = false;
try {
ClassLoader cl = context.getClassLoader();
Class FtFeature = cl.loadClass("android.util.FtFeature");
Method get = FtFeature.getMethod("isFeatureSupport",int.class);
Object obj = get.invoke(FtFeature,NOTCH_IN_SCREEN_VOIO);
Log.e(LogTag, "000:"+obj.toString());
if(obj != null)
ret = obj.toString().toUpperCase().equals("TRUE") ? true : false;
else {
Log.e(LogTag, "obj is null!");
}
} catch (ClassNotFoundException e){
Log.e(LogTag, "hasNotchInScreen ClassNotFoundException");
}
catch (NoSuchMethodException e){
Log.e(LogTag, "hasNotchInScreen NoSuchMethodException");
}
catch (Exception e){
Log.e(LogTag, "hasNotchInScreen Exception");
}
finally{
return ret;}
}
除了华为给力,给了相关的尺寸的API,其他的自己根据查到的尺寸设置吧。
公司没有真机,这些都是一点一点试验出来的,有问题希望大家多多指点。