亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android drawable微技巧,你不知道的drawable細節

2019-10-21 21:37:44
字體:
來源:轉載
供稿:網友

話說微技巧這個詞也是我自己發明的,因為drawable這個東西相信大家天天都在使用,每個人都再熟悉不過了,之所以叫微技巧就是對于這個我們再熟悉不過的技術,可能還有一些你所不知道的細節,那今天我們就來一起探究一下這些微小的細節吧。

大家都知道,在Android項目當中,drawable文件夾都是用來放置圖片資源的,不管是jpg、png、還是9.png,都可以放在這里。除此之外,還有像selector這樣的xml文件也是可以放在drawable文件夾下面的。

但是如果你現在使用Android Studio來新建一個項目,你會發現有如下的目錄結構:

Android,drawable,微技巧

嗯?怎么會有這么多mipmap開頭的文件夾,而且它們的命名規則和drawable文件夾很相似,也是hdpi、mdpi、xhdpi等等,并且里面還真是放的圖片,難道Android項目中放置圖片的位置已經改了?

對于剛剛從Eclipse轉向Android Studio的開發者們可能會對mipmap文件夾感到陌生,其實不用擔心,我們平時的編程習慣并不需要發生任何改變,因為mipmap文件夾只是用來放置應用程序的icon的,僅此而已。那么在此之前,我們都是把應用程序的icon圖標和普通的圖片資源一起放到drawable文件夾下的,這樣看上去就會比較雜亂,有的時候想從一堆的圖片資源里面找icon半天也找不到,而文件一多也就容易出現漏放的情況,但恰恰Android是極度建議我們在每一種分辨率的文件夾下面都放一個相應尺寸的icon的,因此將它們獨立出來專門放到mimap文件夾當中就很好地解決了這個問題。

另外,將icon放置在mipmap文件夾還可以讓我們程序的launcher圖標自動擁有跨設備密度展示的能力,比如說一臺屏幕密度是xxhdpi的設備可以自動加載mipmap-xxxhdpi下的icon來作為應用程序的launcher圖標,這樣圖標看上去就會更加細膩。

關于建議使用mipmap的原文可以參閱這篇文章:Getting Your Apps Ready for Nexus 6 and Nexus 9,當然你還是要科學上網的。

除此之外,對于每種密度下的icon應該設計成什么尺寸其實Android也是給出了最佳建議,icon的尺寸最好不要隨意設計,因為過低的分辨率會造成圖標模糊,而過高的分辨率只會徒增APK大小。建議尺寸如下表所示:

Android,drawable,微技巧

然后我們引用mipmap的方式和之前引用drawable的方式是完全一致的,在資源中就使用@mipmap/res_id,在代碼就使用R.mipmap.res_id。比如AndroidManifest.xml中就是這樣引用ic_launcher圖標的:

<application  android:allowBackup="true"  android:icon="@mipmap/ic_launcher"  android:label="@string/app_name"  android:supportsRtl="true"  android:theme="@style/AppTheme">  <activity android:name=".MainActivity">    <intent-filter>      <action android:name="android.intent.action.MAIN"/>      <category android:name="android.intent.category.LAUNCHER"/>    </intent-filter>  </activity></application>

好的,關于mimap的內容就講這么多,它并不是本篇文章的重點,接下來我們來真真正正看一些drawable的微技巧。

首先我準備了一張270*480像素的圖片:

Android,drawable,微技巧

將圖片命名為android_logo.png,然后把它放在drawable-xxhdpi文件夾下面。為什么要放在這個文件夾下呢?是因為我的手機屏幕的密度就是xxhdpi的。那么怎么才能知道自己手機屏幕的密度呢?你可以使用如下方法先獲取到屏幕的dpi值:

float xdpi = getResources().getDisplayMetrics().xdpi;float ydpi = getResources().getDisplayMetrics().ydpi;

其中xdpi代表屏幕寬度的dpi值,ydpi代表屏幕高度的dpi值,通常這兩個值都是近乎相等或者極其接近的,在我的手機上這兩個值都約等于403。那么403又代表著什么意思呢?我們直接參考下面這個表格就知道了:

Android,drawable,微技巧

從表中可以看出,403dpi是處于320dpi到480dpi之間的,因此屬于xxhdpi的范圍。

圖片放好了之后,下面我在布局文件中引用這張圖片,如下所示:

<?xml version="1.0" encoding="utf-8"?><LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  >  <ImageView    android:id="@+id/image"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:src="@drawable/android_logo"    /></LinearLayout>

在ImageView控件中指定加載android_logo這張圖,并把ImageView控件的寬高都設置成wrap_content,這樣圖片有多大,我們的控件就會有多大。

現在運行一下程序,效果如下所示:

Android,drawable,微技巧

由于我的手機分辨率是1080*1920像素的,而這張圖片的分辨率是270*480像素的,剛好是手機分辨率的四分之一,因此從上圖中也可以看出,android_logo圖片的寬和高大概都占據了屏幕寬高的四分之一左右,大小基本是比較精準的。

到目前為止一切都挺順利的,不是嗎?下面我們嘗試做點改變,將android_logo.png這張圖移動到drawable-xhdpi文件夾下,注意不是復制一份到drawable-xhdpi文件夾下,而是將圖片移動到drawable-xhdpi文件夾下,然后重新運行一下程序,效果如下圖所示:

Android,drawable,微技巧

嗯?怎么感覺圖片好像變大了一點,是錯覺嗎?

那么我們再將這張圖移動到drawable-mdpi文件夾下試試,重新運行程序,效果如下圖所示:

Android,drawable,微技巧

這次肯定不是錯覺了,這實在是太明顯了,圖片被放大了!

那么為什么好端端的一張圖片會被自動放大呢?而且這放大的比例是不是有點太過份了。其實不然,Android所做的這些縮放操作都是有它嚴格的規定和算法的??赡苡胁簧僮隽撕芏嗄闍ndroid的朋友都沒去留意過這些縮放的規則,因為這些細節太微小了,那么本篇的微技巧探索里面,我們就來把這些細節理理清楚。

首先解釋一下圖片為什么會被放大,當我們使用資源id來去引用一張圖片時,Android會使用一些規則來去幫我們匹配最適合的圖片。什么叫最適合的圖片?比如我的手機屏幕密度是xxhdpi,那么drawable-xxhdpi文件夾下的圖片就是最適合的圖片。因此,當我引用android_logo這張圖時,如果drawable-xxhdpi文件夾下有這張圖就會優先被使用,在這種情況下,圖片是不會被縮放的。但是,如果drawable-xxhdpi文件夾下沒有這張圖時, 系統就會自動去其它文件夾下找這張圖了,優先會去更高密度的文件夾下找這張圖片,我們當前的場景就是drawable-xxxhdpi文件夾,然后發現這里也沒有android_logo這張圖,接下來會嘗試再找更高密度的文件夾,發現沒有更高密度的了,這個時候會去drawable-nodpi文件夾找這張圖,發現也沒有,那么就會去更低密度的文件夾下面找,依次是drawable-xhdpi -> drawable-hdpi -> drawable-mdpi -> drawable-ldpi。 
總體匹配規則就是這樣,那么比如說現在終于在drawable-mdpi文件夾下面找到android_logo這張圖了,但是系統會認為你這張圖是專門為低密度的設備所設計的,如果直接將這張圖在當前的高密度設備上使用就有可能會出現像素過低的情況,于是系統自動幫我們做了這樣一個放大操作。

那么同樣的道理,如果系統是在drawable-xxxhdpi文件夾下面找到這張圖的話,它會認為這張圖是為更高密度的設備所設計的,如果直接將這張圖在當前設備上使用就有可能會出現像素過高的情況,于是會自動幫我們做一個縮小的操作。所以,我們可以嘗試將android_logo這張圖移動到drawable-xxxhdpi文件夾下面將會得到這樣的結果:

Android,drawable,微技巧

可以看到,現在圖片的寬和高都達到不手機屏幕的四分之一,說明圖片確實是被縮小了。

另外,剛才在介紹規則的時候提到了一個drawable-nodpi文件夾,這個文件夾是一個密度無關的文件夾,放在這里的圖片系統就不會對它進行自動縮放,原圖片是多大就會實際展示多大。但是要注意一個加載的順序,drawable-nodpi文件夾是在匹配密度文件夾和更高密度文件夾都找不到的情況下才會去這里查找圖片的,因此放在drawable-nodpi文件夾里的圖片通常情況下不建議再放到別的文件夾里面。

圖片被放大的原因現在我們已經搞清楚了,那么接下來還有一個問題,就是放大的倍數是怎么確定的呢?很遺憾,我沒有找到相關的文檔記載,但是我自己總結出了一個規律,這里跟大家分享一下。

還是看一下剛才的 dpi范圍-密度 表格:

Android,drawable,微技巧

可以看到,每一種密度的dpi范圍都有一個最大值,這個最大值之間的比例就是圖片會被系統自動放大的比例。 
口說無憑,下面我們來通過實例驗證一下,修改布局文件中的代碼,如下所示:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  >  <ImageView    android:id="@+id/image"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:src="@drawable/android_logo"    />  <Button    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="獲取圖片寬高"    android:onClick="buttonClick"    /></LinearLayout>

可以看到,我們添加了一個按鈕,并給按鈕注冊了一個點擊事件。然后在MainActivity中處理這個點擊事件:

public class MainActivity extends AppCompatActivity {  ImageView imageView;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    imageView = (ImageView) findViewById(R.id.image);  }  public void buttonClick(View view) {    Toast.makeText(this, "圖片寬度:" + imageView.getWidth(), Toast.LENGTH_SHORT).show();    Toast.makeText(this, "圖片高度:" + imageView.getHeight(), Toast.LENGTH_SHORT).show();  }}

這里在點擊事件中分別獲取圖片的寬和高并使用Toast提示出來。代碼修改這么多就可以了,然后將圖片移動到drawable-mdpi文件夾下。

下面我們來開始分析,mdpi密度的最高dpi值是160,而xxhdpi密度的最高dpi值是480,因此是一個3倍的關系,那么我們就可以猜測,放到drawable-mdpi文件夾下的圖片在xxhdpi密度的設備上顯示會被放大3倍。對應到android_logo這張圖,原始像素是270*480,放大3倍之后就應該是810*1440像素。下面運行程序,效果如下圖所示:

Android,drawable,微技巧

驗證通過。我們再來試驗一次,將圖片移動到drawable-xxxhdpi目錄下。xxxhdpi密度的最高dpi值是640,480是它的0.75倍,那么我們就可以猜測,放到drawable-xxxdpi文件夾下的圖片在xxhdpi密度的設備上顯示會被縮小至0.75倍。270*480的0.75倍應該是202.5*360,由于像素不支持小數點,那么四舍五入就應該是203*360像素。重新運行程序,效果如下圖所示:

Android,drawable,微技巧

再次驗證通過。如果你有興趣的話可以使用其它幾種dpi的drawable文件夾來試一試,應該都是適配這套縮放規則的。這樣我們就把圖片為什么會被縮放,以及具體的縮放倍數都搞明白了,drawable相關的細節你已經探究的非常細微了。

不過本篇文章到這里還沒結束,下面我準備講一講我們在實際開發當中會遇到的場景。根據Android的開發建議,我們在準備圖片資源時盡量應該給每種密度的設備都準備一套,這樣程序的適配性就可以達到最好。但實際情況是,公司的UI們通常就只會給一套圖片資源,想讓他們針對每種密度的設備都設計一套圖片資源,并且還是按照我們上面講的縮放比例規則來設計,就有點想得太開心了。沒錯,這個就是現實情況,那么在這種情況下,我們應該將僅有的這一套圖片資源放在哪個密度的文件夾下呢?

可以這樣來分析,根據我們剛才所學的內容,如果將一張圖片放在低密度文件夾下,那么在高密度設備上顯示圖片時就會被自動放大,而如果將一張圖片放在高密度文件夾下,那么在低密度設備上顯示圖片時就會被自動縮小。那我們可以通過成本的方式來評估一下,一張原圖片被縮小了之后顯示其實并沒有什么副作用,但是一張原圖片被放大了之后顯示就意味著要占用更多的內存了。因為圖片被放大了,像素點也就變多了,而每個像素點都是要占用內存的。

我們仍然可以通過例子來直觀地體會一下,首先將android_logo.png圖片移動到drawable-xxhdpi目錄下,運行程序后我們通過Android Monitor來觀察程序內存使用情況:

Android,drawable,微技巧

可以看到,程序所占用的內存大概穩定在19.45M左右。然后將android_logo.png圖片移動到drawable-mdpi目錄下,重新運行程序,結果如下圖所示:

Android,drawable,微技巧

現在漲到23.40M了,占用內存明顯增加了。如果你將圖片移動到drawable-ldpi目錄下,你會發現占用內存會更高。

通過這個例子同時也驗證了一個問題,我相信有不少比較有經驗的Android程序員可能都遇到過這個情況,就是當你的項目變得越來越大,有的時候加載一張drawable-hdpi下的圖片,程序就直接OOM崩掉了,但如果將這張圖放到drawable-xhdpi或drawable-xxhdpi下就不會崩掉,其實就是這個道理。

那么經過上面一系列的分析,答案自然也就出來了,圖片資源應該盡量放在高密度文件夾下,這樣可以節省圖片的內存開支,而UI在設計圖片的時候也應該盡量面向高密度屏幕的設備來進行設計。就目前來講,最佳放置圖片資源的文件夾就是drawable-xxhdpi。那么有的朋友可能會問了,不是還有更高密度的drawable-xxxhdpi嗎?干嗎不放在這里?這是因為,市面上480dpi到640dpi的設備實在是太少了,如果針對這種級別的屏幕密度來設計圖片,圖片在不縮放的情況下本身就已經很大了,基本也起不到節省內存開支的作用了。

好的,關于drawable微技巧方面的探索我們就講到這里,本篇文章中也是集合了不少我平時的工作經驗總結,以及通過做試驗所得出的一些結論,相信還是可以給大家帶來不少幫助的。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品在线网站| 中文字幕日韩精品在线| 国产精品高精视频免费| 国产精品精品视频一区二区三区| 欧美美女18p| 久久777国产线看观看精品| 欧美大片网站在线观看| 欧美日韩成人精品| 欧美电影免费观看电视剧大全| 亚洲成人精品视频| 45www国产精品网站| 欧洲一区二区视频| 青青a在线精品免费观看| 日韩av免费观影| 伊人久久久久久久久久久久久| 91亚洲国产精品| 精品国产一区久久久| 韩国精品久久久999| 在线日韩av观看| 欧美在线激情视频| 伊人久久久久久久久久久久久| 亚洲欧美日韩网| 亚洲国产成人精品久久| 久久久视频精品| 伊人久久综合97精品| 国产精品久久久久久久久男| 久久这里只有精品视频首页| 九九热这里只有精品免费看| 最好看的2019年中文视频| 在线精品高清中文字幕| 亚洲精品日韩欧美| 国产精品福利观看| 国产精品91一区| 欧美中文在线免费| 中文欧美日本在线资源| 中文字幕久精品免费视频| 日韩一区二区av| 亚洲欧美日韩天堂| 亚洲xxxxx电影| 91久久综合亚洲鲁鲁五月天| 久久99热精品| 久久久国产影院| 国产精品日韩在线一区| 久久精品国产一区二区电影| 91精品视频在线免费观看| 亚洲精品国精品久久99热一| 亚洲精品中文字幕有码专区| 日韩精品中文字幕在线| 欧美大片免费观看在线观看网站推荐| 欧美电影免费观看电视剧大全| 久久久噜久噜久久综合| 91精品国产综合久久男男| 91精品久久久久久| 亚洲日韩欧美视频| 九九热精品视频在线播放| 在线观看日韩专区| 亚洲一区二区日本| 久久综合国产精品台湾中文娱乐网| 91成人在线播放| 日韩欧美在线中文字幕| 久久精品国产欧美激情| 国产主播喷水一区二区| 97在线视频免费播放| 色偷偷9999www| 国产一区玩具在线观看| 欧美大片第1页| 久久伊人精品视频| 亚洲一区美女视频在线观看免费| 欧美视频不卡中文| 成人看片人aa| 91成人在线视频| 日韩经典中文字幕在线观看| 亚洲欧美成人网| 亚洲成人在线视频播放| 亚洲欧洲日产国码av系列天堂| 久青草国产97香蕉在线视频| 欧美精品电影免费在线观看| 色与欲影视天天看综合网| 日韩女在线观看| 国产精品高潮在线| 成人黄色av播放免费| 91精品视频免费观看| 欧美第一黄网免费网站| 福利视频一区二区| 2025国产精品视频| 国产视频丨精品|在线观看| 久久精品这里热有精品| 国产精品在线看| 亚洲最大av在线| 国产精品福利在线| 国产丝袜高跟一区| 欧美精品电影免费在线观看| 国产成人一区二| 88国产精品欧美一区二区三区| 高跟丝袜一区二区三区| 欧美中文字幕视频| 欧美极品少妇xxxxⅹ裸体艺术| 91爱视频在线| 免费av一区二区| 欧美激情精品久久久久久免费印度| 亚洲精品在线看| 色哟哟入口国产精品| 亚洲电影av在线| 日本不卡免费高清视频| 视频直播国产精品| 国产精品私拍pans大尺度在线| 国精产品一区一区三区有限在线| 国产精品久久久久久久久男| 日韩欧中文字幕| 欧美一级免费视频| 最近2019免费中文字幕视频三| 亚洲福利小视频| 欧美超级免费视 在线| 色777狠狠综合秋免鲁丝| 欧美裸体xxxx极品少妇| 中文字幕不卡在线视频极品| 日韩精品久久久久久福利| 日韩精品视频免费在线观看| 国产精品成人一区二区三区吃奶| 国产日韩欧美一二三区| 国产精品视频午夜| 2019最新中文字幕| 欧美有码在线观看视频| 青青久久av北条麻妃黑人| 欧美一级黑人aaaaaaa做受| 精品国模在线视频| 欧美性20hd另类| 久久久精品国产网站| 中文字幕在线日韩| 国产人妖伪娘一区91| 81精品国产乱码久久久久久| 亚洲国产欧美一区二区三区同亚洲| 日韩va亚洲va欧洲va国产| 4k岛国日韩精品**专区| 免费97视频在线精品国自产拍| 91精品在线观| 97免费在线视频| 亚洲欧美日韩国产中文| 欧美性猛交xxxx乱大交3| 欧美综合在线观看| 在线观看不卡av| 久久久久久国产精品三级玉女聊斋| 欧美肥臀大乳一区二区免费视频| 成人黄色短视频在线观看| 精品久久中文字幕久久av| 久久99国产精品久久久久久久久| **欧美日韩vr在线| 亚洲人成电影网站色…| 精品美女国产在线| 欧美激情视频免费观看| 国产欧美最新羞羞视频在线观看| 亚洲在线观看视频| 亚洲v日韩v综合v精品v| 欧美电影电视剧在线观看| 日韩中文字幕网站| 色偷偷偷综合中文字幕;dd| 欧美日韩国产精品专区| 久精品免费视频| 久久手机精品视频| 国产精品自在线| 亚洲一区二区三区在线免费观看| 久久久国产91| 在线亚洲国产精品网| 国产日韩av高清|