(推薦指數(shù)**)Dimension小故事

Dimension就是Android里的尺度標(biāo)準(zhǔn)了误债,其實(shí)呢,世界上本來(lái)有很多度量衡的妄迁,比如說(shuō)我們常用的公制度量衡寝蹈,還有英制度量衡,可能還有等等登淘。箫老。。

Android機(jī)型眾多黔州,分辨率耍鬓,尺寸阔籽,形狀(沒(méi)錯(cuò),Android系統(tǒng)還考慮過(guò)非規(guī)則顯示屏)各異牲蜀,這對(duì)于Android系統(tǒng)設(shè)計(jì)而言是一個(gè)挑戰(zhàn)笆制。對(duì)于一個(gè)實(shí)際的應(yīng)用程序來(lái)說(shuō),怎么知道具體的設(shè)備多長(zhǎng)多粗(*/ω\*)呢涣达。

確實(shí)呢在辆,這不太好解決哦。然而峭判,Google還是想到了一個(gè)辦法开缎。

Android面向應(yīng)用開(kāi)發(fā)呢,提出了一個(gè)叫做dip的長(zhǎng)度單位林螃;
而Android面向設(shè)備呢奕删,要求它聲明自己的xdpiydpi(注意,并不是dpi)疗认。

廢話不多說(shuō)完残,直接切入Android代碼了解下Dimension的那些事兒。主要的兩個(gè)嘉賓是來(lái)自android.util的TypedValue和DisplayMetrics横漏。這兩個(gè)類比較簡(jiǎn)單谨设,加起來(lái)代碼也才800+行,中間很大篇幅還是注釋缎浇。

TypedValue

TypedValue算是Android自己的用于Dimension換算的工具類扎拣,它有很多方法,其中的complexToDimensionPixelSize(int data, DisplayMetrics metrics)甚至在View的構(gòu)造方法中用于解析xml中的長(zhǎng)度值素跺,可見(jiàn)TypedValue的可靠程度二蓝。然而,我們把注意力放在它的另一個(gè)方法applyDimension(int unit, float value, DisplayMetrics metrics)指厌,這個(gè)方法的作用是把單位為px刊愚,dp,sp踩验,pt(什么鬼鸥诽?),in(什么鬼箕憾?)牡借,mm(什么鬼?)的長(zhǎng)度換算到以px為單位的長(zhǎng)度袭异,全部代碼如下:

    /**
     * Converts an unpacked complex data value holding a dimension to its final floating 
     * point value. The two parameters <var>unit</var> and <var>value</var>
     * are as in {@link #TYPE_DIMENSION}.
     *  
     * @param unit The unit to convert from.
     * @param value The value to apply the unit to.
     * @param metrics Current display metrics to use in the conversion -- 
     *                supplies display density and scaling information.
     * 
     * @return The complex floating point value multiplied by the appropriate 
     * metrics depending on its unit. 
     */
    public static float applyDimension(int unit, float value, DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }

這段代碼的可讀性已經(jīng)簡(jiǎn)單到了相當(dāng)?shù)某潭饶屏叶疾缓靡馑级嗫匆谎?///▽///)。然而,這確確實(shí)實(shí)是Android自己的代碼俊鱼,這時(shí)候,我又審視了一遍自己的態(tài)度畅买,并不是越花哨的代碼越好并闲,而是越好的代碼越“花哨”(看人家的注釋,眉飛色舞9刃摺)帝火。

這個(gè)方法推薦大家反復(fù)使用,因?yàn)橥瑯拥姆椒ㄎ覀冏约翰荒軐?xiě)得更簡(jiǎn)潔湃缎、更好犀填。

這個(gè)方法中最有內(nèi)涵的莫過(guò)于這一部分了啊:


Paste_Image.png

好的嗓违,到了這里九巡,除了pt,in蹂季,mm不明所以外差不多都懂了啊冕广,而上圖又都指向了另一個(gè)類DisplayMetrics。先草草地中斷下TypedValue的了解偿洁,看看DisplayMetrics是個(gè)什么鬼撒汉。

DisplayMetrics

關(guān)于DisplayMetrics呢,有人說(shuō)用了很多次了涕滋,可謂是花式編程不勝枚舉睬辐。然而,會(huì)用就算了解了嗎宾肺?(OS[注]:廢話溯饵,都會(huì)用了,還有啥好了解的)

筆者個(gè)人認(rèn)為爱榕,對(duì)于DisplayMetrics瓣喊,我們了解的再多可能也不見(jiàn)得夠啊。

剛才在TypedValue當(dāng)中黔酥,我們見(jiàn)識(shí)了DisplayMetrics的三個(gè)成員藻三,分別是density,scaledDensity和xdpi跪者。頭兩個(gè)大家可能也認(rèn)識(shí)棵帽,最后一個(gè)就蒙嗶了對(duì)不對(duì),啊~~

我們先簡(jiǎn)單的看一下渣玲,這幾個(gè)成員的代碼:

    /**
     * The logical density of the display.  This is a scaling factor for the
     * Density Independent Pixel unit, where one DIP is one pixel on an
     * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen), 
     * providing the baseline of the system's display. Thus on a 160dpi screen 
     * this density value will be 1; on a 120 dpi screen it would be .75; etc.
     *  
     * <p>This value does not exactly follow the real screen size (as given by 
     * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
     * the overall UI in steps based on gross changes in the display dpi.  For 
     * example, a 240x320 screen will have a density of 1 even if its width is 
     * 1.8", 1.3", etc. However, if the screen resolution is increased to 
     * 320x480 but the screen size remained 1.5"x2" then the density would be 
     * increased (probably to 1.5).
     *
     * @see #DENSITY_DEFAULT
     */
    public float density;
    /**
     * A scaling factor for fonts displayed on the display.  This is the same
     * as {@link #density}, except that it may be adjusted in smaller
     * increments at runtime based on a user preference for the font size.
     */
    public float scaledDensity;
    /**
     * The exact physical pixels per inch of the screen in the X dimension.
     */
    public float xdpi;

看完這仨的注釋逗概,我就奔潰了,真?越短越難啊忘衍。什么鬼逾苫?關(guān)鍵是代碼里怎么還有個(gè)ydpi:

    /**
     * The exact physical pixels per inch of the screen in the Y dimension.
     */
    public float ydpi;

這些東西究竟是干嘛的卿城?猴子請(qǐng)來(lái)的逗?jiǎn)裘矗?/p>

我抄起手邊的一臺(tái)手機(jī),洋洋灑灑碼了幾行代碼铅搓,讀了讀這幾個(gè)量瑟押,結(jié)果如下:

Paste_Image.png

圖中的density dpi是我看見(jiàn)DisplayMetrics里的成員densityDpi時(shí),不自禁打粗來(lái)的:

    /**
     * The screen density expressed as dots-per-inch.  May be either
     * {@link #DENSITY_LOW}, {@link #DENSITY_MEDIUM}, or {@link #DENSITY_HIGH}.
     */
    public int densityDpi;

反正都不懂星掰,不在乎多一個(gè)多望。

好了,到這里氢烘,我陷入了深深地思考“為什么我要了解這么深怀偷,這不是有病嗎?”然而答案是否定的播玖。

經(jīng)過(guò)了艱苦卓絕的努力和試驗(yàn)和思考后椎工,我得出了一些結(jié)論:

The End

人家說(shuō)結(jié)束不過(guò)是另一個(gè)開(kāi)始而已。嗯黎棠,確實(shí)呢晋渺,能看到這里首先謝謝各位的耐心。然而脓斩,一個(gè)好(壞木西?)消息是,我們終于要開(kāi)始(手動(dòng)斜眼)介紹Android應(yīng)對(duì)眾多形態(tài)各異的設(shè)備的手段了随静。八千。。

剛才的測(cè)試中燎猛,density和scaledDensity只是簡(jiǎn)單的dp恋捆,sp到px的換算比例而已,這是誰(shuí)都知道的東西重绷。它們都是3.0沸停,說(shuō)明1dp==3px,1sp==3px昭卓。但是愤钾,這個(gè)比例值3.0是如何決定的呢?嗯候醒,這就要看density的注釋中的那段話了能颁,它說(shuō)“如果densityDpi的值是160dpi的若干倍,那么density就是這個(gè)倍數(shù)了”(筆者英文不好倒淫,譯得比較糙伙菊,不服你打我啊ヽ(`⌒′)ノ)。

然而,density注釋里又有一些囈語(yǔ)“一個(gè)240*320的屏幕即便1.8寸或1.3寸寬镜硕,density也可以是1”运翼。這是怎么個(gè)情況呢?我一開(kāi)始也暈兴枯,后來(lái)發(fā)現(xiàn)了蹊蹺(此處陰險(xiǎn)表情)南蹂。請(qǐng)大家注意下咯,我文中測(cè)試的手機(jī)顯示densityDpi是480念恍,而我其實(shí)也測(cè)了另外一臺(tái)手機(jī)(此處陰險(xiǎn)表情again):

Paste_Image.png

這臺(tái)手機(jī)呢,也是480的densityDpi晚顷。然而峰伙,事實(shí)上,雖然兩臺(tái)手機(jī)的分辨率是一樣的(1920*1080)该默,尺寸卻分別是5.0寸和5.2寸瞳氓。到這里我想起了那句囈語(yǔ),又于是聯(lián)想到這么幾點(diǎn):

  1. 市場(chǎng)上確實(shí)存在分辨率相同但是尺寸有差異的手機(jī)栓袖,這些手機(jī)的densityDpi和density又恰巧一致匣摘;
  2. 對(duì)于程序猿而言,我們用到的density裹刮,scaledDensity和densityDpi很多音榜,用到的xdpi,ydpi很少捧弃;
  3. xdpi赠叼,ydpi的注釋表明它們才是實(shí)際的每英寸像素點(diǎn)數(shù)(這也是為啥兩個(gè)手機(jī)的xdpi,ydpi會(huì)有明顯差異的原因)违霞。

綜上嘴办,Google的意圖大概可以這么解釋:

  1. Google希望Android表達(dá)相同的內(nèi)容在5.0寸和5.2寸的手機(jī)上所呈現(xiàn)的比例是接近的,而又不能增加程序猿的工作量买鸽,那么涧郊,就呈現(xiàn)相同的dpi而程序猿看好了,這就是為什么densityDpi相同的原因眼五,因?yàn)樽彼遥琩ensityDpi相同就基本保證了內(nèi)容顯示比例的相同。
  2. 實(shí)際上的手機(jī)尺寸必然有差異弹砚,對(duì)于差異小的手機(jī)双仍,統(tǒng)一到同一densityDpi,差異大的話桌吃,就可以區(qū)分開(kāi)比如xxhdpi或hdpi的密度設(shè)定了(上述的兩個(gè)手機(jī)的xdpi朱沃,ydpi都是比較高的,歸到xhdpi(320dpi)不如歸到xxhdpi(480dpi),所以densityDpi都顯示為480了)逗物。
  3. 如果一定要顯示特定的物理長(zhǎng)度的話搬卒,那么,density顯然是做不到的翎卓,這時(shí)候xdpi和ydpi就能起到作用了契邀。這也是為什么xdpi可以計(jì)算出in(英寸),mm(毫米)和pt(point失暴,這是一個(gè)概念坯门,這個(gè)點(diǎn)的尺寸在不同手機(jī)是等長(zhǎng)的)。

可以想到逗扒,運(yùn)行在有相同密度的不同尺寸的手機(jī)上時(shí)古戴,Android面向程序猿是無(wú)差別的dp長(zhǎng)度,程序猿可以肆意地設(shè)計(jì)內(nèi)容矩肩,而不需要做什么適配现恼。但是由于densityDpi和xdpi,ydpi的實(shí)際差別黍檩,可以想到Android系統(tǒng)在把一堆dp設(shè)定的內(nèi)容映射為實(shí)際顯示的屏幕內(nèi)容的過(guò)程中叉袍,一定有基于densityDpi與xdpi,ydpi比例的換算過(guò)程刽酱。使得同一個(gè)顯示對(duì)象喳逛,在相同密度不同尺寸的手機(jī)上,擁有相同的高寬像素?cái)?shù)棵里,卻有不同的物理長(zhǎng)度艺配。

總結(jié),density衍慎,densityDpi转唉,scaledDensity是面向內(nèi)容的長(zhǎng)度單位(對(duì)程序猿友好,便于表達(dá)內(nèi)容)稳捆,xdpi赠法,ydpi是面向?qū)嶋H設(shè)備的參數(shù)(這是個(gè)連接了物理世界度量衡和Android度量衡的數(shù)值)。

PS:
我用上文的技術(shù)做了一個(gè)直尺的應(yīng)用乔夯,但是砖织,由于實(shí)際的手機(jī)xdpi和ydpi值居然不相等,所以末荐,顯示橫向的尺度相對(duì)來(lái)說(shuō)是比較準(zhǔn)確的侧纯,顯示縱向的尺度就不太準(zhǔn)了(因?yàn)槲矣肨ypedValue中MM的單位獲取長(zhǎng)度,而這個(gè)方法又是采用了xdpi來(lái)實(shí)現(xiàn)的甲脏,如果縱向繪制尺子的話眶熬,實(shí)際上得用ydpi來(lái)實(shí)現(xiàn)才對(duì)妹笆,不該用xdpi來(lái)做,除非xdpi和ydpi是相等的娜氏,而ydpi和xdpi不相等就會(huì)導(dǎo)致縱向繪制出現(xiàn)偏差拳缠,這個(gè)問(wèn)題后續(xù)可改正)。

注:
OS是overlapping sound的簡(jiǎn)稱贸弥,即內(nèi)心獨(dú)白窟坐,不是operating system!绵疲!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哲鸳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盔憨,更是在濱河造成了極大的恐慌帕胆,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件般渡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡芙盘,警方通過(guò)查閱死者的電腦和手機(jī)驯用,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)儒老,“玉大人蝴乔,你說(shuō)我怎么就攤上這事⊥苑” “怎么了薇正?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)囚衔。 經(jīng)常有香客問(wèn)我挖腰,道長(zhǎng),這世上最難降的妖魔是什么练湿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任猴仑,我火速辦了婚禮,結(jié)果婚禮上肥哎,老公的妹妹穿的比我還像新娘辽俗。我一直安慰自己,他們只是感情好篡诽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布崖飘。 她就那樣靜靜地躺著,像睡著了一般杈女。 火紅的嫁衣襯著肌膚如雪朱浴。 梳的紋絲不亂的頭發(fā)上吊圾,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音赊琳,去河邊找鬼街夭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛躏筏,可吹牛的內(nèi)容都是我干的板丽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趁尼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼埃碱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起酥泞,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤砚殿,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后芝囤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體似炎,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年悯姊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了羡藐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悯许,死狀恐怖仆嗦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情先壕,我是刑警寧澤瘩扼,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站垃僚,受9級(jí)特大地震影響集绰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谆棺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一倒慧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧包券,春花似錦纫谅、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至侍郭,卻和暖如春询吴,著一層夾襖步出監(jiān)牢的瞬間掠河,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工猛计, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唠摹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓奉瘤,卻偏偏與公主長(zhǎng)得像勾拉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盗温,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,528評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)藕赞、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,033評(píng)論 4 62
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程卖局,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 王國(guó)維把詩(shī)講透了斧蜕,他說(shuō)詩(shī)要論境界。而我所讀的詩(shī)砚偶,凡是好詩(shī)批销,必有一點(diǎn),是為真染坯。 真摯的感情均芽,真摯的思想,不是為寫(xiě)詩(shī)而...
    HandsomeKing閱讀 195評(píng)論 0 0
  • 眼前是一望無(wú)際的金黃酒请,輕柔的風(fēng)掠過(guò)一片稻田,遠(yuǎn)處隱約還能看到割麥人隨著麥浪涌動(dòng)的身影鸣个。孤零零的我站在這里羞反,有...
    思似柳萬(wàn)絳閱讀 314評(píng)論 0 0