包结构
BrowsePicActivity.java
package com.example.activity;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.example.adapter.GridViewImageAdapter;
import com.example.captureimage.R;
import com.example.captureimage.R.layout;
import com.example.help.AppConstant;
import com.example.help.Utils;
import android.R.integer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.Toast;
public class BrowsePicActivity extends Activity {
private Utils utils;
private GridView gridView;
private ArrayList<String> fileNames=new ArrayList<String>();
private GridViewImageAdapter adapter;
private int columnWidth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_browse_pic);
gridView=(GridView) findViewById(R.id.grid_view);
utils=new Utils(this);
initGridLayout();
fileNames=utils.getFilePaths();
adapter=new GridViewImageAdapter(BrowsePicActivity.this, fileNames, columnWidth);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode==100){
this.recreate();
}
}
private void initGridLayout() {
Resources resources=getResources();
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppConstant.GRID_PADDING, resources.getDisplayMetrics());
columnWidth = (int) ((utils.getScreenWidth() - ((AppConstant.NUM_OF_COLUMNS + 1) * padding)) / AppConstant.NUM_OF_COLUMNS);
gridView.setNumColumns(AppConstant.NUM_OF_COLUMNS);
gridView.setColumnWidth(columnWidth);
gridView.setStretchMode(GridView.NO_STRETCH);
gridView.setPadding((int)padding,(int) padding,(int) padding,(int) padding);
gridView.setHorizontalSpacing((int) padding);
gridView.setVerticalSpacing((int) padding);
}
}
CapturePicActivity.java
package com.example.activity;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import com.example.captureimage.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.media.Image;
import android.os.Bundle;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
public class CapturePicActivity extends Activity {
SurfaceView sView;
SurfaceHolder surfaceHolder;
int screenWidth, screenHeight;
// 定义系统所用的照相机
Camera camera;
// 是否在预览中
boolean isPreview = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置全屏
// requestWindowFeature(Window.FEATURE_NO_TITLE);
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
// WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
// 获取窗口管理器
WindowManager wm = getWindowManager();
Display display = wm.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
// 获取屏幕的宽和高
display.getMetrics(metrics);
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
// 获取界面中SurfaceView组件
sView = (SurfaceView) findViewById(R.id.sView);
// 设置该Surface不需要自己维护缓冲区
sView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 获得SurfaceView的SurfaceHolder
surfaceHolder = sView.getHolder();
// 为surfaceHolder添加一个回调监听器
surfaceHolder.addCallback(new Callback() {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 打开摄像头
initCamera();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 如果camera不为null ,释放摄像头
if (camera != null) {
if (isPreview)
camera.stopPreview();
camera.release();
camera = null;
}
}
});
}
private void initCamera() {
if (!isPreview) {
// 此处默认打开后置摄像头。
// 通过传入参数可以打开前置摄像头
camera = Camera.open(0); // ①
camera.setDisplayOrientation(90);
}
if (camera != null && !isPreview) {
try {
Camera.Parameters parameters = camera.getParameters();
// 设置预览照片的大小
parameters.setPreviewSize(screenWidth, screenHeight);
// 设置预览照片时每秒显示多少帧的最小值和最大值
parameters.setPreviewFpsRange(4, 10);
// 设置图片格式
parameters.setPictureFormat(ImageFormat.JPEG);
// 设置JPG照片的质量
parameters.set("jpeg-quality", 85);
// 设置照片的大小
parameters.setPictureSize(screenWidth, screenHeight);
// 通过SurfaceView显示取景画面
camera.setPreviewDisplay(surfaceHolder); // ②
// 开始预览
camera.startPreview(); // ③
} catch (Exception e) {
e.printStackTrace();
}
isPreview = true;
}
}
public void capture(View source) {
if (camera != null) {
// 控制摄像头自动对焦后才拍照
camera.autoFocus(autoFocusCallback); // ④
}
}
AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
// 当自动对焦时激发该方法
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
// takePicture()方法需要传入3个监听器参数
// 第1个监听器:当用户按下快门时激发该监听器
// 第2个监听器:当相机获取原始照片时激发该监听器
// 第3个监听器:当相机获取JPG照片时激发该监听器
camera.takePicture(new ShutterCallback() {
public void onShutter() {
// 按下快门瞬间会执行此处代码
}
}, new PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
// 此处代码可以决定是否需要保存原始照片信息
}
}, myJpegCallback); // ⑤
}
}
};
PictureCallback myJpegCallback = new PictureCallback() {
private Bitmap bm;
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 根据拍照所得的数据创建位图
bm = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.setRotate(90, bm.getWidth() / 2, bm.getHeight() / 2);
bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
// 加载/layout/save.xml文件对应的布局资源
View saveDialog = getLayoutInflater().inflate(R.layout.save, null);
final EditText photoName = (EditText) saveDialog.findViewById(R.id.phone_name);
// 获取saveDialog对话框上的ImageView组件
ImageView show = (ImageView) saveDialog.findViewById(R.id.show);
// 显示刚刚拍得的照片
show.setImageBitmap(bm);
// 使用对话框显示saveDialog组件
new AlertDialog.Builder(CapturePicActivity.this).setView(saveDialog).setPositiveButton("保存", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (photoName.length() < 1) {
try {
Toast.makeText(CapturePicActivity.this, "请输入文件名", Toast.LENGTH_SHORT).show();
Field field = dialog.getClass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
field.set(dialog, false);
dialog.dismiss();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
Field field = dialog.getClass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
field.set(dialog, true);
dialog.dismiss();
String pathName = Environment.getExternalStorageDirectory() + "/FNST/";
String fileName = photoName.getText().toString() + ".jpg";
File path = new File(pathName);
File file = new File(pathName + fileName);
System.out.println(pathName + fileName);
if (!path.exists()) {
path.mkdir();
Toast.makeText(getApplicationContext(), "创建目录", Toast.LENGTH_SHORT).show();
}
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream outStream = null;
// 打开指定文件对应的输出流
outStream = new FileOutputStream(file);
// 把位图输出到指定文件中
bm.compress(CompressFormat.JPEG, 100, outStream);
outStream.close();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).setNegativeButton("取消", null).show();
// 重新浏览
camera.stopPreview();
camera.startPreview();
isPreview = true;
}
};
public void browse(View view) {
Intent intent = new Intent(CapturePicActivity.this, BrowsePicActivity.class);
startActivity(intent);
isPreview = false;
}
}
FullScreenViewActivity.java
package com.example.activity;
import com.example.adapter.FullScreenImageAdapter;
import com.example.captureimage.R;
import com.example.help.Utils;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Adapter;
public class FullScreenViewActivity extends Activity {
private Utils utils;
private FullScreenImageAdapter adapter;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreenview_pic);
viewPager=(ViewPager) findViewById(R.id.pager);
utils=new Utils(this);
Intent intent=getIntent();
int position=intent.getIntExtra("position", 0);
adapter=new FullScreenImageAdapter(FullScreenViewActivity.this, utils.getFilePaths());
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(position);
}
}
FullScreenViewActivity.java
package com.example.activity;
import com.example.adapter.FullScreenImageAdapter;
import com.example.captureimage.R;
import com.example.help.Utils;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Adapter;
public class FullScreenViewActivity extends Activity {
private Utils utils;
private FullScreenImageAdapter adapter;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreenview_pic);
viewPager=(ViewPager) findViewById(R.id.pager);
utils=new Utils(this);
Intent intent=getIntent();
int position=intent.getIntExtra("position", 0);
adapter=new FullScreenImageAdapter(FullScreenViewActivity.this, utils.getFilePaths());
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(position);
}
}
FullScreenImageAdapter.java
package com.example.adapter;
import java.io.File;
import java.util.ArrayList;
import com.example.captureimage.R;
import android.R.integer;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class FullScreenImageAdapter extends PagerAdapter {
private Activity activity;
private ArrayList<String> fileNames;
private LayoutInflater inflater;
public FullScreenImageAdapter(Activity activity, ArrayList<String> fileNames) {
super();
this.activity = activity;
this.fileNames = fileNames;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return fileNames.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
// TODO Auto-generated method stub
return view == ((RelativeLayout) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView;
Button btnClose;
Button btnDelete;
final String fileName=fileNames.get(position);
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View viewLayout = inflater.inflate(R.layout.fullscreen_image,
container, false);
imageView = (ImageView) viewLayout.findViewById(R.id.imgDisplay);
btnClose = (Button) viewLayout.findViewById(R.id.btnClose);
btnDelete=(Button) viewLayout.findViewById(R.id.btnDelete);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(fileName,options);
imageView.setImageBitmap(bitmap);
btnClose.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
activity.finish();
}
});
btnDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
File file=new File(fileName);
file.delete();
activity.setResult(100);
activity.finish();
}
});
((ViewPager) container).addView(viewLayout);
return viewLayout;
}
@Override
public void destroyItem(ViewGroup container,int position,Object object){
((ViewPager) container).removeView((RelativeLayout) object);
}
}
GridViewImageAdapter.java
package com.example.adapter;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import com.example.activity.BrowsePicActivity;
import com.example.activity.FullScreenViewActivity;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
public class GridViewImageAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<String> filePaths=new ArrayList<String>();
private int imageWidth;
public GridViewImageAdapter(Activity activity,ArrayList<String> filePaths,int imageWidth) {
this.activity=activity;
this.filePaths=filePaths;
this.imageWidth=imageWidth;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return filePaths.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return filePaths.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if(convertView==null){
imageView=new ImageView(activity);
}else{
imageView = (ImageView) convertView;
}
Bitmap image=decodeFile(filePaths.get(position),imageWidth,imageWidth);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(imageWidth,
imageWidth));
imageView.setImageBitmap(image);
//imageView.setOnClickListener(new OnImageClickListener(position));
return imageView;
}
/*class OnImageClickListener implements OnClickListener {
int postion;
public OnImageClickListener(int position) {
this.postion=position;
}
@Override
public void onClick(View v) {
// on selecting grid view image
// launch full screen activity
Intent intent=new Intent(activity,FullScreenViewActivity.class);
intent.putExtra("position", postion);
activity.startActivity(intent);
activity.startActivityForResult(intent, 100);
}
}*/
/*
* Resizing image size
*/
private Bitmap decodeFile(String filePath, int WIDTH, int HEIGHT) {
try {
File f = new File(filePath);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_WIDTH = WIDTH;
final int REQUIRED_HIGHT = HEIGHT;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
}
AppConstant.java
package com.example.help;
import java.util.Arrays;
import java.util.List;
public class AppConstant {
// Number of columns of Grid View
public static final int NUM_OF_COLUMNS = 3;
// Gridview image padding
public static final int GRID_PADDING = 8; // in dp
// SD card image directory
public static final String PHOTO_ALBUM = "FNST";
// supported file formats
public static final List<String> FILE_EXTN = Arrays.asList("jpg", "jpeg",
"png");
}
Utils.java
package com.example.help;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Point;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
public class Utils {
private Context _context;
// constructor
public Utils(Context context) {
this._context = context;
}
/*
* Reading file paths from SDCard
*/
public ArrayList<String> getFilePaths() {
ArrayList<String> filePaths = new ArrayList<String>();
File directory = new File(
android.os.Environment.getExternalStorageDirectory()
+ File.separator + AppConstant.PHOTO_ALBUM);
// check for directory
if (directory.isDirectory()) {
// getting list of file paths
File[] listFiles = directory.listFiles();
// Check for count
if (listFiles.length > 0) {
// loop through all files
for (int i = 0; i < listFiles.length; i++) {
// get file path
String filePath = listFiles[i].getAbsolutePath();
// check for supported file extension
if (IsSupportedFile(filePath)) {
// Add image path to array list
filePaths.add(filePath);
}
}
} else {
// image directory is empty
Toast.makeText(
_context,
AppConstant.PHOTO_ALBUM
+ " is empty. Please load some images in it !",
Toast.LENGTH_LONG).show();
}
} else {
AlertDialog.Builder alert = new AlertDialog.Builder(_context);
alert.setTitle("Error!");
alert.setMessage(AppConstant.PHOTO_ALBUM
+ " directory path is not valid! Please set the image directory name AppConstant.java class");
alert.setPositiveButton("OK", null);
alert.show();
}
return filePaths;
}
/*
* Check supported file extensions
*
* @returns boolean
*/
private boolean IsSupportedFile(String filePath) {
String ext = filePath.substring((filePath.lastIndexOf(".") + 1),
filePath.length());
if (AppConstant.FILE_EXTN
.contains(ext.toLowerCase(Locale.getDefault())))
return true;
else
return false;
}
/*
* getting screen width
*/
public int getScreenWidth() {
int columnWidth;
WindowManager wm = (WindowManager) _context
.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
columnWidth = point.x;
return columnWidth;
}
}
button_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="3dp" />
<solid android:color="#000000" />
<stroke
android:width="2px"
android:color="#ffffff" />
</shape>
activity_browse_pic.xml
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:gravity="center"
android:stretchMode="columnWidth"
android:background="#000000">
</GridView>
activity_fullscreenview_pic.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
fullscreen_image.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
android:id="@+id/imgDisplay"
/>
<Button
android:id="@+id/btnClose"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="15dp"
android:layout_marginTop="15dp"
android:background="@drawable/button_background"
android:paddingBottom="2dp"
android:paddingTop="2dp"
android:text="Close"
android:textColor="#ffffff" />
<Button
android:id="@+id/btnDelete"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:background="@drawable/button_background"
android:paddingBottom="2dp"
android:paddingTop="2dp"
android:text="Delete"
android:textColor="#ffffff" />
</RelativeLayout>
添加一个手势缩放
package com.example.view;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class TouchImageView extends ImageView {
Matrix matrix;
// 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;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
int viewWidth, viewHeight;
static final int CLICK = 3;
float saveScale = 1f;
protected float origWidth, origHeight;
int oldMeasuredWidth, oldMeasuredHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public TouchImageView(Context context) {
super(context);
sharedConstructing(context);
}
public TouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
sharedConstructing(context);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix = new Matrix();
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(curr);
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
matrix.postTranslate(fixTransX, fixTransY);
fixTrans();
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
}
});
}
public void setMaxZoom(float x) {
maxScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
else
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
fixTrans();
return true;
}
}
void fixTrans() {
matrix.getValues(m);
float transX = m[Matrix.MTRANS_X];
float transY = m[Matrix.MTRANS_Y];
float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);
if (fixTransX != 0 || fixTransY != 0)
matrix.postTranslate(fixTransX, fixTransY);
}
float getFixTrans(float trans, float viewSize, float contentSize) {
float minTrans, maxTrans;
if (contentSize <= viewSize) {
minTrans = 0;
maxTrans = viewSize - contentSize;
} else {
minTrans = viewSize - contentSize;
maxTrans = 0;
}
if (trans < minTrans)
return -trans + minTrans;
if (trans > maxTrans)
return -trans + maxTrans;
return 0;
}
float getFixDragTrans(float delta, float viewSize, float contentSize) {
if (contentSize <= viewSize) {
return 0;
}
return delta;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
//
// Rescales image on rotation
//
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight || viewWidth == 0 || viewHeight == 0)
return;
oldMeasuredHeight = viewHeight;
oldMeasuredWidth = viewWidth;
if (saveScale == 1) {
// Fit to screen.
float scale;
Drawable drawable = getDrawable();
if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
return;
int bmWidth = drawable.getIntrinsicWidth();
int bmHeight = drawable.getIntrinsicHeight();
Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
float scaleX = (float) viewWidth / (float) bmWidth;
float scaleY = (float) viewHeight / (float) bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
// Center the image
float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = viewWidth - 2 * redundantXSpace;
origHeight = viewHeight - 2 * redundantYSpace;
setImageMatrix(matrix);
}
fixTrans();
}
}