Android开发---图片渲染问题----真的很严重
Bitmap和Drawable淺談
一、概念區(qū)別
Bitmap - 稱作位圖,一般位圖的文件格式后綴為bmp,當(dāng)然編碼器也有很多如RGB565、RGB8888。作為一種逐像素的顯示對(duì)象執(zhí)行效率高,但是缺點(diǎn)也很明顯存儲(chǔ)效率低。我們理解為一種存儲(chǔ)對(duì)象比較好。
Drawable - 作為Android平下通用的圖形對(duì)象,它可以裝載常用格式的圖像,比如GIF、PNG、JPG,當(dāng)然也支持BMP,當(dāng)然還提供一些高級(jí)的可視化對(duì)象,比如漸變、圖形等。
Canvas - 名為畫布,我們可以看作是一種處理過(guò)程,使用各種方法來(lái)管理Bitmap、GL或者Path路徑,同時(shí)它可以配合Matrix矩陣類給圖像做旋轉(zhuǎn)、縮放等操作,同時(shí)Canvas類還提供了裁剪、選取等操作。
Paint - 我們可以把它看做一個(gè)畫圖工具,比如畫筆、畫刷。他管理了每個(gè)畫圖工具的字體、顏色、樣式。
二、Android讀取不同位置(drawable,asset,SDCard)的圖片資源
方式一:
已將圖片保存到drawable目錄下,通過(guò)圖片id獲得Drawable或者Bitmap,此方式最常用。(若只知道圖片的名稱,還可以通過(guò)圖片的名稱獲得圖片的id)
(1)通過(guò)圖片id獲得Drawable
Drawable drawable=getResource().getDrawable(R.drawable.xxx);
(2)通過(guò)圖片id獲得Bitmap
Resource res=gerResource();
Bitmap bitmap=BitmapFactory.decodeResource(res, id);
(3)通過(guò)圖片的名稱獲得圖片的id(兩種方法)
int id =res.getIdentifier(name, defType, defPackage); //name:圖片的名,defType:資源類型(drawable,string。。。),defPackage:工程的包名
Drawable drawable=getResource().getDrawable(id);
方式二:
已將圖片保存到assest目錄下,知道圖片的名稱,通過(guò)inputstream獲得圖片Drawabl
或者 Bitmap
AssetManager asm=getAssetMg();
InputStream is=asm.open(name);//name:圖片的名稱
(1)獲得Drawable
Drawable da = Drawable.createFromStream(is, null);
(2)獲得Bitmap
Bitmap bitmap=BitmapFactory.decodeStream(is);
方式三: 圖片保存在sdcard,通過(guò)圖片的路徑h
/圖片路徑
String imgFilePath = Environment.getExternalStorageDirectory().toString()
+ “/DCIM/device.png”;
(1)文件輸入流
fis = new FileInputStream(new File(imgFilePath));//文件輸入流
Bitmap bmp = BitmapFactory.decodeStream(fis);
(2)
ImageView iv = (ImageView) findViewById(R.id.image);
Bitmap bit = BitmapFactory.decodeFile("/sdcard/android.bmp");
iv.setImageBitmap(bit);
iv.setImageDrawable(Drawable.createFromPath(new File(Environment.getExternalStorageDirectory(), "camera.jpg").getAbsolutePath()));
三、Drawable、Bitmap、byte[]之間的轉(zhuǎn)換
1)? ?? ?Drawble轉(zhuǎn)Bitmap
public static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = Bitmap
.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
//canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
2)?從資源中獲取Bitmap
Resources res=getResources();
Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.pic);
?
3) Bitmap?→?byte[]
private byte[] Bitmap2Bytes(Bitmap bm){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
4) byte[]?→?Bitmap
private Bitmap Bytes2Bimap(byte[] b){
if(b.length!=0){
return BitmapFactory.decodeByteArray(b, 0, b.length);
}
else {
return null;
}
}
//將assets文件中資源取出,并將圖片從bitmap轉(zhuǎn)換成drawable格式
public static Drawable getDrawableFromAssetFile(Context context,String fileName){
Bitmap image = null;
BitmapDrawable drawable=null;
try{
AssetManager am = context.getAssets();
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
drawable= new BitmapDrawable(context.getResources(), image);
is.close();
}catch(Exception e){
}
return drawable;
}
四、APK程序里的drawable—hdpi、drawable—mdpi、drawable—ldpi詳解
自己DIY過(guò)APK程序的達(dá)人們肯定會(huì)對(duì)于android中放置圖片的地方drawable—hdpi、drawable—mdpi、drawable—ldpi這三個(gè)感到好奇。肯定心里會(huì)想,放在哪一個(gè)都行,只要是在android中的res目錄下的drawable中就行,系統(tǒng)會(huì)自己找到。有心的朋友肯定會(huì)他把弄個(gè)究竟。我以前對(duì)drawable—hdpi、drawable—mdpi、drawable—ldpi這三個(gè)也了解了一下,但是只是字面上的,沒有真正理解透徹,到今天我才算有稍深點(diǎn)的理解。drawable—hdpi看他的單詞名肯定知道他是放置高分辨率的圖片,drawable—mdpi放置中等分辨率的圖片,drawable—ldpi放置低分辨率的圖片。大部分人都把的圖片放在drawable—mdpi中。起初我認(rèn)為隨便將圖片放置在三個(gè)當(dāng)中的任意一個(gè)都行,但是今天我知道了。在分辨率低于480*800時(shí)把圖片放在drawable—mdpi中是不會(huì)有什么影響,但是當(dāng)分辨率為420*800或高于它時(shí)就會(huì)出問題了。你的手機(jī)屏幕有那么大但是他會(huì)將圖片拉伸,當(dāng)加載圖片后讓你感覺該屏幕沒有實(shí)際的大小,而如果將圖片放到drawable—hdpi中則該問題就不會(huì)存在了。比如手機(jī)屏幕的大小為420*800如果你將圖片放在drawable—mdpi中,那么你就要準(zhǔn)備一張340*525分辨率的圖片,今天我就遇到了,很是讓我郁悶當(dāng)時(shí)我還以為屏幕有誤差,查閱其他代碼后才發(fā)現(xiàn)自己把圖片放錯(cuò)了位置。
1)不同的layout
Android手機(jī)屏幕大小不一,有480×320, 640×360, 800×480.怎樣才能讓App自動(dòng)適應(yīng)不同的屏幕呢?
其實(shí)很簡(jiǎn)單,只需要在res目錄下創(chuàng)建不同的layout文件夾,比如layout-640×360,layout-800×480,所有的layout文件在編譯之后都會(huì)寫入R.java里,而系統(tǒng)會(huì)根據(jù)屏幕的大小自己選擇合適的layout進(jìn)行使用。
2)hdpi、mdpi、ldpi
在之前的版本中,只有一個(gè)drawable,而2.1版本中有drawable-mdpi、drawable-ldpi、drawable-hdpi三個(gè),這三個(gè)主要是為了支持多分辨率。
drawable- hdpi、drawable- mdpi、drawable-ldpi的區(qū)別:
(1)drawable-hdpi里面存放高分辨率的圖片,如WVGA (480×800),FWVGA (480×854)
(2)drawable-mdpi里面存放中等分辨率的圖片,如HVGA (320×480)
(3)drawable-ldpi里面存放低分辨率的圖片,如QVGA (240×320)
系統(tǒng)會(huì)根據(jù)機(jī)器的分辨率來(lái)分別到這幾個(gè)文件夾里面去找對(duì)應(yīng)的圖片。
在開發(fā)程序時(shí)為了兼容不同平臺(tái)不同屏幕,建議各自文件夾根據(jù)需求均存放不同版本圖片。
3)橫屏豎屏
以下步驟是網(wǎng)上流傳的,不過(guò)我自己之前是通過(guò)圖形化界面實(shí)現(xiàn)這個(gè)配置,算是殊途同歸,有空我會(huì)把圖片貼上來(lái)。
還要說(shuō)明一點(diǎn):每個(gè)activity都有這個(gè)屬性screenOrientation,每個(gè)activity都需要設(shè)置,可以設(shè)置為豎屏(portrait),也可以設(shè)置為無(wú)重力感應(yīng)(nosensor)。
要讓程序界面保持一個(gè)方向,不隨手機(jī)方向轉(zhuǎn)動(dòng)而變化的處理辦法:
在AndroidManifest.xml里面配置一下就可以了。加入這一行android:screenOrientation=”landscape”。
例如(landscape是橫向,portrait是縱向):
?
對(duì)于Android游戲開發(fā)我們不得不像iPhone那樣思考兼容?Android平板電腦,對(duì)于蘋果要考慮iPad、iPhone 3GS和iPhone 4等屏幕之間的兼容性,對(duì)于幾乎所有的分辨率總結(jié)了大約超過(guò)20中粉筆阿女郎的大小和對(duì)應(yīng)關(guān)系,對(duì)于開發(fā)Android游戲而言可以考慮到未來(lái)的3.0以及很多平板電腦的需要。
常規(guī)的我們可能只考慮QVGA,HVGA,WVGA,FWVGA和DVGA,但是拋去了手機(jī)不談,可能平板使用類似WSVGA的1024×576以及WXGA的1280×768等等。
QVGA = 320 * 240;
WQVGA = 320 * 480;
WQVGA2 = 400 * 240;
WQVGA3 = 432 * 240;
HVGA = 480 * 320;
VGA = 640 * 480;
WVGA = 800 * 480;
WVGA2 = 768 * 480;
FWVGA = 854 * 480;
DVGA = 960 * 640;
PAL = 576 * 520;
NTSC = 486 * 440;
SVGA = 800 * 600;
ps:
Android開發(fā)過(guò)程中,遇到的這個(gè)問題真的把人搞死了,客戶一直不爽那個(gè)啟動(dòng)圖標(biāo),換了好幾個(gè)手機(jī)測(cè)試,每個(gè)手機(jī)都有自己的渲染效果
讓人郁悶的要死啊,關(guān)于這點(diǎn)一定要好好的注意下,小米手機(jī)渲染和三星手機(jī)完全就是兩回事
總結(jié)
以上是生活随笔為你收集整理的Android开发---图片渲染问题----真的很严重的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米传送门导致OnTouch事件中Mot
- 下一篇: Android11不如,1200万像素的