android對(duì)圖片進(jìn)行縮放

作者:某人_Valar
如需轉(zhuǎn)載請(qǐng)保留原文鏈接
近期都在處理android圖像方面的問(wèn)題惦辛,就記錄一下

相關(guān)文章

1 簡(jiǎn)介

先來(lái)一張效果圖


TIM圖片.gif

上圖中灰色的一塊是ImageView控件爪幻,ImageView中的圖片進(jìn)行左右上下移動(dòng)塑顺,以及雙指縮放。
對(duì)于android控件的縮放移動(dòng)畅哑,點(diǎn)這里----android控件的縮放肴楷,移動(dòng)

2 使用步驟
  • 布局layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:id="@+id/root"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/mywhite"
              android:gravity="center_horizontal"
              android:fitsSystemWindows="true">

  
        <ImageView
            android:background="@color/light_gery"
            android:scaleType="matrix"
            android:src="@drawable/ic_sure"
            android:id="@+id/hair_iv"
            android:layout_marginTop="50dp"
            android:layout_width="300dp"
            android:layout_height="300dp"/>


</LinearLayout>
  • 先看關(guān)于手勢(shì)觸摸的判斷,需要判斷用戶是單指觸摸還是雙指荠呐,分別在OnTounch的監(jiān)聽事件中判斷赛蔫。
    注:先重寫onLongClick()方法,不然會(huì)影響OnTouch里面的觸摸監(jiān)聽泥张。
  private static final int NONE = 0;
  private static final int DRAG = 1;
  private static final int ZOOM = 2;
  private int mode = NONE;

hairIv.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                return true;
            }
        });


 hairIv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                         //單點(diǎn)觸控
                        mode = DRAG;
                        
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        //多點(diǎn)觸控
                    
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // 手指滑動(dòng)
                        if (mode == DRAG) {
                            // 是一個(gè)手指拖動(dòng)
                          Log.d(TAG, "mode = DRAG" );
                        } else if (mode == ZOOM) {
                            // 兩個(gè)手指滑動(dòng)
                          Log.d(TAG, "mode = ZOOM" );
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        // 手指放開事件
                        mode = NONE;
                        break;
                }
              
                return true;
            }
        });

這些寫上之后就可以先看一下單指呵恢,雙指的觸摸事件有沒(méi)有被正確處理

  • 通過(guò)Android提供的Matrix類對(duì)圖像進(jìn)行處理,關(guān)于Matrix的原理可以看一下Android官方文檔Matrix部分媚创,也可以找一些其他的博客渗钉,這里只看使用。

定義要用到的變量

    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    // 第一個(gè)按下的手指的點(diǎn)
    private PointF startPoint = new PointF();
    // 兩個(gè)按下的手指的觸摸點(diǎn)的中點(diǎn)
    private PointF midPoint = new PointF();
    // 初始的兩個(gè)手指按下的觸摸點(diǎn)的距離
    private float oriDis = 1f;

在onTouch中完善

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ImageView view = (ImageView) v;
                final int x = (int) event.getRawX();
                final int y = (int) event.getRawY();
                Log.d(TAG, "onTouch: x= " + x + "y=" + y);
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                         //單點(diǎn)觸控
                        matrix.set(view.getImageMatrix());
                        savedMatrix.set(matrix);
                        startPoint.set(event.getX(), event.getY());
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        //多點(diǎn)觸控
                        oriDis = distance(event);
                        if (oriDis > 10f) {
                            savedMatrix.set(matrix);
                            midPoint = midPoint(event);
                            mode = ZOOM;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // 手指滑動(dòng)事件
                        if (mode == DRAG) {
                            // 是一個(gè)手指拖動(dòng)
                            matrix.set(savedMatrix);
                            matrix.postTranslate(event.getX() - startPoint.x, event.getY()
                                    - startPoint.y);
                        } else if (mode == ZOOM) {
                            // 兩個(gè)手指滑動(dòng)
                            float newDist = distance(event);
                            if (newDist > 10f) {
                                matrix.set(savedMatrix);
                                float scale = newDist / oriDis;
                                matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        // 手指放開事件
                        mode = NONE;
                        break;
                }
                view.setImageMatrix(matrix);
                return true;
            }

其中用到的計(jì)算位置和距離的方法

    /**
     * 計(jì)算兩個(gè)手指頭之間的中心點(diǎn)的位置
     * x = (x1+x2)/2;
     * y = (y1+y2)/2;
     *
     * @param event 觸摸事件
     * @return 返回中心點(diǎn)的坐標(biāo)
     */
    private PointF midPoint(MotionEvent event) {
        float x = (event.getX(0) + event.getX(1)) / 2;
        float y = (event.getY(0) + event.getY(1)) / 2;
        return new PointF(x, y);
    }


    /**
     * 計(jì)算兩個(gè)手指間的距離
     *
     * @param event 觸摸事件
     * @return 放回兩個(gè)手指之間的距離
     */
    private float distance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);//兩點(diǎn)間距離公式
    }
3 源碼
public class ImageActivity extends AppCompatActivity{

    @BindView(R.id.hair_iv)
    ImageView hairIv;

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;

    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    // 第一個(gè)按下的手指的點(diǎn)
    private PointF startPoint = new PointF();
    // 兩個(gè)按下的手指的觸摸點(diǎn)的中點(diǎn)
    private PointF midPoint = new PointF();
    // 初始的兩個(gè)手指按下的觸摸點(diǎn)的距離
    private float oriDis = 1f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image);
        ButterKnife.bind(this);

        hairIv.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                return true;
            }
        });

        hairIv.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ImageView view = (ImageView) v;
                final int x = (int) event.getRawX();
                final int y = (int) event.getRawY();
                Log.d(TAG, "onTouch: x= " + x + "y=" + y);
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                         //單點(diǎn)觸控
                        matrix.set(view.getImageMatrix());
                        savedMatrix.set(matrix);
                        startPoint.set(event.getX(), event.getY());
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        //多點(diǎn)觸控
                        oriDis = distance(event);
                        if (oriDis > 10f) {
                            savedMatrix.set(matrix);
                            midPoint = midPoint(event);
                            mode = ZOOM;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // 手指滑動(dòng)事件
                        if (mode == DRAG) {
                            // 是一個(gè)手指拖動(dòng)
                            matrix.set(savedMatrix);
                            matrix.postTranslate(event.getX() - startPoint.x, event.getY()
                                    - startPoint.y);
                        } else if (mode == ZOOM) {
                            // 兩個(gè)手指滑動(dòng)
                            float newDist = distance(event);
                            if (newDist > 10f) {
                                matrix.set(savedMatrix);
                                float scale = newDist / oriDis;
                                matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        // 手指放開事件
                        mode = NONE;
                        break;
                }
                view.setImageMatrix(matrix);
                return true;
            }
        });
    }

    /**
     * 計(jì)算兩個(gè)手指頭之間的中心點(diǎn)的位置
     * x = (x1+x2)/2;
     * y = (y1+y2)/2;
     *
     * @param event 觸摸事件
     * @return 返回中心點(diǎn)的坐標(biāo)
     */
    private PointF midPoint(MotionEvent event) {
        float x = (event.getX(0) + event.getX(1)) / 2;
        float y = (event.getY(0) + event.getY(1)) / 2;
        return new PointF(x, y);
    }


    /**
     * 計(jì)算兩個(gè)手指間的距離
     *
     * @param event 觸摸事件
     * @return 放回兩個(gè)手指之間的距離
     */
    private float distance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);//兩點(diǎn)間距離公式
    }

  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钞钙,一起剝皮案震驚了整個(gè)濱河市鳄橘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芒炼,老刑警劉巖疹味,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秃流,死亡現(xiàn)場(chǎng)離奇詭異钱慢,居然都是意外死亡疮绷,警方通過(guò)查閱死者的電腦和手機(jī)弧关,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)唤锉,“玉大人世囊,你說(shuō)我怎么就攤上這事×椋” “怎么了株憾?”我有些...
    開封第一講書人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晒衩。 經(jīng)常有香客問(wèn)我嗤瞎,道長(zhǎng),這世上最難降的妖魔是什么听系? 我笑而不...
    開封第一講書人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任贝奇,我火速辦了婚禮,結(jié)果婚禮上靠胜,老公的妹妹穿的比我還像新娘掉瞳。我一直安慰自己,他們只是感情好浪漠,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開白布陕习。 她就那樣靜靜地躺著,像睡著了一般址愿。 火紅的嫁衣襯著肌膚如雪该镣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,798評(píng)論 1 290
  • 那天响谓,我揣著相機(jī)與錄音损合,去河邊找鬼。 笑死歌粥,一個(gè)胖子當(dāng)著我的面吹牛塌忽,可吹牛的內(nèi)容都是我干的拍埠。 我是一名探鬼主播失驶,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼枣购!你這毒婦竟也來(lái)了嬉探?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤棉圈,失蹤者是張志新(化名)和其女友劉穎涩堤,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體分瘾,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胎围,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片白魂。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汽纤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出福荸,到底是詐尸還是另有隱情蕴坪,我是刑警寧澤,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布敬锐,位于F島的核電站背传,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏台夺。R本人自食惡果不足惜径玖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颤介。 院中可真熱鬧挺狰,春花似錦、人聲如沸买窟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)始绍。三九已至瞳购,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亏推,已是汗流浹背学赛。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吞杭,地道東北人盏浇。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像芽狗,于是被迫代替她去往敵國(guó)和親绢掰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

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