您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關如何在Android項目中使用ImageView,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
首先創建一個叫MatrixImageView的類去繼承ImageView,然后重寫其構造方法:
public class MatrixImageView2 extends ImageView { public MatrixImageView2(Context context, AttributeSet attrs) { super(context, attrs); initView(); } }
然后我們需要定義幾種當前view的狀態:
MODE_NONE(初始狀態);
MODE_DRAG(拖拽狀態);
MODE_ZOOM(兩個手指縮放狀態)
public class MatrixImageView2 extends ImageView { private static final int MODE_NONE = 190; private static final int MODE_DRAG = 468; private static final int MODE_ZOOM = 685; ..... }
我們對ImageView做旋轉、縮放、位移等操作主要是用到ImageView的這個方法:
/** * Adds a transformation {@link Matrix} that is applied * to the view's drawable when it is drawn. Allows custom scaling, * translation, and perspective distortion. * * @param matrix the transformation parameters in matrix form */ public void setImageMatrix(Matrix matrix) { // collapse null and identity to just null if (matrix != null && matrix.isIdentity()) { matrix = null; } // don't invalidate unless we're actually changing our matrix if (matrix == null && !mMatrix.isIdentity() || matrix != null && !mMatrix.equals(matrix)) { mMatrix.set(matrix); configureBounds(); invalidate(); } }
利用的是Matrix這個類(對這個類不懂的童鞋自己去查資料哈~),然后通過監聽我們的onTouchEvent方法獲取當前手勢操作,然后對matrix進行相應操作,改變圖片的狀態。
代碼比較短,而且我每行都注釋了,我就直接給代碼了:
MatrixImageView.java:
package com.leo.gestureimageview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.widget.ImageView; public class MatrixImageView2 extends ImageView { private static final int MODE_NONE = 190; private static final int MODE_DRAG = 468; private static final int MODE_ZOOM = 685; //當前mode private int mode; //手指按下時候的坐標 private float startX, startY; //兩個手指中間點的位置 private float midX, midY; //當前imageview的matirx對象,以前imageview的matrix對象 private Matrix currMatrix, savedMatrix; //之前圖片的旋轉角度 private float preRotate; //之間兩個手指之間的距離 private float preSpacing; public MatrixImageView2(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { //初始化模式為初始狀態 mode = MODE_NONE; currMatrix = new Matrix(); savedMatrix = new Matrix(); DisplayMetrics dm = getResources().getDisplayMetrics(); //給ImageView設置一張圖片(此處為了測試直接在imageview里面設置了一張測試圖片) Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test); bitmap = Bitmap.createScaledBitmap(bitmap, dm.widthPixels, dm.heightPixels, true); setImageBitmap(bitmap); } @Override public boolean onTouchEvent(MotionEvent event) { //多點觸碰如果需要監聽ACTION_POINTER_DOWN等操作的時候,必須用event.getAction() & MotionEvent.ACTION_MASK //而不是直接的event.getAction(); switch (event.getAction() & MotionEvent.ACTION_MASK) { //當一個手指按下的時候 case MotionEvent.ACTION_DOWN: //保存當前imageview的matrix對象 savedMatrix.set(currMatrix); //記錄手指開始的坐標 startX = event.getX(); startY = event.getY(); //此時的狀態為拖拽狀態 mode = MODE_DRAG; break; //當兩個手指按下的時候(我們先不考慮很多個的情況哈,能力有限~!) case MotionEvent.ACTION_POINTER_DOWN: //計算兩個手指之間的距離并保存起來 preSpacing = calSpacing(event); //如果兩個手指之間的距離大于我們指定的一個值后(改變狀態為縮放) if (preSpacing > 10f) { savedMatrix.set(currMatrix); mode = MODE_ZOOM; //記錄下縮放的中間坐標值 midX = (event.getX(0) + event.getX(1)) / 2; midY = (event.getY(0) + event.getY(1)) / 2; } //根據兩個手指的位置計算出當前角度并保存 preRotate = calRotate(event); break; //當手指移動的時候 case MotionEvent.ACTION_MOVE: //如果之前給的狀態為拖拽狀態的時候 if (mode == MODE_DRAG) { //首先把之前的matrix的狀態賦給當前的matrix對象 currMatrix.set(savedMatrix); //算出手指移動的距離 float dx = event.getX() - startX; float dy = event.getY() - startY; //把手指移動的距離設置給matrix對象 currMatrix.postTranslate(dx, dy); //當狀態為放大狀態的時候,并且有兩個手指按下的時候 } else if (mode == MODE_ZOOM && event.getPointerCount() == 2) { //首先把之前的matrix的狀態賦給當前的matrix對象 currMatrix.set(savedMatrix); //計算出此時兩個手指之間的距離 float spacing = calSpacing(event); //如果此時兩手指之間的距離大于我們給定的值 if (spacing > 10f) { //此時兩手指距離/第二個手指剛按下時兩手指的距離 float scale = spacing / preSpacing; //把算出的縮放值給當前matrix對象,(縮放中心點為之前算出的mid) currMatrix.postScale(scale, scale, midX, midY); } //根據兩手指位置算出此時的旋轉角度 float rotate = calRotate(event); if (rotate != preRotate) { //算出此時需要旋轉的角度 rotate = rotate - preRotate; //開始旋轉圖片 currMatrix.postRotate(rotate, getMeasuredWidth() / 2, getMeasuredHeight() / 2); } } break; } //最后記得把當前的matrix對象給imageview setImageMatrix(currMatrix); return true; } /** * 根據兩手指的位置算出角度 * 勾股定理 tan0=x(兩手指橫坐標距離)/y(兩手指縱坐標距離); * @param event * @return */ private float calRotate(MotionEvent event) { double x = event.getX(0) - event.getX(1); double y = event.getY(0) - event.getY(1); double radius = Math.atan2(y, x); return (float) Math.toDegrees(radius); } /** * 兩個點距離公式為d*d=(x1-x0)的平方+(y1-y0)的平方 * @param event * @return */ private float calSpacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); } }
然后添加我們的布局文件:
<com.leo.gestureimageview.MatrixImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="matrix" android:src="@mipmap/test" />
最后運行代碼:
好了,雖說我們是實現了我們的手勢imageview的基本功能,但是如果要處理那種多點(>兩個手指)觸碰,還有一些復雜的操作的時候,我們的onTouchEvent里面寫的代碼可能就不止這么一點了(還是有點復雜的,考慮的因素太多),但如果可以把某個事件的處理單獨拿出去分成很多個分支的話,還會這么復雜么?? 如果說我們的代碼可以像下面這樣的話,你是不是覺得很爽呢?
package com.leo.gestureimageview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.PointF; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.widget.ImageView; import com.leo.gestureimageview.GestureDetectors.MoveGestureDetector; import com.leo.gestureimageview.GestureDetectors.RotateGestureDetector; public class MatrixImageView2 extends ImageView { private Matrix mMatrix = new Matrix(); private float mScaleFactor =1f; private float mRotationDegrees = 0.f; private float mFocusX = 0.f; private float mFocusY = 0.f; private ScaleGestureDetector mScaleDetector; private RotateGestureDetector mRotateDetector; private MoveGestureDetector mMoveDetector; public MatrixImageView2(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { //初始化模式為初始狀態 DisplayMetrics dm = getResources().getDisplayMetrics(); //給ImageView設置一張圖片(此處為了測試直接在imageview里面設置了一張測試圖片) Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test); bitmap = Bitmap.createScaledBitmap(bitmap, dm.widthPixels, dm.heightPixels, true); setImageBitmap(bitmap); mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); mRotateDetector = new RotateGestureDetector(getContext(), new RotateListener()); mMoveDetector = new MoveGestureDetector(getContext(), new MoveListener()); mFocusX = dm.widthPixels/2f; mFocusY = dm.heightPixels/2f; } @Override public boolean onTouchEvent(MotionEvent event) { mScaleDetector.onTouchEvent(event); mRotateDetector.onTouchEvent(event); mMoveDetector.onTouchEvent(event); return true; } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); // scale change since previous event // Don't let the object get too small or too large. mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); changeMatrix(); return true; } } private class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener { @Override public boolean onRotate(RotateGestureDetector detector) { mRotationDegrees -= detector.getRotationDegreesDelta(); changeMatrix(); return true; } } private class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener { @Override public boolean onMove(MoveGestureDetector detector) { PointF d = detector.getFocusDelta(); mFocusX += d.x; mFocusY += d.y; changeMatrix(); return true; } } private void changeMatrix(){ float scaledImageCenterX = (getDrawable().getIntrinsicWidth()*mScaleFactor)/2; float scaledImageCenterY = (getDrawable().getIntrinsicHeight()*mScaleFactor)/2; mMatrix.reset(); mMatrix.postScale(mScaleFactor, mScaleFactor); mMatrix.postRotate(mRotationDegrees, scaledImageCenterX, scaledImageCenterY); mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY - scaledImageCenterY); setImageMatrix(mMatrix); } }
我們的ImageView的onTouchEvent就只剩下短短的幾行代碼了,然后各個detector處理完事件后,我們只需要拿到處理好的值就可以了:
@Override public boolean onTouchEvent(MotionEvent event) { //把縮放事件給mScaleDetector mScaleDetector.onTouchEvent(event); //把旋轉事件個mRotateDetector mRotateDetector.onTouchEvent(event); //把移動事件給mMoveDetector mMoveDetector.onTouchEvent(event); return true; }
上述就是小編為大家分享的如何在Android項目中使用ImageView了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。