巧用Android圖片資源,打造更精致的APP
前言
由于android系統的開放性,以及IOS的相對封閉。第三方設備想要使用蘋果的OS,目前來說是不可能。所以,各廠商紛紛的投入了android的懷抱, android陣營也越來越強大,如今移動操作系統也就是android和ios的天下。也正是因為android的開放性,可定制度高,導致了各種屏幕尺寸、各種分辨率的android設備 鋪滿了手機、平板、智能電視、手表、盒子、智能硬件…等各種應用場景。
作為一名有逼格的程序猿,在面對如此眾多的尺寸和分辨率設備上,想要打造一款通吃的app,勢必是要花費一番功夫的。
drawable-xxx資源文件夾
還好google已經為我們想好了對策,為不同的分辨率提供不同的drawable資源。
先來看看微信的android客戶端,在圖片資源的使用
在res目錄下,以drawable開頭的文件夾占了一大半,后面以-hdpi、-land、-mdpi、-xhdpi…等文件夾以適配不同分辨率的機型。
可能有人會說,開發應用只用適配hdpi或者xhdpi就可以了,同樣可以顯示出來嘛!干嘛搞這么多版本,浪費空間,還麻煩!
如果是這樣的想法,那只能說你的應用受眾群體還沒達到一定程度,或者不追求細節的完美。對于高逼格的應用來說,哪怕一個像素的缺失,都是不完美。
廢話了這么多,先來看卡google官方對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.
獨立像素單位(Density-independent pixel (dp)
一個虛擬的單位,用來決定UI布局的。用來表述布局的尺寸或者位置。 dp是一個與屏幕密度有關系的單位,dp與像素的換算關系為 px = dp * (dpi / 160)。例如在240密度(dpi)的屏幕上一個dp等于1.5個像素。以后我們應該盡量使用dp單位布局,不要使用像素單位。這樣會使你的app屏幕兼容性更好
為了更直觀的感受,他們之間的區別,在1920x1080的手機屏幕上:
-
將同一張96×96像素的png圖片,分別放到hdpi、xhdpi、xxhdpi文件夾中,寬高均以wrap_content顯示
可以看到,適配較低drawable-dpi的資源圖片,顯示尺寸相對較大,但是清晰度差。而適配高dpi的圖片,顯示尺寸相對較小,但是銳度高,比較清晰!
-
將像素分別為72×72、96×96、144×144像素的圖片,分別放置于hdpi xhdpi xxhdpi文件夾中,寬高以wrap_content顯示效果。
可以看到,不同大小的圖片,放到不同的資源文件夾下,最終在屏幕上顯示的大小居然一致!但是144×144像素對應的圖片顯示的最精致和清晰。
到這里,應該能看出圖片資源與drawable文件夾對應的關系了。即使不使用高質量的圖片,仍然可在高分辨率的屏幕上進行對應的顯示,但是犧牲了控件顯示的精細度,屏幕dpi越高顯示越不清楚。如果一張高清晰度的照片,被放置在不恰當的drawable下也不能準確的還原應有的尺寸和清晰度。
對比IOS對圖片的定義,2倍圖即-xhdpi密度,3倍圖即-xxhdpi密度。
所以,想要讓應用中的icon顯示的更加精致,那就需要對應的配置不同像素的圖片。
使用wrap_content代替dp
很多人在處理帶圖片的icon的時候,會指定其大小,如:
<ImageView android:layout_width="45dp" android:layout_height="45dp" android:src="@drawable/icon_hdpi"/>
wrap_content 可理解為包裹內容,當控件被設置為 wrap_content 將會根據實際大小進行顯示。相比直接設置dip的方式,在圖片的顯示上或多或少的會存在縮放。也就會導致圖標會顯示的不夠精致。
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/voip_camerachat_xhdpi"/>
下面以應用中常用的tabbar,作為對比:(以1920×1080屏幕像素截圖)
- 圖1
- 圖2
圖1中的icon統一被設置了固定的大小24dp,同時只在drawable-xhdpi中進行圖片的適配。可以看出圖片被不同程度的拉伸,icon顯示較模糊。
圖2將icon的寬高均設置為 wrap_content ,同時在drawable-xxhdpi中進行了適配。圖2的icon銳度有所提高,因為wrap_content屬性的設置,本身icon圖片大小不同,導致icon顯示的大小不一致。所以完美的方案就是,需要UI提供尺寸均一的大圖片,適配到drawable-xxhdpi下.
相比微信的高清圖片資源,展現的精致效果:
SVG
Scalable Vector Graphics
在 Android 5.0(API 級別 21)及更高版本中,可定義矢量圖片,而且圖片可在不損失清晰度的情況下縮放。 只需一個資產文件即可創建一個矢量圖像,而位圖圖像則需要為每個屏幕密度提供一個資產文件。 如果要創建一個矢量圖像,在 XML 元素中定義形狀的詳情。
下列示例以定義一個矢量圖像:
在drawable文件夾下–>new–>vector Asset
可以選擇Material Icon,使用studio內置的icon資源。這里選擇了Local SVG file,使用自己定義的svg文件。
確定保存文件的位置。svg文件會導出為xml文件:
生成的moon.xml內容如下,path節點下的fillColor屬性,可以自定義顏色值。
<vectorxmlns: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的方式設置,而清晰度并未受影響。
SVG除了可以用在矢量圖片上,也可以在android上用來顯示精美的動畫效果。
有時間再對svg的生成,以及使用做更詳細的介紹。
來自:https://blog.maxleap.cn/archives/1226