編輯:關於Android編程
Android平台上查看單張圖片時,通常情況下需要實現圖片查看、單指移動、雙指縮放、雙擊最大化或最小化功能。
目前網絡上的實現方式,都沒有將此功能封裝為類,零落在類和xml文件中,代碼難以閱讀,功能難以復用。
為此,我專門寫了一個類做此功能。此類唯一的缺點是沒有實現回彈動畫。不說廢話了,上代碼。
代碼如下:
package com.example.test; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.widget.ImageView; public class TouchImageView extends ImageView { private PointF down = new PointF(); private PointF mid = new PointF();private float oldDist = 1f; private Matrix matrix = new Matrix(); private Matrix preMatrix = new Matrix(); private Matrix savedMatrix = new Matrix(); private static final int NONE = 0; private static final int DRAG = 1; private static final int ZOOM = 2; private int mode = NONE; private boolean isBig = false; private int widthScreen; private int heightScreen; private int touchImgWidth; private int touchImgHeight; private float defaultScale; private long lastClickTime = 0; private Bitmap touchImg = null; private static final int DOUBLE_CLICK_TIME_SPACE = 300; private static final int DOUBLE_POINT_DISTANCE = 10; private static float MAX_SCALE = 3.0f; public TouchImageView(Context context) { super(context); } public TouchImageView(Context context, AttributeSet attrs) { super(context, attrs); } public TouchImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public void initImageView(int screenWidth, int screenHeight) { widthScreen = screenWidth; heightScreen = screenHeight; touchImg = ((BitmapDrawable) getDrawable()).getBitmap(); touchImgWidth = touchImg.getWidth(); touchImgHeight = touchImg.getHeight(); float scaleX = (float) widthScreen / touchImgWidth; float scaleY = (float) heightScreen / touchImgHeight; defaultScale = scaleX < scaleY ? scaleX : scaleY; float subX = (widthScreen - touchImgWidth * defaultScale) / 2; float subY = (heightScreen - touchImgHeight * defaultScale) / 2; setScaleType(ScaleType.MATRIX); preMatrix.reset(); preMatrix.postScale(defaultScale, defaultScale); preMatrix.postTranslate(subX, subY); matrix.set(preMatrix); invalidate(); } @Override protected void onDraw(Canvas canvas) { if (null != touchImg) { canvas.save(); canvas.drawBitmap(touchImg, matrix, null); canvas.restore(); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mode = DRAG; down.x = event.getX(); down.y = event.getY(); savedMatrix.set(matrix); if (event.getEventTime() - lastClickTime < DOUBLE_CLICK_TIME_SPACE) { changeSize(event.getX(), event.getY()); } lastClickTime = event.getEventTime(); break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = spacing(event); if (oldDist > DOUBLE_POINT_DISTANCE) { mode = ZOOM; // oldRotation = rotation(event); savedMatrix.set(matrix); midPoint(mid, event); } break; case MotionEvent.ACTION_MOVE: if (mode == ZOOM) { float newDist = spacing(event); float scale = newDist / oldDist; if (scale > 1.01 || scale < 0.99) { preMatrix.set(savedMatrix); preMatrix.postScale(scale, scale, mid.x, mid.y);// 縮放 if (canZoom()) { matrix.set(preMatrix); invalidate(); } } } else if (mode == DRAG) { if (1.0f < distance(event, down)) { preMatrix.set(savedMatrix); preMatrix.postTranslate(event.getX() - down.x, 0); if (event.getX() > down.x) { if (canDrag(DRAG_RIGHT)) { savedMatrix.set(preMatrix); } else { preMatrix.set(savedMatrix); } } else { if (canDrag(DRAG_LEFT)) { savedMatrix.set(preMatrix); } else { preMatrix.set(savedMatrix); } } preMatrix.postTranslate(0, event.getY() - down.y); if (event.getY() > down.y) { if (canDrag(DRAG_DOWN)) { savedMatrix.set(preMatrix); } else { preMatrix.set(savedMatrix); } } else { if (canDrag(DRAG_TOP)) { savedMatrix.set(preMatrix); } else { preMatrix.set(savedMatrix); } } matrix.set(preMatrix); invalidate(); down.x = event.getX(); down.y = event.getY(); savedMatrix.set(matrix); } } break; case MotionEvent.ACTION_UP: mode = NONE; springback(); break; case MotionEvent.ACTION_POINTER_UP: mode = NONE; break; } return true; } private void springback() { preMatrix.set(matrix); float[] x = new float[4]; float[] y = new float[4]; getFourPoint(x, y); if (x[1] - x[0] > widthScreen) { if (x[0] > 0) { preMatrix.postTranslate(-x[0], 0); matrix.set(preMatrix); invalidate(); } else if (x[1] < widthScreen) { preMatrix.postTranslate(widthScreen - x[1], 0); matrix.set(preMatrix); invalidate(); } } else if (x[1] - x[0] < widthScreen - 1f) { preMatrix.postTranslate((widthScreen - (x[1] - x[0])) / 2 - x[0], 0); matrix.set(preMatrix); invalidate(); } if (y[2] - y[0] > heightScreen) { if (y[0] > 0) { preMatrix.postTranslate(0, -y[0]); matrix.set(preMatrix); invalidate(); } else if (y[2] < heightScreen) { preMatrix.postTranslate(0, heightScreen - y[2]); matrix.set(preMatrix); invalidate(); } } else if (y[2] - y[0] < heightScreen - 1f) { preMatrix.postTranslate(0, (heightScreen - (y[2] - y[0])) / 2 - y[0]); matrix.set(preMatrix); invalidate(); } } private void getFourPoint(float[] x, float[] y) { float[] f = new float[9]; preMatrix.getValues(f); // 圖片4個頂點的坐標 x[0] = f[Matrix.MSCALE_X] * 0 + f[Matrix.MSKEW_X] * 0 + f[Matrix.MTRANS_X]; y[0] = f[Matrix.MSKEW_Y] * 0 + f[Matrix.MSCALE_Y] * 0 + f[Matrix.MTRANS_Y]; x[1] = f[Matrix.MSCALE_X] * touchImg.getWidth() + f[Matrix.MSKEW_X] * 0 + f[Matrix.MTRANS_X]; y[1] = f[Matrix.MSKEW_Y] * touchImg.getWidth() + f[Matrix.MSCALE_Y] * 0 + f[Matrix.MTRANS_Y]; x[2] = f[Matrix.MSCALE_X] * 0 + f[Matrix.MSKEW_X] * touchImg.getHeight() + f[Matrix.MTRANS_X]; y[2] = f[Matrix.MSKEW_Y] * 0 + f[Matrix.MSCALE_Y] * touchImg.getHeight() + f[Matrix.MTRANS_Y]; x[3] = f[Matrix.MSCALE_X] * touchImg.getWidth() + f[Matrix.MSKEW_X] * touchImg.getHeight() + f[Matrix.MTRANS_X]; y[3] = f[Matrix.MSKEW_Y] * touchImg.getWidth() + f[Matrix.MSCALE_Y] * touchImg.getHeight() + f[Matrix.MTRANS_Y]; } private final static int DRAG_LEFT = 0; private final static int DRAG_RIGHT = 1; private final static int DRAG_TOP = 2; private final static int DRAG_DOWN = 3; private boolean canDrag(final int direction) { float[] x = new float[4]; float[] y = new float[4]; getFourPoint(x, y); // 出界判斷 if ((x[0] > 0 || x[2] > 0 || x[1] < widthScreen || x[3] < widthScreen) && (y[0] > 0 || y[1] > 0 || y[2] < heightScreen || y[3] < heightScreen)) { return false; } if (DRAG_LEFT == direction) { // 左移出界判斷 if (x[1] < widthScreen || x[3] < widthScreen) { return false; } } else if (DRAG_RIGHT == direction) { // 右移出界判斷 if (x[0] > 0 || x[2] > 0) { return false; } } else if (DRAG_TOP == direction) { // 上移出界判斷 if (y[2] < heightScreen || y[3] < heightScreen) { return false; } } else if (DRAG_DOWN == direction) { // 下移出界判斷 if (y[0] > 0 || y[1] > 0) { return false; } } else { return false; } return true; } private boolean canZoom() { float[] x = new float[4]; float[] y = new float[4]; getFourPoint(x, y); // 圖片現寬度 double width = Math.sqrt((x[0] - x[1]) * (x[0] - x[1]) + (y[0] - y[1]) * (y[0] - y[1])); double height = Math.sqrt((x[0] - x[2]) * (x[0] - x[2]) + (y[0] - y[2]) * (y[0] - y[2])); // 縮放比率判斷 if (width < touchImgWidth * defaultScale - 1 || width > touchImgWidth * MAX_SCALE + 1) { return false; } // 出界判斷 if (width < widthScreen && height < heightScreen) { return false; } return true; } // 觸碰兩點間距離 private static float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); if (x < 0) { x = -x; } float y = event.getY(0) - event.getY(1); if (y < 0) { y = -y; } return FloatMath.sqrt(x * x + y * y); } // 取手勢中心點 private static void midPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); } // 取兩點之間的距離 private static float distance(MotionEvent point2, PointF point1) { float x = point1.x - point2.getX(); if (x < 0) { x = -x; } float y = point1.y - point2.getY(); if (y < 0) { y = -y; } return FloatMath.sqrt(x * x + y * y); } private void changeSize(float x, float y) { if (isBig) { float subX = (widthScreen - touchImgWidth * defaultScale) / 2; float subY = (heightScreen - touchImgHeight * defaultScale) / 2; preMatrix.reset(); preMatrix.postScale(defaultScale, defaultScale); preMatrix.postTranslate(subX, subY); matrix.set(preMatrix); invalidate(); isBig = false; } else { float transX = (widthScreen - touchImgWidth * MAX_SCALE) / 2; float transY = (heightScreen - touchImgHeight * MAX_SCALE) / 2; preMatrix.reset(); preMatrix.postScale(MAX_SCALE, MAX_SCALE); preMatrix.postTranslate(transX, transY); matrix.set(preMatrix); invalidate(); isBig = true; } } }
測試代碼如下:
activity_main.xml文件:
MainActivity.java文件:
package com.example.test; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Menu; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.LinearLayout; public class MainActivity extends Activity { private TouchImageView imgView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); TouchImageView imgView = (TouchImageView) findViewById(R.id.img_id); imgView.initImageView(dm.widthPixels, dm.heightPixels - 80); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
SQLite是Android系統內置的數據庫,是一種輕量級的關系型數據庫,它運算速度快,占用資源少,非常適合在移動設備上使用。同時,它不僅支持標准的SQL語法,還遵循了數
在很多方面,藍牙是一種能夠發送或接受兩個不同的設備之間傳輸的數據。 Android平台包含了藍牙框架,使設備以無線方式與其他藍牙設備進行數據交換的支持。Android提供
下拉刷新對於一個app來說是必不可少的一個功能,在早期大多數使用的是chrisbanes的PullToRefresh,或是修改自該框架的其他庫。而到現在已經有了更多的選擇
本文實例講述了Android編程之控件ListView使用方法。分享給大家供大家參考。具體分析如下:控件ListView是一個重要的控件,可以被用作用戶列表等顯示,下面進