日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 配置aspect_Android APP全面屏适配技术要点

發(fā)布時間:2025/4/16 Android 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 配置aspect_Android APP全面屏适配技术要点 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

全面屏的概念

為什么先要解釋一下全面屏,因為這個詞在現(xiàn)在來講就是一個偽命題。全面屏字面意思就是手機的正面全部都是屏幕,100%的屏占比。但是現(xiàn)在推出所謂“全面屏”手機的廠商沒有一個能達到全面的。

那么下面來說一下Android開發(fā)領域?qū)θ嫫恋睦斫夂投x吧。

一般手機的屏幕縱橫比為16:9,如1080x1920、1440x2560等,其比值為1.77,在全面屏手機出現(xiàn)之前,Android中默認的最大屏幕縱橫比(maximum aspect ratio)為1.86,即能夠兼容16:9的屏幕。

一些手機廠商為了追求更大的屏幕空間以及更極致的用戶體驗,于是提高了屏幕縱橫比,17:9、19:10、18:9、18.5:9的手機開始進入市場,這些手機的屏幕縱橫比大大超過了1.86,這些手機被稱為全面屏手機。

為何需要適配

我們將targetSdkVersion的值改為小于等于23,運行程序,我們會發(fā)現(xiàn)屏幕底部出現(xiàn)一個黑條。

image

如何適配

targetSdkVersion<=23,更大的屏幕縱橫比

在Galaxy S8發(fā)布之后,Android官方提供了適配方案,即提高App所支持的最大屏幕縱橫比,實現(xiàn)很簡單,在AndroidManifest.xml中可做如下配置:

android:value="ratio_float"/>

其中ratio_float為浮點數(shù),官方建議為2.1或更大,因為18.5:9=2.055555555……,如果日后出現(xiàn)縱橫比更大的手機,此值將會更大。

android:value="2.1" />

max_aspect值也可以在Java代碼中動態(tài)地設置,通過下面的方法即可實現(xiàn):

public void setMaxAspect() {

ApplicationInfo applicationInfo = null;

try {

applicationInfo = getPackageManager().getApplicationInfo(getPackageName(),

PackageManager.GET_META_DATA);

} catch (PackageManager.NameNotFoundException e) {

e.printStackTrace();

}

if(applicationInfo == null){

throw new IllegalArgumentException(" get application info = null ");

}

applicationInfo.metaData.putString("android.max_aspect", "2.1");

}

如果targetSdkVersion的值的值大于23,那么應該不用設置max_aspect即可。

查看適配之后的截圖:

image

圖片資源適配

我們看一下啟動頁,在16:9屏幕中適配的圖片,到了18:9的屏幕中就會被拉伸了。

16:9屏幕中顯示

18:9屏幕中顯示

image

image

解決這個問題無非就是兩種方法,換圖片或者是換布局

換圖片

不能依賴單一廠商的解決方案,只能從Android系統(tǒng)屬性出發(fā)。考慮到目前大部分全面屏手機只是在高度上拉長,且大多為6.0英寸左右,像素密度對比xxhdpi并沒有多大區(qū)別,那我們可以在項目中增加一組資源drawable-xxhdpi-2160x1080 、drawable-long 這樣解決圖片的拉伸問題,當然這樣的方法肯定是不太好的,會增加app的容量。這里就不演示了。

優(yōu)化布局

當然最好的方法還是用相對布局采用XML的方式,或者.9圖的解決方案。

我總結的就是少量多切,盡量減少尺寸對布局的影響。比如這里,使用正方形的切圖,讓他居中顯示,無論屏幕縱橫比如何,都不會拉伸這個圖片,拉伸的只是背景而已。

image

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:scaleType="fitCenter"

android:src="@drawable/bz002"/>

適配前

適配后

image

image

全面屏高度問題適配

首先解釋一下window,decorview,rootview這幾個概念

image

Window官方文檔:Window

public abstract class Window. Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc.

The only existing implementation of this abstract class is android.view.PhoneWindow, which you should instantiate when needing a Window.

翻譯一下:每一個 Activity 都持有一個 Window 對象,但是 Window 是一個抽象類,這里 Android 為 Window 提供了唯一的實現(xiàn)類 PhoneWindow。也就是說 Activity 中的 window 實例就是一個 PhoneWindow 對象。

但是 PhoneWindow 終究是 Window,它并不具備多少 View 相關的能力。不過 PhoneWindow 中持有一個 Android 中非常重要的一個 View 對象 DecorView.

現(xiàn)在的關系就很明確了,每一個 Activity 持有一個 PhoneWindow 的對象,而一個 PhoneWindow 對象持有一個 DecorView 的實例,所以 Activity 中 View 相關的操作其實大都是通過 DecorView 來完成。

DecorView就可以理解為手機的內(nèi)屏,就是那塊玻璃,可以發(fā)光的屏幕。

這里通過代碼,打印出我們頁面中的高度的各項數(shù)據(jù)

int decorviewHeight = decorView.getHeight();

int screenHeight = FullScreenManager.getScreenHeight();

int nativeBarHeight = FullScreenManager.getNativeBarHeight();

int contentViewHeight = rootView.getHeight();

int navigationBarHeight1 = FullScreenManager.getNavigationBarHeight();

Log.d("shijiacheng","=======================================");

Log.d("shijiacheng","DecorView height: " + decorviewHeight + " px");

Log.d("shijiacheng","Screen height: " + screenHeight + " px");

Log.d("shijiacheng","NativeBar height: " + nativeBarHeight + " px");

Log.d("shijiacheng","ContentView height: " + contentViewHeight + " px");

Log.d("shijiacheng","NavigationBar height: " + navigationBarHeight + " px");

Log.d("shijiacheng","---------------------------------------");

獲取decorView的高度

final View decorView = getWindow().getDecorView();

int decorviewHeight = decorView.getHeight();

獲得屏幕高度

/**

* 獲得屏幕高度

* @return

*/

public static int getScreenHeight() {

Resources resource = AppContext.getInstance().getResources();

DisplayMetrics displayMetrics = resource.getDisplayMetrics();

return displayMetrics.heightPixels;

}

獲取狀態(tài)欄的高度

/**

* 獲取狀態(tài)欄的高度

*

* @return

*/

public static int getNativeBarHeight() {

Resources resource = AppContext.getInstance().getResources();

int result = 0;

int resourceId = resource.getIdentifier("status_bar_height",

"dimen", "android");

if (resourceId > 0) {

result = resource.getDimensionPixelSize(resourceId);

}

return result;

}

獲取contentView的高度

LinearLayout contentView = findViewById(R.id.root);

int contentViewHeight = contentView.getHeight();

獲取NavigationBar的高度

public static int getNavigationBarHeight() {

Resources resources = AppContext.getInstance().getResources();

int resourceId = resources.getIdentifier("navigation_bar_height","dimen", "android");

int height = resources.getDimensionPixelSize(resourceId);

return height;

}

為了更加直觀的展示各個數(shù)據(jù),這里我們使用布局的方式將各個數(shù)據(jù)展示出來,布局代碼比較簡單,這里就不展示了。

image

先展示一下正常的屏幕高度的各項數(shù)據(jù)

10-08 09:52:03.636 23818-23818/? D/shijiacheng: =========================

10-08 09:52:03.637 23818-23818/? D/shijiacheng: DecorView height: 1280 px

10-08 09:52:03.637 23818-23818/? D/shijiacheng: Screen height: 1280 px

10-08 09:52:03.637 23818-23818/? D/shijiacheng: NativeBar height: 50 px

10-08 09:52:03.637 23818-23818/? D/shijiacheng: ContentView height: 1230 px

10-08 09:52:03.637 23818-23818/? D/shijiacheng: NavigationBar height: 96 px

10-08 09:52:03.637 23818-23818/? D/shijiacheng: -------------------------

image

DecorView = Screen height = NativeBar height + ContentView height

看一下小米mix全面屏的情況

2018-10-08 09:54:15.640 /? D/shijiacheng: =========================

2018-10-08 09:54:15.640 /? D/shijiacheng: DecorView height: 2160 px

2018-10-08 09:54:15.641 /? D/shijiacheng: RootView height: 2094 px

2018-10-08 09:54:15.641 /? D/shijiacheng: Screen height: 2030 px

2018-10-08 09:54:15.641 /? D/shijiacheng: NativeBar height: 66 px

2018-10-08 09:54:15.641 /? D/shijiacheng: ContentView height: 2094 px

2018-10-08 09:54:15.641 /? D/shijiacheng: NavigationBar height: 130 px

2018-10-08 09:54:15.641 /? D/shijiacheng: -------------------------

image

問題出現(xiàn)了,可以發(fā)現(xiàn)contentView的高度比screen屏幕的高度還要大,不禁要懷疑,我們的獲取屏幕高度的方法在全面屏下計算錯誤了。

問題1:獲取屏幕高度方法計算不準確

我們一直都是使用如下方法進行屏幕高度測量的:

public static int getScreenHeight() {

Resources resource = AppContext.getInstance().getResources();

DisplayMetrics displayMetrics = resource.getDisplayMetrics();

return displayMetrics.heightPixels;

}

但是這個方法卻是一個十分古老的方法,沒有與時俱進,雖然說在普通屏幕上這種方法沒有問題,但是在全面屏手機上來說,這種方法就不靈了。

下面我們就來研究一下獲取屏幕尺寸的方法的演進。

獲取屏幕寬高

獲取屏幕的寬高是我們開發(fā)中經(jīng)常遇到的問題,而且相信大家都已經(jīng)非常熟悉,最常用的為以下兩種:

public static int getScreenHeight1(Activity activity) {

return activity.getWindowManager().getDefaultDisplay().getHeight();

}

public static int getScreenHeight2(Activity activity) {

DisplayMetrics displayMetrics = new DisplayMetrics();

activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

return displayMetrics.heightPixels;

}

其實以上兩種方式是一樣的,只不過第二種是把信息封裝到 DesplayMetrics中,再從DesplayMetrics得到數(shù)據(jù)。

在 Android 3.2(Api 13) 之后又提供了如下的一個方法,將數(shù)據(jù)封裝到Point中,然后返回寬度高度信息。

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)

public static int getScreenHeight3(Activity activity) {

Point point = new Point();

activity.getWindowManager().getDefaultDisplay().getSize(point);

return point.y;

}

在 Android 4.2(Api17) 之后提供了如下方法,與第三種類似也是將數(shù)據(jù)封裝到Point中,然后返回款高度信息。

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)

public static int getScreenHeight4(Activity activity) {

Point realSize = new Point();

activity.getWindowManager().getDefaultDisplay().getRealSize(realSize);

return realSize.y;

}

其實getRealSize這個方法在Android Api15的時候就已經(jīng)加入了,不過是被隱藏了,通過查閱源碼我們可以看到。

image

Android Api15 Display.java源碼中getRealSize()方法被標記為@hide

image

因此,我們可以重寫獲取高度的方法,適配所有機型,所有系統(tǒng)。

適配所有屏幕的獲取屏幕尺寸的方法

public static int[] getScreenSize(Context context) {

int[] size = new int[2];

WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

Display d = w.getDefaultDisplay();

DisplayMetrics metrics = new DisplayMetrics();

d.getMetrics(metrics);

// since SDK_INT = 1;

int widthPixels = metrics.widthPixels;

int heightPixels = metrics.heightPixels;

// includes window decorations (statusbar bar/menu bar)

if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)

try {

widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);

heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);

} catch (Exception ignored) {

}

// includes window decorations (statusbar bar/menu bar)

if (Build.VERSION.SDK_INT >= 17)

try {

Point realSize = new Point();

Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);

widthPixels = realSize.x;

heightPixels = realSize.y;

} catch (Exception ignored) {

}

size[0] = widthPixels;

size[1] = heightPixels;

return size;

}

使用新的獲取高度的方法,重新運行程序,運行結果已經(jīng)正常顯示了。

2018-10-08 13:19:32.389 /? D/shijiacheng: ==========================

2018-10-08 13:19:32.390 /? D/shijiacheng: DecorView height: 2160 px

2018-10-08 13:19:32.390 /? D/shijiacheng: Screen height: 2160 px

2018-10-08 13:19:32.390 /? D/shijiacheng: NativeBar height: 66 px

2018-10-08 13:19:32.390 /? D/shijiacheng: ContentView height: 2094 px

2018-10-08 13:19:32.390 /? D/shijiacheng: NavigationBar height: 130 px

2018-10-08 13:19:32.390 /? D/shijiacheng: --------------------------

image

問題2:小米mix切為經(jīng)典導航鍵模式下的計算問題

我們在MIUI設置中將全面屏導航樣式修改為“經(jīng)典導航鍵”樣式。

image

重新運行程序,運行結果如下:

image

可以發(fā)現(xiàn)又出問題了,DecorView = Screen height > NativeBar height + ContentView height

這里不難發(fā)現(xiàn),Screen height將底部虛擬導航欄的高度也算進里面了。

很多情況下,我們都用如下方法獲取導航欄的高度:

public static int getNavigationBarHeight() {

Resources resources = AppContext.getInstance().getResources();

int resourceId = resources.getIdentifier("navigation_bar_height",

"dimen", "android");

int height = resources.getDimensionPixelSize(resourceId);

return height;

}

這種方法得到的導航欄的高度數(shù)值是沒問題的,但是在全面屏的手機上,即使隱藏了導航欄,也是可以獲取到導航欄的高度的。通過上面的logcat日志可以看到,即使沒有導航欄,導航欄的高度的計算也是有值的。

適配小米mix虛擬導航欄

小米mix的機型中,我們可以“force_fsg_nav_bar”來判斷小米手機是否開啟了全面屏手勢。

public static int getHeightOfNavigationBar(Context context) {

//如果小米手機開啟了全面屏手勢隱藏了導航欄則返回 0

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {

if (Settings.Global.getInt(context.getContentResolver(),

"force_fsg_nav_bar", 0) != 0) {

return 0;

}

}

int realHeight = getScreenSize(context)[1];

Display d = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))

.getDefaultDisplay();

DisplayMetrics displayMetrics = new DisplayMetrics();

d.getMetrics(displayMetrics);

int displayHeight = displayMetrics.heightPixels;

return realHeight - displayHeight;

}

因此可以通過這個方法來判斷是否顯示了底部導航欄,并且可以計算導航欄的高度。

int navigationBarHeight = FullScreenManager.getHeightOfNavigationBar(MainActivity.this);

if (navigationBarHeight > 0){

container_navigationview.setVisibility(View.VISIBLE);

}else {

container_navigationview.setVisibility(View.GONE);

}

正常的顯示效果如下:

有虛擬導航欄

沒有虛擬導航欄

image

image

沒有虛擬導航欄Log

2018-10-08 13:19:32.389 /? D/shijiacheng: ==========================

2018-10-08 13:19:32.390 /? D/shijiacheng: DecorView height: 2160 px

2018-10-08 13:19:32.390 /? D/shijiacheng: Screen height: 2160 px

2018-10-08 13:19:32.390 /? D/shijiacheng: NativeBar height: 66 px

2018-10-08 13:19:32.390 /? D/shijiacheng: ContentView height: 2094 px

2018-10-08 13:19:32.390 /? D/shijiacheng: NavigationBar height: 0 px

2018-10-08 13:19:32.390 /? D/shijiacheng: --------------------------

有虛擬導航欄Log

2018-10-08 13:38:03.229 /? D/shijiacheng: ==========================

2018-10-08 13:38:03.230 /? D/shijiacheng: DecorView height: 2160 px

2018-10-08 13:38:03.230 /? D/shijiacheng: Screen height: 2160 px

2018-10-08 13:38:03.230 /? D/shijiacheng: NativeBar height: 66 px

2018-10-08 13:38:03.230 /? D/shijiacheng: ContentView height: 1964 px

2018-10-08 13:38:03.230 /? D/shijiacheng: NavigationBar height: 130 px

2018-10-08 13:38:03.230 /? D/shijiacheng: --------------------------

總結

以上是生活随笔為你收集整理的android 配置aspect_Android APP全面屏适配技术要点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 绿帽视频 | 爱爱视频在线免费观看 | 影音先锋成人 | 亚洲超碰在线观看 | 四虎影视免费在线观看 | 99国产精品久久久久久久成人 | 久久久久逼 | 在线高清观看免费观看 | 日本黄动漫 | 处破痛哭a√18成年片免费 | 国产精品av一区 | 日韩av在线免费观看 | 国产精品福利影院 | 黄色免费网页 | av手机在线免费观看 | 午夜日韩在线观看 | 日韩av成人在线 | 欧美日一区二区 | 国产精品久久久久9999爆乳 | 亚洲三级黄色片 | 中文字幕乱码无码人妻系列蜜桃 | 特黄aaaaaaaaa毛片免费视频 | 6080电视影片在线观看 | 91成人精品视频 | 成人午夜视频在线免费观看 | 成人免费福利 | 一级在线 | 色狠狠一区二区 | 成人欧美一区二区三区黑人冫 | 最新日韩中文字幕 | 色干综合 | 国产麻豆一区二区三区在线观看 | 精品国产18久久久久久 | 欧美成人国产精品高潮 | 免费一级毛片麻豆精品 | 成人av小说| av免费天堂 | 91九色蝌蚪91por成人 | 黄网站在线播放 | 青娱乐极品在线 | 三上悠亚ssⅰn939无码播放 | 成人网战 | 亚洲精品无码久久 | 女人免费视频 | 日韩成人免费在线观看 | 国产男女猛烈无遮挡 | 欧洲成人在线观看 | 日韩激情在线播放 | 日韩视频免费观看 | 99午夜视频 | 亚洲国产av一区二区三区 | 亚洲精品一区 | 毛片网站在线播放 | 日韩中文字幕av | 日韩一区欧美一区 | 国产精品久久一区二区三区 | 91美女啪啪 | 尹人香蕉网 | 日韩极品一区 | 夜夜狠狠擅视频 | 另类在线视频 | 国产美女精品视频国产 | 3d成人动漫在线观看 | 99精品热视频 | 日韩和欧美的一区二区 | 久久久国产精品一区二区三区 | 国产视频一区二区视频 | 91亚洲精品久久久久久久久久久久 | 精品国产一区二区三区在线观看 | 特级a级片 | 中文字幕一区二区人妻 | 日韩不卡视频在线观看 | 性感美女毛片 | 国产激情文学 | 国产乱欲视频 | 优优色综合 | 日韩精品一区中文字幕 | 91综合在线 | 乱xxxxx普通话对白 | 久久久免费高清视频 | 亚洲av无码一区二区乱孑伦as | 另类小说亚洲色图 | 在线看黄色网址 | 精品人妻人伦一区二区有限公司 | 村姑电影在线播放免费观看 | 91搞| 大黑人交交护士xxxxhd | 麻豆传媒在线 | 中文字幕不卡在线 | 你懂的国产 | 欧美精品免费在线 | 97人妻精品一区二区三区 | 蜜臀久久精品 | 就要干就要操 | 亚洲码国产精品高潮在线 | 最新国产露脸在线观看 | 麻豆视频免费在线 | 欧美一区久久 | 日本在线国产 |