自定義ImageView系列 - 區(qū)域截圖(下)

自定義ImageView系列 - 區(qū)域截圖(下)

功能要點(diǎn):

  • 根據(jù)控件自身大小計(jì)算合適的透明正方形預(yù)覽區(qū)荆虱;
  • 截取預(yù)覽區(qū)圖像并按照指定的尺寸縮放君编,生成Bitmap對(duì)象。
    本文著重介紹上述第2個(gè)要點(diǎn)。

有關(guān)第一個(gè)要點(diǎn)的內(nèi)容岳瞭,請(qǐng)參閱上一篇文章:請(qǐng)點(diǎn)此歧焦。
本篇文章中我們主要聊兩個(gè)問(wèn)題:

  • 屏幕指定區(qū)域截圖签赃;
  • 圖片縮放哨坪。

由于在前文中,我們知道了指定區(qū)域的方位,那么解決起來(lái)就輕松很多了两嘴。只要先截取整個(gè)屏幕丛楚,然后利用Matrix將圖片進(jìn)行裁剪即可。
截取到指定部分的圖像后憔辫,再利用Matrix的postScale()方法即可進(jìn)行縮放趣些。
下面放上代碼片段:

public Bitmap getAdjustedBitmap(Activity activity) {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    bitmap = view.getDrawingCache();
    matrix = new Matrix();
    matrix.postScale((CommonSettings.AVATOR\_SIZE * 1.0f) / (previewEdge[1] - previewEdge[0]), (CommonSettings.AVATOR\_SIZE * 1.0f) / (previewEdge[1] - previewEdge[0]));
    return Bitmap.createBitmap(bitmap, previewEdge[0] - 2, previewEdge[2] + myLocationStart[1] - 2, previewEdge[1] - previewEdge[0], previewEdge[1] - previewEdge[0], matrix, false);
}

如上所示,即可完成截圖和縮放操作贰您。
接下來(lái)放上整個(gè)重寫的ImageView類的代碼坏平,這里面還包含了雙指縮放和單指移動(dòng)操作功能。

 package com.toec.acryptim.view;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import com.toec.acryptim.R;
import com.toec.acryptim.environment.CommonSettings;

/**
 * 作者:蕭文翰
 * 郵箱:wh1990xiao2005@hotmail.com
 * 移動(dòng)電話:+86 15822932537
 * 微博:http://weibo.com/xwhnew
 * 個(gè)人網(wǎng)站:http://www.xwhcoder.com
 */
public class PhotoChooseForAvatorImageView extends ImageView {

private Bitmap bitmap;
private Matrix matrix;

private float point1_old_x, point1_old_y, point1_new_x, point1_new_y,
        point2_old_x, point2_old_y, point2_new_x, point2_new_y,
        distance_old, distance_new;
private float point_old_x, point_old_y, point_new_x, point_new_y;
private boolean isMultiTouch = false;

private int[] myLocationStart;
private int[] myLocationEnd;
private int[] myLocationMid;

private int[] previewEdge;

private int bitmapLocXStart, bitmapLocXEnd, bitmapLocYStart, bitmapLocYEnd;

private Paint rectPaint;
private Paint rectBgPaint;


public PhotoChooseForAvatorImageView(Context context) {
    super(context);
    if (matrix == null) {
        matrix = new Matrix();
    }
}

public PhotoChooseForAvatorImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    if (matrix == null) {
        matrix = new Matrix();
    }
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.save();
    if (bitmap != null) {
        canvas.drawBitmap(bitmap, matrix, null);
    }
    if (previewEdge != null) {
        //上
        canvas.drawLine(previewEdge[0], previewEdge[2], previewEdge[1], previewEdge[2], rectPaint);
        //左
        canvas.drawLine(previewEdge[0], previewEdge[2], previewEdge[0], previewEdge[3], rectPaint);
        //下
        canvas.drawLine(previewEdge[0], previewEdge[3], previewEdge[1], previewEdge[3], rectPaint);
        //右
        canvas.drawLine(previewEdge[1], previewEdge[2], previewEdge[1], previewEdge[3], rectPaint);
        //灰色部分
        canvas.drawRect(0, 0, previewEdge[0], myLocationEnd[1], rectBgPaint);
        canvas.drawRect(previewEdge[0], 0, previewEdge[1], previewEdge[2], rectBgPaint);
        canvas.drawRect(previewEdge[1], 0, myLocationEnd[0], myLocationEnd[1], rectBgPaint);
        canvas.drawRect(previewEdge[0], previewEdge[3], previewEdge[1], myLocationEnd[1], rectBgPaint);
    }
    canvas.restore();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            // 單點(diǎn)移動(dòng) 按下
            if (event.getPointerCount() == 1) {
                isMultiTouch = false;
                point_old_x = event.getX();
                point_old_y = event.getY();
            }
            break;
        case MotionEvent.ACTION_UP:
            // 單點(diǎn)移動(dòng) 抬起
            if (event.getPointerCount() == 1) {
                isMultiTouch = false;
                point_old_x = point_new_x;
                point_old_y = point_new_y;
            }

            break;
        case MotionEvent.ACTION_POINTER_UP:
            // 雙點(diǎn)操作 抬起
            if (event.getPointerCount() == 2) {
                isMultiTouch = true;
                point1_old_x = point1_new_x;
                point1_old_y = point1_new_y;
                point2_old_x = point2_new_x;
                point2_old_y = point2_new_y;

            }
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            // 雙點(diǎn)操作 按下
            if (event.getPointerCount() == 2) {
                isMultiTouch = true;
                point1_old_x = event.getX(0);
                point1_old_y = event.getY(0);
                point2_old_x = event.getX(1);
                point2_old_y = event.getY(1);
                distance_old = (float) Math
                        .sqrt(((point1_old_x - point2_old_x)
                                * (point1_old_x - point2_old_x) + (point1_old_y - point2_old_y)
                                * (point1_old_y - point2_old_y)));
            }
            break;
        case MotionEvent.ACTION_MOVE:
            // 雙點(diǎn)操作 移動(dòng)
            if (event.getPointerCount() == 2) {
                isMultiTouch = true;
                point1_new_x = event.getX(0);
                point1_new_y = event.getY(0);
                point2_new_x = event.getX(1);
                point2_new_y = event.getY(1);
                pinch();
            } else {
                // 單點(diǎn)移動(dòng) 移動(dòng)
                if (event.getPointerCount() == 1) {
                    if (!isMultiTouch) {
                        point_new_x = event.getX();
                        point_new_y = event.getY();
                        matrix.postTranslate((point_new_x - point_old_x),
                                (point_new_y - point_old_y));
                        point_old_x = point_new_x;
                        point_old_y = point_new_y;
                        invalidate();
                    }
                }
            }
            break;
    }
    return true;
}

// 縮放圖片方法
private void pinch() {
    distance_new = (float) Math.sqrt(((point1_new_x - point2_new_x)
            * (point1_new_x - point2_new_x) + (point1_new_y - point2_new_y)
            * (point1_new_y - point2_new_y)));
    matrix.postScale((distance_new / distance_old),
            (distance_new / distance_old), this.getWidth() / 2,
            this.getTop() / 2);
    invalidate();
    distance_old = distance_new;
}

/**
 * 設(shè)置Bitmap
 *
 * @param bitmap
 */
public void setImage(Bitmap bitmap) {
    this.bitmap = bitmap;
    //獲取控件自身起始點(diǎn)
    myLocationStart = new int[2];
    getLocationOnScreen(myLocationStart);
    //獲取控件自身終止點(diǎn)
    myLocationEnd = new int[2];
    myLocationEnd[0] = getWidth() + myLocationStart[0];
    myLocationEnd[1] = getHeight() + myLocationStart[1];
    //計(jì)算控件自身中點(diǎn)
    myLocationMid = new int[2];
    myLocationMid[0] = (myLocationStart[0] + myLocationEnd[0]) / 2;
    myLocationMid[1] = (myLocationStart[1] + myLocationEnd[1]) / 2 - myLocationStart[1];
    //設(shè)置中間預(yù)覽框邊框色
    rectPaint = new Paint();
    rectPaint.setColor(Color.WHITE);
    rectPaint.setStrokeWidth(2);

    rectBgPaint = new Paint();
    rectBgPaint.setColor(getResources().getColor(R.color.photo_adjust_for_avator_bg));
    //計(jì)算中間預(yù)覽邊框位置
    previewEdge = new int[4];
    previewEdge[0] = (myLocationMid[0] - myLocationStart[0]) / 8;
    previewEdge[1] = myLocationEnd[0] - previewEdge[0];
    previewEdge[2] = myLocationMid[1] - ((previewEdge[1] - previewEdge[0]) / 2);
    previewEdge[3] = myLocationMid[1] + ((previewEdge[1] - previewEdge[0]) / 2);
    //計(jì)算Bitmap起點(diǎn)
    bitmapLocXStart = myLocationMid[0] - bitmap.getWidth() / 2;
    bitmapLocYStart = myLocationMid[1] - bitmap.getHeight() / 2;
    bitmapLocXEnd = bitmapLocXStart + bitmap.getWidth();
    bitmapLocYEnd = bitmapLocYStart - bitmap.getHeight();
    //調(diào)整Bitmap位置
    matrix.postTranslate(bitmapLocXStart, bitmapLocYStart);
    PhotoChooseForAvatorImageView.this.invalidate();
}

/**
 * 截圖并返回Bitmap對(duì)象
 */
public Bitmap getAdjustedBitmap(Activity activity) {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    bitmap = view.getDrawingCache();
    matrix = new Matrix();
    matrix.postScale((CommonSettings.AVATOR_SIZE * 1.0f) / (previewEdge[1] - previewEdge[0]), (CommonSettings.AVATOR_SIZE * 1.0f) / (previewEdge[1] - previewEdge[0]));
    return Bitmap.createBitmap(bitmap, previewEdge[0] - 2, previewEdge[2] + myLocationStart[1] - 2, previewEdge[1] - previewEdge[0], previewEdge[1] - previewEdge[0], matrix, false);
}

/**
 * 重置Bitmap(回收內(nèi)存)
 */
public void resetBitmap() {
    bitmap.recycle();
    bitmap = null;
}
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锦亦,一起剝皮案震驚了整個(gè)濱河市舶替,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杠园,老刑警劉巖顾瞪,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抛蚁,居然都是意外死亡陈醒,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門瞧甩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钉跷,“玉大人,你說(shuō)我怎么就攤上這事肚逸∫蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵吼虎,是天一觀的道長(zhǎng)犬钢。 經(jīng)常有香客問(wèn)我苍鲜,道長(zhǎng)思灰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任混滔,我火速辦了婚禮洒疚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坯屿。我一直安慰自己油湖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布领跛。 她就那樣靜靜地躺著乏德,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喊括,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天胧瓜,我揣著相機(jī)與錄音,去河邊找鬼郑什。 笑死府喳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蘑拯。 我是一名探鬼主播钝满,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼申窘!你這毒婦竟也來(lái)了弯蚜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤剃法,失蹤者是張志新(化名)和其女友劉穎熟吏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玄窝,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡牵寺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恩脂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帽氓。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俩块,靈堂內(nèi)的尸體忽然破棺而出黎休,到底是詐尸還是另有隱情,我是刑警寧澤玉凯,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布势腮,位于F島的核電站,受9級(jí)特大地震影響漫仆,放射性物質(zhì)發(fā)生泄漏捎拯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一盲厌、第九天 我趴在偏房一處隱蔽的房頂上張望署照。 院中可真熱鬧,春花似錦吗浩、人聲如沸建芙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)禁荸。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赶熟,已是汗流浹背品嚣。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钧大,地道東北人翰撑。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像啊央,于是被迫代替她去往敵國(guó)和親眶诈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

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

  • 功能要點(diǎn): 根據(jù)控件自身大小計(jì)算合適的透明正方形預(yù)覽區(qū)瓜饥; 截取預(yù)覽區(qū)圖像并按照指定的尺寸縮放逝撬,生成Bitmap對(duì)象...
    蕭文翰閱讀 898評(píng)論 0 0
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,085評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件乓土、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,096評(píng)論 4 62
  • 今天是2015年8月20號(hào)趣苏,農(nóng)歷上是傳統(tǒng)的七夕狡相,牛郎和織女鵲橋相會(huì)的日子,想必很多朋友都對(duì)高三課本里的那句“金風(fēng)玉...
    董明明閱讀 2,465評(píng)論 21 48
  • 今天請(qǐng)出在冰箱里封存已久的番茄豆食磕。綿軟尽棕,酸甜。不錯(cuò)彬伦。 午餐依舊滔悉,菜2份,飯1份单绑,優(yōu)質(zhì)蛋白1點(diǎn)點(diǎn)回官。 噹噹噹噹,為大家...
    靜趣_兒童心理師閱讀 280評(píng)論 0 0