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
}
}
}