巧用Android圖片資源,打造更精致的APP
前言
由于android系統(tǒng)的開放性,以及IOS的相對(duì)封閉。第三方設(shè)備想要使用蘋果的OS,目前來(lái)說(shuō)是不可能。所以,各廠商紛紛的投入了android的懷抱,
android陣營(yíng)也越來(lái)越強(qiáng)大,如今移動(dòng)操作系統(tǒng)也就是android和ios的天下。也正是因?yàn)閍ndroid的開放性,可定制度高,導(dǎo)致了各種屏幕尺寸、各種分辨率的android設(shè)備
鋪滿了手機(jī)、平板、智能電視、手表、盒子、智能硬件...等各種應(yīng)用場(chǎng)景。
作為一名有逼格的程序猿,在面對(duì)如此眾多的尺寸和分辨率設(shè)備上,想要打造一款通吃的app,勢(shì)必是要花費(fèi)一番功夫的。
drawable-xxx資源文件夾
還好google已經(jīng)為我們想好了對(duì)策,為不同的分辨率提供不同的drawable資源。
先來(lái)看看微信的android客戶端,在圖片資源的使用
在res目錄下,以drawable開頭的文件夾占了一大半,后面以-hdpi、-land、-mdpi、-xhdpi...等文件夾以適配不同分辨率的機(jī)型。
可能有人會(huì)說(shuō),開發(fā)應(yīng)用只用適配hdpi或者xhdpi就可以了,同樣可以顯示出來(lái)嘛!干嘛搞這么多版本,浪費(fèi)空間,還麻煩!
如果是這樣的想法,那只能說(shuō)你的應(yīng)用受眾群體還沒(méi)達(dá)到一定程度,或者不追求細(xì)節(jié)的完美。對(duì)于高逼格的應(yīng)用來(lái)說(shuō),哪怕一個(gè)像素的缺失,都是不完美。
廢話了這么多,先來(lái)看卡google官方對(duì)dp的定義
Density-independent pixel (dip)
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
獨(dú)立像素單位(Density-independent pixel (dp)
一個(gè)虛擬的單位,用來(lái)決定UI布局的。用來(lái)表述布局的尺寸或者位置。
dp是一個(gè)與屏幕密度有關(guān)系的單位,dp與像素的換算關(guān)系為 px = dp * (dpi / 160)。例如在240密度(dpi)的屏幕上一個(gè)dp等于1.5個(gè)像素。以后我們應(yīng)該盡量使用dp單位布局,不要使用像素單位。這樣會(huì)使你的app屏幕兼容性更好
將同一張96x96像素的png圖片,分別放到hdpi、xhdpi、xxhdpi文件夾中,寬高均以wrap_content顯示
- 
- 可以看到,適配較低drawable-dpi的資源圖片,顯示尺寸相對(duì)較大,但是清晰度差。而適配高dpi的圖片,顯示尺寸相對(duì)較小,但是銳度高,比較清晰!
將像素分別為72x72、96x96、144x144像素的圖片,分別放置于hdpi xhdpi xxhdpi文件夾中,寬高以wrap_content顯示效果。
- 
- 可以看到,不同大小的圖片,放到不同的資源文件夾下,最終在屏幕上顯示的大小居然一致!但是144x144像素對(duì)應(yīng)的圖片顯示的最精致和清晰。
到這里,應(yīng)該能看出圖片資源與drawable文件夾對(duì)應(yīng)的關(guān)系了。即使不使用高質(zhì)量的圖片,仍然可在高分辨率的屏幕上進(jìn)行對(duì)應(yīng)的顯示,但是犧牲了控件顯示的精細(xì)度,屏幕dpi越高顯示越不清楚。如果一張高清晰度的照片,被放置在不恰當(dāng)?shù)膁rawable下也不能準(zhǔn)確的還原應(yīng)有的尺寸和清晰度。
對(duì)比IOS對(duì)圖片的定義,2倍圖即-xhdpi密度,3倍圖即-xxhdpi密度。
所以,想要讓應(yīng)用中的icon顯示的更加精致,那就需要對(duì)應(yīng)的配置不同像素的圖片。
使用wrap_content代替dp
很多人在處理帶圖片的icon的時(shí)候,會(huì)指定其大小,如:
- <ImageView
- android:layout_width="45dp"
- android:layout_height="45dp"
- android:src="@drawable/icon_hdpi" />
wrap_content可理解為包裹內(nèi)容,當(dāng)控件被設(shè)置為wrap_content將會(huì)根據(jù)實(shí)際大小進(jìn)行顯示。相比直接設(shè)置dip的方式,在圖片的顯示上或多或少的會(huì)存在縮放。也就會(huì)導(dǎo)致圖標(biāo)會(huì)顯示的不夠精致。
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/voip_camerachat_xhdpi" />
下面以應(yīng)用中常用的tabbar,作為對(duì)比:(以1920x1080屏幕像素截圖)
圖1
圖2
圖1中的icon統(tǒng)一被設(shè)置了固定的大小24dp,同時(shí)只在drawable-xhdpi中進(jìn)行圖片的適配??梢钥闯鰣D片被不同程度的拉伸,icon顯示較模糊。
圖2將icon的寬高均設(shè)置為wrap_content,同時(shí)在drawable-xxhdpi中進(jìn)行了適配。圖2的icon銳度有所提高,因?yàn)閣rap_content屬性的設(shè)置,本身icon圖片大小不同,導(dǎo)致icon顯示的大小不一致。所以完美的方案就是,需要UI提供尺寸均一的大圖片,適配到drawable-xxhdpi下.
相比微信的高清圖片資源,展現(xiàn)的精致效果:
SVG
Scalable Vector Graphics
在 Android 5.0(API 級(jí)別 21)及更高版本中,可定義矢量圖片,而且圖片可在不損失清晰度的情況下縮放。 只需一個(gè)資產(chǎn)文件即可創(chuàng)建一個(gè)矢量圖像,而位圖圖像則需要為每個(gè)屏幕密度提供一個(gè)資產(chǎn)文件。 如果要?jiǎng)?chuàng)建一個(gè)矢量圖像,在 <vector> XML 元素中定義形狀的詳情。
下列示例以定義一個(gè)矢量圖像:
在drawable文件夾下-->new-->vector Asset
可以選擇Material Icon,使用studio內(nèi)置的icon資源。這里選擇了Local SVG file,使用自己定義的svg文件。
確定保存文件的位置。svg文件會(huì)導(dǎo)出為xml文件:
生成的moon.xml內(nèi)容如下,path節(jié)點(diǎn)下的fillColor屬性,可以自定義顏色值。
- <vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="22.0"
- android:viewportWidth="22.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M16,10l0.8,-3.2L20,6l-3.2,-0.8L16,2l-0.8,3.2L12,6l3.2,0.8L16,10zM6,8c0,-2.17 0.867,-4.134 2.269,-5.575C4.634,3.581 2,6.982 2,11c0,4.971 4.029,9 9,9c4.018,0 7.419,-2.634 8.575,-6.269C18.134,15.133 16.17,16 14,16C9.582,16 6,12.418 6,8z" />
- </vector>
layout中使用和普通圖片使用相同
- <ImageView
- android:layout_width="40dp"
- android:layout_height="40dp"
- android:src="@drawable/moon" />
界面顯示效果:
控件的寬高可以任意以dp的方式設(shè)置,而清晰度并未受影響。
SVG除了可以用在矢量圖片上,也可以在android上用來(lái)顯示精美的動(dòng)畫效果。
有時(shí)間再對(duì)svg的生成,以及使用做更詳細(xì)的介紹。