package net.oschina.gitapp.ui; import java.io.File; import java.io.IOException; import net.oschina.gitapp.AppConfig; import net.oschina.gitapp.AppContext; import net.oschina.gitapp.AppException; import net.oschina.gitapp.R; import net.oschina.gitapp.api.ApiClient; import net.oschina.gitapp.common.FileUtils; import net.oschina.gitapp.common.ImageUtils; import net.oschina.gitapp.common.StringUtils; import net.oschina.gitapp.common.UIHelper; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.Button; import android.widget.ImageView; import android.widget.ViewSwitcher; /** * 图片缩放对话框 * * @author liux (http://my.oschina.net/liux) * @version 1.0 * @created 2012-3-21 */ public class ImageZoomActivity extends Activity implements OnTouchListener, OnClickListener { private AppContext mAppContext; // These matrices will be used to move and zoom image Matrix matrix = new Matrix(); Matrix savedMatrix = new Matrix(); PointF start = new PointF(); PointF mid = new PointF(); DisplayMetrics dm; float oldDist = 1f; private ImageView imgView; private Button zoomIn, zoomOut; private ViewSwitcher mViewSwitcher; private Button btnSave; private Button btnClose; // button zoom private float scaleWidth = 1; private float scaleHeight = 1; private Bitmap bitmap, zoomedBMP; private int zoom_level = 0; private static final double ZOOM_IN_SCALE = 1.25;// 放大系数 private static final double ZOOM_OUT_SCALE = 0.8;// 缩小系数 float minScaleR;// 最小缩放比例 static final float MAX_SCALE = 4f;// 最大缩放比例 // We can be in one of these 3 states static final int NONE = 0;// 初始状态 static final int DRAG = 1;// 拖动 static final int ZOOM = 2;// 缩放 int mode = NONE; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image_zoom); mAppContext = (AppContext) getApplication(); this.initView(); this.initData(); } private void initView() { dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm);// 获取分辨率 imgView = (ImageView) findViewById(R.id.imagezoomdialog_image); imgView.setOnTouchListener(this);// 设置触屏监听 mViewSwitcher = (ViewSwitcher) findViewById(R.id.imagezoomdialog_view_switcher); // 保存到图库 btnSave = (Button) findViewById(R.id.btn_save); btnSave.setOnClickListener(new View.OnClickListener() { @SuppressLint("NewApi") @Override public void onClick(View v) { try { String saveImagePath = AppConfig.DEFAULT_SAVE_IMAGE_PATH; ImageUtils.saveImageToSD(ImageZoomActivity.this, saveImagePath + ImageUtils.getTempFileName() + ".jpg", bitmap, 100); UIHelper.ToastMessage(ImageZoomActivity.this, "保存成功"); } catch (IOException e) { e.printStackTrace(); UIHelper.ToastMessage(ImageZoomActivity.this, "保存失败"); } } }); btnClose = (Button) findViewById(R.id.btn_close); btnClose.setOnClickListener(new OnClickListener() { @SuppressLint("NewApi") @Override public void onClick(View v) { ImageZoomActivity.this.onBackPressed(); } }); } private void initData() { final String imgURL = getIntent().getStringExtra("img_url"); final String ErrMsg = getString(R.string.msg_load_image_fail); final Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 1 && msg.obj != null) { bitmap = (Bitmap) msg.obj; imgView.setImageBitmap(bitmap); minZoom();// 计算最小缩放比 CheckView();// 设置图像居中 imgView.setImageMatrix(matrix); mViewSwitcher.showNext(); btnSave.setVisibility(View.VISIBLE); } else { UIHelper.ToastMessage(ImageZoomActivity.this, ErrMsg); finish(); } } }; new Thread() { public void run() { Message msg = new Message(); Bitmap bmp = null; String filename = FileUtils.getFileName(imgURL); try { // 读取本地图片 if (imgURL.endsWith("portrait.gif") || StringUtils.isEmpty(imgURL)) { bmp = BitmapFactory .decodeResource(imgView.getResources(), R.drawable.widget_dface); } if (bmp == null) { // 是否有缓存图片 // Environment.getExternalStorageDirectory();返回/sdcard String filepath = getFilesDir() + File.separator + filename; File file = new File(filepath); if (file.exists()) { bmp = ImageUtils.getBitmap(imgView.getContext(), filename); } } if (bmp == null) { bmp = ApiClient.getNetBitmap(imgURL); if (bmp != null) { try { // 写图片缓存 ImageUtils.saveImage(imgView.getContext(), filename, bmp); } catch (IOException e) { e.printStackTrace(); } // 缩放图片 bmp = ImageUtils.reDrawBitMap(ImageZoomActivity.this, bmp); } } msg.what = 1; msg.obj = bmp; } catch (AppException e) { e.printStackTrace(); msg.what = -1; msg.obj = e; } handler.sendMessage(msg); } }.start(); } public boolean onTouch(View v, MotionEvent event) { // Handle touch events here... ImageView imgView = (ImageView) v; // Handle touch events here... switch (event.getAction() & MotionEvent.ACTION_MASK) { // 设置拖拉模式(主点) case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); start.set(event.getX(), event.getY()); // Log.d(TAG, "mode=DRAG"); mode = DRAG; break; // 设置多点触摸模式(副点) case MotionEvent.ACTION_POINTER_DOWN: oldDist = spacing(event); // Log.d(TAG, "oldDist=" + oldDist); if (oldDist > 10f) { savedMatrix.set(matrix); midPoint(mid, event); mode = ZOOM; // Log.d(TAG, "mode=ZOOM"); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; // Log.d(TAG, "mode=NONE"); break; // 若为DRAG模式,则点击移动图片 case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix.set(savedMatrix); // 设置位移 matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); } // 若为ZOOM模式,则多点触摸缩放 else if (mode == ZOOM) { float newDist = spacing(event); // Log.d(TAG, "newDist=" + newDist); if (newDist > 10f) { matrix.set(savedMatrix); float scale = newDist / oldDist; // 设置缩放比例和图片中点位置 matrix.postScale(scale, scale, mid.x, mid.y); } } break; } // Perform the transformation imgView.setImageMatrix(matrix); CheckView(); return true; // indicate event was handled } /** * 限制最大最小缩放比例,自动居中 */ private void CheckView() { float p[] = new float[9]; matrix.getValues(p); if (mode == ZOOM) { if (p[0] < minScaleR) { matrix.setScale(minScaleR, minScaleR); } if (p[0] > MAX_SCALE) { matrix.set(savedMatrix); } } center(); } /** * 最小缩放比例,最大为100% */ private void minZoom() { // minScaleR = Math.min( // (float) dm.widthPixels / (float) bitmap.getWidth(), // (float) dm.heightPixels / (float) bitmap.getHeight()); if (bitmap.getWidth() >= dm.widthPixels) minScaleR = ((float) dm.widthPixels) / bitmap.getWidth(); else minScaleR = 1.0f; if (minScaleR < 1.0) { matrix.postScale(minScaleR, minScaleR); } } private void center() { center(true, true); } /** * 横向、纵向居中 */ protected void center(boolean horizontal, boolean vertical) { Matrix m = new Matrix(); m.set(matrix); RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (vertical) { // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移 int screenHeight = dm.heightPixels; if (height < screenHeight) { deltaY = (screenHeight - height) / 2 - rect.top; } else if (rect.top > 0) { deltaY = -rect.top; } else if (rect.bottom < screenHeight) { deltaY = imgView.getHeight() - rect.bottom; } } if (horizontal) { int screenWidth = dm.widthPixels; if (width < screenWidth) { deltaX = (screenWidth - width) / 2 - rect.left; } else if (rect.left > 0) { deltaX = -rect.left; } else if (rect.right < screenWidth) { deltaX = screenWidth - rect.right; } } matrix.postTranslate(deltaX, deltaY); } // 计算移动距离 @SuppressLint("NewApi") private float spacing(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); } // 计算中点位置 @SuppressLint("NewApi") private 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); } // 放大,缩小按钮点击事件 // @Override public void onClick(View v) { if (v == zoomIn) { enlarge(); } else if (v == zoomOut) { small(); } } // 按钮点击缩小函数 private void small() { int bmpWidth = bitmap.getWidth(); int bmpHeight = bitmap.getHeight(); scaleWidth = (float) (scaleWidth * ZOOM_OUT_SCALE); scaleHeight = (float) (scaleHeight * ZOOM_OUT_SCALE); Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); zoomedBMP = Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true); imgView.setImageBitmap(zoomedBMP); } // 按钮点击放大函数 private void enlarge() { try { int bmpWidth = bitmap.getWidth(); int bmpHeight = bitmap.getHeight(); scaleWidth = (float) (scaleWidth * ZOOM_IN_SCALE); scaleHeight = (float) (scaleHeight * ZOOM_IN_SCALE); Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); zoomedBMP = Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true); imgView.setImageBitmap(zoomedBMP); } catch (Exception e) { // can't zoom because of memory issue, just ignore, no big deal } } }