Android學(xué)習(xí)筆記18 圖形圖像完全解析

本文主要對(duì)Android開發(fā)中圖形圖像部分的相關(guān)內(nèi)容作個(gè)簡(jiǎn)單的學(xué)習(xí)總結(jié)。

一薛闪、概述
二、ImageView詳解
三俺陋、Bitmap詳解
四豁延、Canvas詳解
五昙篙、SurfaceView簡(jiǎn)介
六、總結(jié)

一诱咏、概述

在我們的應(yīng)用開發(fā)中苔可,圖形圖像處理往往是不可避免要接觸的內(nèi)容。一個(gè)完整的App袋狞,文字焚辅、圖像、動(dòng)畫等都是用戶交互的重要組成元素苟鸯。本文主要從ImageView開始同蜻,對(duì)Android開發(fā)中與圖形圖像處理相關(guān)的內(nèi)容作個(gè)簡(jiǎn)單的總結(jié)。

二早处、ImageView用法與解析

1湾蔓、ImageView簡(jiǎn)介

ImageView的用途相信大家都已經(jīng)十分的熟悉,應(yīng)用中圖標(biāo)或者圖片的展示一般都需要用到這個(gè)控件砌梆。SDK文檔中對(duì)它的介紹默责,大致翻譯是ImageView,圖像視圖咸包,是用來(lái)展示一個(gè)任意的圖像的控件桃序,例如圖標(biāo)。它可以從不同的來(lái)源載入圖像诉儒,控制圖像的大小葡缰,并提供多種展示選項(xiàng)亏掀,比如縮放比例或者著色器等忱反。

2、ImageView用法

首先我們看下ImageView一個(gè)最簡(jiǎn)單的使用滤愕。

<ImageView
     android:id="@+id/iv_scaletype_test"
     android:layout_width="200dp"
     android:layout_height="200dp"
     android:src="@drawable/img_test" />

當(dāng)在布局文件里指定ImageView的寬高以及src屬性后温算,一張圖片就可以展示在ImageView上了。如果是用Java代碼動(dòng)態(tài)控制间影,那么src屬性可以用方法setImageResource來(lái)完成注竿。

當(dāng)然,我們也可以配置很多其它屬性魂贬。常用的有scaleType巩割,了解它之前我們來(lái)看兩張對(duì)比圖。

未設(shè)置scaleType的ImageView
scaleType設(shè)置為CENTER_CROP的ImageView

可以看到付燥,scaleType的不同設(shè)置可以控制圖像在ImageView中的顯示樣式宣谈。

scaleType的取值共有8種,分別是:

  • MATRIX键科,意思是“矩陣”闻丑,即用矩陣來(lái)繪制漩怎,不縮放
  • FIT_XY,不按比例縮放圖片嗦嗡,把圖片塞滿整個(gè)ImageView勋锤。
  • FIT_START,置頂侥祭,圖片顯示在ImageView的左上角start的位置
  • FIT_CENTER叁执,居中
  • FIT_END,置底矮冬,圖片顯示在ImageView的右下角end的位置
  • CENTER徒恋,按圖片的原來(lái)尺寸居中顯示,當(dāng)圖片長(zhǎng)/寬超過ImageView的長(zhǎng)/寬欢伏,則截取圖片的居中部分顯示
  • CENTER_CROP入挣,按比例擴(kuò)大圖片的size居中顯示,使得圖片長(zhǎng)(寬)等于或大于ImageView的長(zhǎng)(寬)
  • CENTER_INSIDE硝拧,圖片完整居中顯示径筏,比例縮小或原來(lái)的size使得圖片長(zhǎng)/寬等于或小于ImageView的長(zhǎng)/寬

一圖勝千言,請(qǐng)看:

scaleType不同的設(shè)置.gif

在未設(shè)置scaleType時(shí)障陶,系統(tǒng)默認(rèn)保證圖片完整滋恬、居中顯示,并等比縮放抱究,其效果跟android:scaleType=”fitCenter”的效果一致恢氯。

在代碼里控制圖片的縮放樣式是用方法setScaleType來(lái)設(shè)置的」乃拢可以看到勋拟,用好這個(gè)屬性,可以明顯地改善圖片在界面上的顯示效果妈候。

在ImageView的使用過程中敢靡,還有個(gè)tint屬性可以設(shè)置。tint翻譯是著色苦银,它可以用來(lái)改變ImageView中內(nèi)容的顏色啸胧,在代碼中對(duì)應(yīng)的設(shè)置方法是imageview.setColorFilter(Color),我們可以利用這個(gè)屬性來(lái)修改一些圖標(biāo)的顯示顏色幔虏。

三纺念、Bitmap詳解

Bitmap,翻譯為位圖想括,它是一個(gè)final類陷谱,Android系統(tǒng)圖像處理中最重要的類之一。Bitmap可以獲取圖像文件信息主胧,對(duì)圖像進(jìn)行剪切叭首、旋轉(zhuǎn)习勤、縮放,壓縮等操作焙格,并可以以指定格式保存圖像文件图毕。在實(shí)際使用過程中,因?yàn)锽itmap很占內(nèi)存眷唉,所以需要注意進(jìn)行壓縮予颤,高效加載避免OOM。

Bitmap類比較特別冬阳,我們不能通過它的構(gòu)造方法來(lái)實(shí)例化蛤虐,只能通過Bitmap的靜態(tài)方法或者借助BitmapFactory的靜態(tài)方法來(lái)實(shí)例化。類BitmapFactory肝陪,它可以讓我們從不同的來(lái)源驳庭,比如文件,流氯窍,字節(jié)數(shù)組等來(lái)源中創(chuàng)建Bitmap對(duì)象饲常。下面是BitmapFactory的類結(jié)構(gòu)±翘郑可以看到贝淤,它提供了一系列從不同來(lái)源實(shí)例化Bitmap的方法。

BitmapFactory的類結(jié)構(gòu)

下面看個(gè)簡(jiǎn)單的例子政供。

實(shí)例化Bitmap并顯示在ImageView上

上圖中播聪,已經(jīng)用OkHttp網(wǎng)絡(luò)請(qǐng)求獲取到了字節(jié)數(shù)組,在Handler中處理消息時(shí)布隔,先獲取到字節(jié)數(shù)組离陶,然后利用BitmapFactory的decodeByteArray方法,實(shí)例化Bitmap执泰,最后通過ImageView的setImageBitmap方法將Bitmap設(shè)置為ImageView的內(nèi)容枕磁。

Bitmap特別耗內(nèi)存渡蜻,所以我們?cè)谑褂弥幸肿⒁鈨?yōu)化术吝。常見的措施有,及時(shí)調(diào)用recycle()進(jìn)行內(nèi)存回收茸苇,實(shí)例化Bitmap時(shí)進(jìn)行圖片壓縮排苍,以及采取圖片緩存等。

下面是在使用BitmapFactory的靜態(tài)方法實(shí)例化Bitmap時(shí)進(jìn)行壓縮学密。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;

Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);

可以看到上面的代碼實(shí)例化參數(shù)Options時(shí)設(shè)置inSampleSize為4淘衙,這樣實(shí)例化的Bitmap占用的內(nèi)存只為原來(lái)的1/16。

1.Bitmap的內(nèi)存占用

上面我們提到腻暮,在使用類BitmapFactory加載Bitmap時(shí)指定Options可以有效的優(yōu)化Bitmap的內(nèi)存占用彤守,那么Bitmap的內(nèi)存占用具體怎么計(jì)算的呢毯侦?這里有個(gè)公式:

占用內(nèi)存 = 圖片寬 * 圖片高 * 單位像素占用的內(nèi)存

這里簡(jiǎn)單說(shuō)明一下,圖片的寬和高比較容易理解具垫,單位像素的占用內(nèi)存一般是由圖片加載時(shí)的色彩模式?jīng)Q定的侈离,android默認(rèn)的色彩模式是ARGB_8888,一個(gè)像素占用的內(nèi)存是4個(gè)字節(jié)筝蚕。

這里還需要注意的是卦碾,圖片的來(lái)源也會(huì)最終影響占用內(nèi)存。如果我們直接從網(wǎng)絡(luò)上獲取圖片起宽,那么圖片的占用內(nèi)存就是上面的公式洲胖。但是如果是從drawable目錄下加載圖片,那么占用內(nèi)存會(huì)因?yàn)椴煌膁rawable目錄而不同坯沪,因?yàn)锳ndroid系統(tǒng)在加載不同drawable目錄下的圖片到不用分辨率的機(jī)型上時(shí)會(huì)進(jìn)行一定的縮放绿映。

2.Bitmap的高效加載

BitmapFactory加載Bitmap時(shí)指定Options是一個(gè)比較好的習(xí)慣,那么Options的inSampleSize指定多少比較合適呢腐晾?其實(shí)最理想的情況是我們根據(jù)需要顯示的ImageView的大小計(jì)算出Options的inSampleSize绘梦。

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

3.Bitmap的緩存

項(xiàng)目中如果需要加載圖片,那么圖片緩存的設(shè)計(jì)非常重要赴魁。一般來(lái)說(shuō)卸奉,圖片緩存會(huì)涉及到內(nèi)存緩存和磁盤緩存,當(dāng)需要加載圖片時(shí)颖御,先看內(nèi)存中有沒有榄棵,沒有的話再看磁盤緩存中有沒有,最后再嘗試網(wǎng)絡(luò)請(qǐng)求獲取圖片潘拱。

內(nèi)存緩存和磁盤緩存目前比較常用的算法是LRU(Least Recently Used)疹鳄,即近期最少使用算法,內(nèi)存緩存我們可以借助LruCache這個(gè)類來(lái)完成芦岂,磁盤緩存可以用DiskLruCache瘪弓,它們共同的原理是指定一個(gè)緩存的總大小,當(dāng)緩存滿時(shí)禽最,優(yōu)先淘汰那些近期最少使用的緩存的對(duì)象腺怯。

四、Canvas解析

說(shuō)到圖形圖像川无,那么肯定離不開要談Canvas這個(gè)類呛占。當(dāng)我們想要繪制自己的圖形時(shí),或者在自定義View中懦趋,一般都會(huì)用到它晾虑。Canvas,直譯為畫布,SDK文檔對(duì)它的介紹如下:

The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).

Canvas類包含很多draw的方法帜篇,要畫某樣?xùn)|西糙捺,一般需要4個(gè)基本元素:一是Bitmap,用來(lái)包含像素笙隙。二是Canvas继找,包含畫的方法。三是畫的參數(shù)逃沿,比如寬高等屬性婴渡。四是Paint,畫筆凯亮,用來(lái)描述繪畫的顏色和樣式边臼。

Canvas類中用來(lái)draw系列方法

同樣的,我們來(lái)看個(gè)簡(jiǎn)單的例子假消。

public class MyDrawView extends View {

    private Paint mPaint;

    public MyDrawView(Context context) {
        super(context);

        mPaint = new Paint();
        mPaint.setColor(Color.RED);// 設(shè)置畫筆顏色為紅色
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setTextSize(50f);
        canvas.drawText("畫圓:", 100, 200, mPaint);// 畫文本

        canvas.drawCircle(300, 200, 80, mPaint);// 小圓
        mPaint.setAntiAlias(true);// 設(shè)置畫筆的鋸齒效果
        canvas.drawCircle(600, 200, 150, mPaint);// 大圓

        canvas.drawText("畫線:", 100, 600, mPaint);
        canvas.drawLine(600, 400, 1000, 400, mPaint);// 畫線
        canvas.drawLine(600, 400, 1000, 800, mPaint);// 斜線
    }
}

在上面的代碼中柠并,我們創(chuàng)建了一個(gè)繼承自View的子類,構(gòu)造函數(shù)里我們初始化了畫筆Paint富拗,設(shè)置顏色為紅色臼予。在onDraw()方法里,我們使用Canvas內(nèi)部的幾個(gè)draw方法繪制不同的圖形啃沪,drawText是繪制文本粘拾,drawCircle是繪制圓...

最后效果如下:

Canvas畫圖

除了繪制各種基本的圖形,我們也可以通過drawBitmap來(lái)繪制圖片创千。實(shí)際開發(fā)中缰雇,利用Canvas、Paint等類追驴,我們可以創(chuàng)造出很出酷炫的自定義圖形械哟。

五、SurfaceView簡(jiǎn)介

自己之前對(duì)SurfaceView這個(gè)類不是很熟悉殿雪,這次特地查閱了官方文檔結(jié)合相關(guān)資料暇咆,這里簡(jiǎn)單地作個(gè)介紹。

View在大部分情況下可以滿足我們的繪圖需求丙曙,但是當(dāng)需要頻繁刷新爸业,或者刷新時(shí)數(shù)據(jù)量比較大時(shí),容易造成畫面卡頓河泳,SurfaceView是用來(lái)在上述兩種情況下替代View的沃呢。

下面是官方文檔的介紹

Provides a dedicated drawing surface embedded inside of a view hierarchy. You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen

SurfaceView提供了一個(gè)專門用于繪圖的surface,它嵌入在View的內(nèi)部拆挥。我們可以控制這個(gè)surface的格式和大小,SurfaceView主要負(fù)責(zé)把surface放置在屏幕上的正確位置。

SurfaceView可以直接從內(nèi)存或者DMA等硬件接口取得圖像數(shù)據(jù)纸兔,因此是個(gè)非常重要的繪圖容器惰瓜。

六、總結(jié)

在實(shí)際開發(fā)中汉矿,我們可以為顯示的圖形圖像增加很多的特效崎坊,這部分內(nèi)容這里就不詳細(xì)介紹了≈弈矗總的來(lái)說(shuō)奈揍,我們可以利用ColorMatrix顏色矩陣類來(lái)處理圖像的色彩效果,Android系統(tǒng)利用矩陣來(lái)進(jìn)行圖像的圖形變換赋续,當(dāng)然男翰,我們還可以充分地利用Android中的動(dòng)畫來(lái)完成圖形圖像的動(dòng)態(tài)效果展示。

關(guān)于Android中的圖形圖像部分的學(xué)習(xí)總結(jié)就是這些纽乱,當(dāng)然實(shí)踐出真知蛾绎,只有在實(shí)際開發(fā)中不斷摸索不斷嘗試,才能更好地掌握Android中的這些圖形圖像處理鸦列,創(chuàng)造出更多更酷炫的自定義效果租冠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市薯嗤,隨后出現(xiàn)的幾起案子顽爹,更是在濱河造成了極大的恐慌,老刑警劉巖骆姐,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件话原,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡诲锹,警方通過查閱死者的電腦和手機(jī)繁仁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)归园,“玉大人黄虱,你說(shuō)我怎么就攤上這事∮褂眨” “怎么了捻浦?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)桥爽。 經(jīng)常有香客問我朱灿,道長(zhǎng),這世上最難降的妖魔是什么钠四? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任盗扒,我火速辦了婚禮跪楞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侣灶。我一直安慰自己甸祭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布褥影。 她就那樣靜靜地躺著池户,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凡怎。 梳的紋絲不亂的頭發(fā)上校焦,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音统倒,去河邊找鬼寨典。 笑死,一個(gè)胖子當(dāng)著我的面吹牛檐薯,可吹牛的內(nèi)容都是我干的凝赛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坛缕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼墓猎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起赚楚,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤毙沾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后宠页,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體左胞,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年举户,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烤宙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俭嘁,死狀恐怖躺枕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情供填,我是刑警寧澤拐云,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站近她,受9級(jí)特大地震影響叉瘩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粘捎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一薇缅、第九天 我趴在偏房一處隱蔽的房頂上張望危彩。 院中可真熱鬧,春花似錦捅暴、人聲如沸恬砂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至漆羔,卻和暖如春梧奢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背演痒。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工亲轨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸟顺。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓惦蚊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親讯嫂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹦锋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評(píng)論 25 707
  • 1. Outline 本文主要從以下三個(gè)大的方面來(lái)說(shuō)明一下2D Graphic 繪圖的一些相關(guān)函數(shù)及應(yīng)用。 Col...
    lee_3do閱讀 3,029評(píng)論 0 11
  • //通過獲得資源文件進(jìn)行設(shè)置欧芽。根據(jù)不同的情況R.color.red也可以是R.string.red或者R.draw...
    gogoingmonkey閱讀 1,943評(píng)論 0 2
  • 參考Drawable子類之—— BitmapDrawable (可控制對(duì)齊平鋪的圖像) 明明圖片拉進(jìn)去對(duì)應(yīng)的文件之...
    合肥黑閱讀 5,385評(píng)論 0 7
  • docker-compose 訪問http://192.168.99.100:8500/ui/#/dc1/serv...
    go4it閱讀 598評(píng)論 0 1