問題
今天無意中發現了一個問題,通過Bitmap的getWidth和getHeight方法獲取到的圖片尺寸與實際的尺寸(1920*1080)不一致,后來更進一步發現,把這張圖片分別放在raw、drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi、drawable-xxxhdpi時,通過以上兩個方法獲取到的尺寸也都不一致。
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img_mac_os_x); if (bitmap != null) { Log.i("xp.chen", "decode bitmap width: "+bitmap.getWidth()+", bitmap height: "+bitmap.getHeight()); }
下面是把圖片分別放在raw、drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi、drawable-xxxhdpi時,通過Bitmap的getWidth()/getHeight()分別獲取到的尺寸:
raw:I/xp.chen: decode bitmap width: 7680, bitmap height: 4320
drawable-mdpi:I/xp.chen: decode bitmap width: 7680, bitmap height: 4320
drawable-hdpi:I/xp.chen: decode bitmap width: 5120, bitmap height: 2880
drawable-xhdpi:I/xp.chen: decode bitmap width: 3840, bitmap height: 2160
drawable-xxhdpi:I/xp.chen: decode bitmap width: 2560, bitmap height: 1440
drawable-xxxhdp:I/xp.chen: decode bitmap width: 1920, bitmap height: 1080
為什么會這樣
首先要知道的是,除了raw文件夾,上述的其它文件夾主要是用來適配不同屏幕的顯示密度的,放在不同文件夾里等於是告訴系統,我這張圖片是針對哪一種顯示密度的設備,如果圖片放置的文件夾與實際運行的設備密度不一致,那么系統會對這張圖片進行放大或縮小。比如:我把圖片放置在xhdpi(dpi是320)里面,但是我實際運行的設備是640,xxxhdpi里又沒有放置任何圖片,那么這個時候系統就會對放置在xhdpi里的同名圖片進行縮放。
在屏幕dpi為160時,1dp = 1px,也就是說如果運行設備的屏幕的dpi是160時,圖片是可以1:1正常顯示的,查看當前屏幕的dpi和density可以通過下列API:
float density = getResources().getDisplayMetrics().density; int densityDpi = getResources().getDisplayMetrics().densityDpi;
通過測試,我手機的dpi為640,density是4,也就是說當我把圖片放在xxxhdpi里時,圖片可以正常匹配,系統不會做任何處理,所以上面放在xxxhdpi時,運行的Log是正確的,剛好是1920*1080,那放置到其它的文件夾里的尺寸是如何計算的呢?個人猜測應該是這樣:當放置在
drawable-mdpi時,該文件夾對應的dpi是160,density是1,實際屏幕dpi是640,密度是4,不符合要求,放大4倍 ,(7680*4320);
drawable-hdpi時,該文件夾對應的dpi是240,density是1.5,實際屏幕dpi是640,密度是4,不符合要求,放大2.666 (4/1.5) 倍, (5120*2880);
drawable-xhdpi時,該文件夾對應的dpi是320,density是2,實際屏幕dpi是640,密度是4,不符合要求,放大2 (4/2) 倍, (3840*2160);
drawable-xxhdpi時,該文件夾對應的dpi是480,density是3,實際屏幕dpi是640,密度是4,不符合要求,放大1.333 (4/3) 倍, (2560*1440);
drawable-xxxhdpi時,該文件夾對應的dpi是640,density是4,實際屏幕dpi是640,密度是4,符合要求,正常顯示, (1920*1080);
因此導致了使用BitmapFactory在decode圖片時發生了上述的差異,那么是否有什么途徑可以保證decode圖片時,得到的圖片尺寸與實際的圖片尺寸相一致呢?這里有兩種方法:
第一種方法,如果僅僅是為了獲取圖片的尺寸,不需要獲取其對應的Bitmap,可以通過下列方式:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img_mac_os_x, options); Log.i("xp.chen", "decode bitmap width: "+options.outWidth+", bitmap height: "+options.outHeight);
這里通過 options.outWidth 和 options.outHeight 拿到的就是圖片實際的寬高,經測試剛好是1920*1080,注意這里返回的bitmap對象是NULL。
第二種方法,不僅僅是為了要拿到圖片的尺寸,也需要拿到對應的Bitmap,可以通過下列方式:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img_mac_os_x, options); if (bitmap != null) { Log.i("xp.chen", "decode bitmap width: "+bitmap.getWidth()+", bitmap height: "+bitmap.getHeight()); }
設置 options.inScaled 為false,等於告訴系統,不要對該圖片進行縮放,通過這種方法拿到的寬高也是1920*1080。