術(shù)語(yǔ)解析
像素(Pixel):屏幕繪制的最小單位,無(wú)論在開(kāi)發(fā)時(shí)使用什么尺寸單位,最終都需要轉(zhuǎn)為像素。下簡(jiǎn)稱(chēng)px。
密度無(wú)關(guān)像素(Density independent pixel,簡(jiǎn)稱(chēng)dip/dp):簡(jiǎn)單來(lái)說(shuō)是一個(gè)物理尺寸單位,寬高具有相同dp值的widget在不同屏幕上的物理尺寸是相同的(但實(shí)際上可能是近似,因?yàn)锳ndroid設(shè)備使用廣義密度而不是真實(shí)密度,下面會(huì)講述),和屏幕尺寸以及分辨率沒(méi)有關(guān)系。下簡(jiǎn)稱(chēng)dp。
屏幕大小(Screen size):如果沒(méi)特別說(shuō)明,屏幕大小是指其對(duì)角線長(zhǎng)度,單位為英寸。
屏幕密度(Dots per inch,簡(jiǎn)稱(chēng)Dpi):屏幕每英寸上有多少個(gè)px點(diǎn)。計(jì)算公式:sqrt(widthPixels *widthPixels + heightPixels * heightPixels) / screenSize
為什么Android要使用dp而不是傳統(tǒng)的px作為widget長(zhǎng)度單位?
Android的主要交互是觸控,而人的手指頭大小變化范圍比較小。如果以px作為長(zhǎng)度單位,在一個(gè)大屏幕低分屏上可以正常觸控的按鈕,換到一個(gè)一個(gè)小屏幕高分屏上可能很難按到(因?yàn)槲锢沓叽缱冃×?,手指頭可不能跟著變?。?,所以需要使用一個(gè)和屏幕參數(shù)無(wú)關(guān)的單位,維持交互控件的物理尺寸。
獲取屏幕分辨率
方式1:
# 像素寬
int width = context.getResources().getDisplayMetrics().widthPixels;
# 像素高
int height = context.getResources().getDisplayMetrics().heightPixels;
方式2:
//獲取手機(jī)屏幕分辨率的類(lèi)
private DisplayMetrics displayMetrics;
displayMetrics = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
# 像素寬
int width = displayMetrics.widthPixels;
# 像素高
int height = displayMetrics.heightPixels;
注意:getMetrics()和getRealMetrics()
getMetrics()這種方法廣為流傳,百度一下但是這種方法有一個(gè)弊端,具體原因?yàn)間etMetrics()獲取到的屏幕信息在android4.4后會(huì)忽略底部的虛擬按鍵的高度。所以此時(shí)該用getRealMetrics()。
getRealMetrics()和getMetrics()獲取到的屏幕信息差別只在于widthPixels或heightPixels的值是否去除虛擬鍵所占用的像素,和是否全屏和沉浸模式無(wú)關(guān)。
具體到我的問(wèn)題就是用getMetrics()獲取到的是1280x672,而用getRealMetrics()獲取到的就是正確的1280x720。2個(gè)方法僅僅相差一個(gè)Real,然而結(jié)果卻完全不同,而網(wǎng)絡(luò)上大部分都是前者,僅僅是今天我才發(fā)現(xiàn)有一篇文章提到了getRealMetrics(),并解釋了二者的區(qū)別。
術(shù)語(yǔ)解析2
廣義密度(Generalized density):從上面屏幕密度的計(jì)算公式可知,通過(guò)更改分辨率或者屏幕尺寸可以搞出無(wú)數(shù)種真實(shí)屏幕密度,不同的屏幕密度意味著,繪制相同的物理尺寸的widget要使用的px數(shù)是不一樣的。假定要讓一張圖片在10個(gè)屏幕密度不一樣的設(shè)備上以相同物理尺寸顯示(不使用動(dòng)態(tài)縮放),那么開(kāi)發(fā)者需要準(zhǔn)備10張px面積不同的圖片以獲得最佳顯示效果,顯然這是不可接受的。對(duì)此Android的解決方案是犧牲widget在物理尺寸上的一致性,在不同密度的設(shè)備上widget物理尺寸只是近似而不是相同,換取適配工作量的降低。具體的做法:將一定范圍的屏幕密度的設(shè)備視為一個(gè)特定的密度,比如屏幕密度在240左右的設(shè)備視為高密度(hdpi),在320左右的視為超高密度(xhdpi)等。注意的是,在兩個(gè)廣義密度之間并沒(méi)有明確的邊界值,屏幕具體屬于何種廣義密度由系統(tǒng)決定而不是由真實(shí)密度決定,系統(tǒng)在進(jìn)行繪制換算時(shí)也只會(huì)使用廣義密度。下簡(jiǎn)稱(chēng)density。
dp縮放因子:每個(gè)dp對(duì)應(yīng)多少個(gè)px。這個(gè)值在Android系統(tǒng)的變量命名也是density,但實(shí)際上和屏幕密度是兩回事,所以我稱(chēng)之為scale factor。先說(shuō)說(shuō)這個(gè)值的來(lái)源,Android系統(tǒng)規(guī)定在廣義密度為160(mdpi)的設(shè)備上1dp=1px,這是一個(gè)定值。對(duì)于密度為320(xhdpi)的設(shè)備,后者每英寸像素點(diǎn)為前者的320/160=2倍。在前者使用1個(gè)像素繪制的物體,在后者需要使用4個(gè)像素(2*2)繪制,對(duì)于用戶(hù)來(lái)說(shuō)它的物理大小才是相同的,那么顯然,對(duì)于后者來(lái)講1dp=2px。換句話說(shuō),dp縮放因子 = density / 160,同時(shí)可以推出公式px = dp * dp縮放因子 = dp * (density / 160) 。下簡(jiǎn)稱(chēng)factor。
px-dp 縮放因子(像素密度)
方式1:
float density = context.getResources().getDisplayMetrics().density;
方式2:
displayMetrics = new DisplayMetrics();
// dp縮放因子
float density = displayMetrics.density;