Android中映像變換Matrix的原理、代碼驗證和應用(三)

來源:互聯網
上載者:User

第三部分 應用

在這一部分,我們會將前面兩部分所瞭解到的內容和Android手勢結合起來,利用各種不同的手勢對映像進行平移、縮放和旋轉,前面兩項都是在實踐中經常需要用到的功能,後一項據說蘋果也是最近才加上的,而實際上在Android中,咱們通過自己的雙手,也可以很輕鬆地實現之。

 

首先建立一個Android項目PatImageView,同時建立一個Activity:PatImageViewActivity。完成這一步後, 記得在AndroidManifest.xml中增加如下許可:

<uses-permissionandroid:name="android.permission.VIBRATE"/>

因為我們將要通過短按還是長按,來確定將圖片到底是縮放還是旋轉。

 

現在來建立一個ImageView的衍生類別:PatImageView,其代碼(PatImageView.java)如下(2011-11-22 revised):

package com.pat.imageview;import android.app.Service;import android.content.Context;import android.graphics.Matrix;import android.graphics.PointF;import android.os.Vibrator;import android.util.FloatMath;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;public class PatImageView extends ImageView{private Matrix matrix;private Matrix savedMatrix;private boolean long_touch = false;private static int NONE = 0;private static int DRAG = 1;// 拖動private static int ZOOM = 2;// 縮放private static int ROTA = 3;// 旋轉private int mode = NONE;private PointF startPoint;private PointF middlePoint;private float oldDistance;private float oldAngle;private Vibrator vibrator;private GestureDetector gdetector;public PatImageView(final Context context){super(context);matrix = new Matrix();savedMatrix = new Matrix();matrix.setTranslate(0f, 0f);setScaleType(ScaleType.MATRIX);setImageMatrix(matrix);startPoint = new PointF();middlePoint = new PointF();oldDistance = 1f;gdetector = new GestureDetector(context, new GestureDetector.OnGestureListener(){@Overridepublic boolean onSingleTapUp(MotionEvent e){return true;}@Overridepublic void onShowPress(MotionEvent e){}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){return true;}@Overridepublic void onLongPress(MotionEvent e){long_touch = true;vibrator = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);// 震動50ms,提示後續的操作將是旋轉圖片,而非縮放圖片vibrator.vibrate(50);}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){return true;}@Overridepublic boolean onDown(MotionEvent e){return true;}});setOnTouchListener(new OnTouchListener(){public boolean onTouch(View view, MotionEvent event){switch(event.getAction() & MotionEvent.ACTION_MASK){case MotionEvent.ACTION_DOWN:// 第一個手指touchsavedMatrix.set(matrix);startPoint.set(event.getX(), event.getY());mode = DRAG;long_touch = false;break;case MotionEvent.ACTION_POINTER_DOWN:// 第二個手指toucholdDistance = getDistance(event);// 計算第二個手指touch時,兩指之間的距離oldAngle = getDegree(event);// 計算第二個手指touch時,兩指所形成的直線和x軸的角度if(oldDistance > 10f){savedMatrix.set(matrix);middlePoint = midPoint(event);if(!long_touch){mode = ZOOM;}else{mode = ROTA;}}break;case MotionEvent.ACTION_UP:mode = NONE;break;case MotionEvent.ACTION_POINTER_UP:mode = NONE;break;case MotionEvent.ACTION_MOVE:if(vibrator != null)vibrator.cancel();if(mode == DRAG){matrix.set(savedMatrix);matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);}if(mode == ZOOM){float newDistance = getDistance(event);if(newDistance > 10f){matrix.set(savedMatrix);float scale = newDistance / oldDistance;matrix.postScale(scale, scale, middlePoint.x, middlePoint.y);}}if(mode == ROTA){float newAngle = getDegree(event);matrix.set(savedMatrix);float degrees = newAngle - oldAngle;matrix.postRotate(degrees, middlePoint.x, middlePoint.y);}break;}setImageMatrix(matrix);invalidate();gdetector.onTouchEvent(event);return true;}});}// 計算兩個手指之間的距離    private float getDistance(MotionEvent event)    {        float x = event.getX(0) - event.getX(1);        float y = event.getY(0) - event.getY(1);        return FloatMath.sqrt(x * x + y * y);    }        // 計算兩個手指所形成的直線和x軸的角度    private float getDegree(MotionEvent event)    {    return (float)(Math.atan((event.getY(1) - event.getY(0)) / (event.getX(1) - event.getX(0))) * 180f);    }    // 計算兩個手指之間,中間點的座標    private PointF midPoint( MotionEvent event)    {    PointF point = new PointF();        float x = event.getX(0) + event.getX(1);        float y = event.getY(0) + event.getY(1);        point.set(x / 2, y / 2);                return point;    }}

 

下面完善PatImageViewActivity.java的代碼,使之如下:

package com.pat.imageview;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class PatImageViewActivity extends Activity{    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);                requestWindowFeature(Window.FEATURE_NO_TITLE);        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,         WindowManager.LayoutParams.FLAG_FULLSCREEN);                PatImageView piv = new PatImageView(this);        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);        piv.setImageBitmap(bmp);                setContentView(piv);    }}

 

由於有些手勢在模擬器上無法類比,所以就不上運行結果的圖片了。本人在真機上運行後(照片就不拍了,有點累啦),可以輕鬆做到:

1.     很方便地拖動圖片(比如,單指按住螢幕進行拖動)

2.     很方便地縮放圖片(比如,雙指按住螢幕進行分開或者併攏操作,可分別實現放大或者縮小圖片的功能)

3.     長按出現震動後,可以很方便地旋轉圖片(一個手指固定,另外一個手指圍繞那個固定的手指運動)。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.