Unity刘海屏幕适配
華為適配官網網址: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,//oppoOPPO,//vivoVIVO}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,其他的自己根據查到的尺寸設置吧。
公司沒有真機,這些都是一點一點試驗出來的,有問題希望大家多多指點。
?
?
總結
以上是生活随笔為你收集整理的Unity刘海屏幕适配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手把手教你学Python之波士顿房价预测
- 下一篇: 创意编程绘制