自定义了gallary和ImageView:
gallary:
public class MyGallery extends Gallery {
/**
* GestureDetector类 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,
* 将捕捉到的MotionEvent交给GestureDetector 来分析是否有合适的callback函数来处理用户的手势
*/
private GestureDetector gestureScanner;
private MyPicImageView imageView;
public MyGallery(Context context) {
super(context);
}
public MyGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyGallery(Context context, AttributeSet attrs) {
super(context, attrs);
gestureScanner = new GestureDetector(new MySimpleGesture());
this.setOnTouchListener(new OnTouchListener() {
float baseValue;
float originalScale;
// 重写onTouch方法实现缩放
@Override
public boolean onTouch(View v, MotionEvent event) {
RelativeLayout relayout = (RelativeLayout) MyGallery.this
.getSelectedView();
View view = relayout.findViewById(R.id.pic);
if (view instanceof MyPicImageView) {
imageView = (MyPicImageView) view;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
baseValue = 0;
originalScale = imageView.getScale();
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
// 处理拖动
if (event.getPointerCount() == 2) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
float value = (float) Math.sqrt(x * x + y * y);// 计算两点的距离
if (baseValue == 0) {
baseValue = value;
}
float scale = value / baseValue;// 当前两点间的距离除以手指落下时两点间的距离就是需要缩放的比例。
// scale the image
imageView.zoomTo(originalScale * scale,
x + event.getX(1), y + event.getY(1));
}
}
}
return false;
}
});
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
RelativeLayout relayout = (RelativeLayout) MyGallery.this
.getSelectedView();
View view = relayout.findViewById(R.id.pic);
if (view instanceof MyPicImageView) {
imageView = (MyPicImageView) view;
float v[] = new float[9];
Matrix m = imageView.getImageMatrix();
m.getValues(v);
// 图片实时的上下左右坐标
float left, right;
// 图片的实时宽,高
float width, height;
width = imageView.getScale() * imageView.getImageWidth();
height = imageView.getScale() * imageView.getImageHeight();
// 下面逻辑为移动图片和滑动gallery换屏的逻辑。如果没对整个框架了解的非常清晰,勿动以下代码
if ((int) width <= EnLargePicActivity.screenWidth
&& (int) height <= EnLargePicActivity.screenHeight)// 如果图片当前大小<屏幕大小,直接处理滑屏事件
{
super.onScroll(e1, e2, distanceX, distanceY);
} else {
left = v[Matrix.MTRANS_X];
right = left + width;
Rect r = new Rect();
imageView.getGlobalVisibleRect(r);
// Log.i("lyc", "distanceX:" +
// distanceX+"r.left::"+r.left+"r.right::"+r.right+"distanceY::"+distanceY+"r.top::"+r.top+"r.bottom::"+r.bottom);
if (distanceX > 0)// 向左滑动
{
if (r.left > 0) {// 判断当前ImageView是否显示完全
super.onScroll(e1, e2, distanceX, distanceY);
} else if (right < EnLargePicActivity.screenWidth) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
} else if (distanceX < 0)// 向右滑动
{
if (r.right < EnLargePicActivity.screenWidth) {
super.onScroll(e1, e2, distanceX, distanceY);
} else if (left > 0) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
}
if (distanceY > 0) {// 向下滑
imageView.postTranslate(-distanceX, -distanceY);
} else {// 向上滑
imageView.postTranslate(-distanceX, -distanceY);
}
}
} else {
super.onScroll(e1, e2, distanceX, distanceY);
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;// 这样
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureScanner.onTouchEvent(event);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
// 判断上下边界是否越界
RelativeLayout relayout = (RelativeLayout) MyGallery.this
.getSelectedView();
View view = relayout.findViewById(R.id.pic);
if (view instanceof MyPicImageView) {
imageView = (MyPicImageView) view;
float width = imageView.getScale() * imageView.getImageWidth();
float height = imageView.getScale()
* imageView.getImageHeight();
if ((int) width <= EnLargePicActivity.screenWidth&& (int) height <= EnLargePicActivity.screenHeight)// 如果图片当前大小<屏幕大小,判断边界
{break;
}
float v[] = new float[9];
Matrix m = imageView.getImageMatrix();
m.getValues(v);
float top = v[Matrix.MTRANS_Y];
float bottom = top + height;
if (top > 0) {
imageView.postTranslateDur(-top, 200f);
}Log.i("lyc", "bottom:" + bottom);
if (bottom < EnLargePicActivity.screenHeight) {
imageView.postTranslateDur(EnLargePicActivity.screenHeight
- bottom, 200f);
}
}
break;
}
return super.onTouchEvent(event);
}
private class MySimpleGesture extends SimpleOnGestureListener {
// 按两下的第二下Touch down时触发
public boolean onDoubleTap(MotionEvent e) {
RelativeLayout relayout = (RelativeLayout) MyGallery.this
.getSelectedView();
View view = relayout.findViewById(R.id.pic);
if (view instanceof MyPicImageView) {
imageView = (MyPicImageView) view;
if (imageView.getScale() > imageView.getScaleRate()) {
imageView.zoomTo(imageView.getScaleRate(),
EnLargePicActivity.screenWidth / 2,
EnLargePicActivity.screenHeight / 2, 200f);
// imageView.layoutToCenter();
} else {
imageView.zoomTo(1.0f, EnLargePicActivity.screenWidth / 2,
EnLargePicActivity.screenHeight / 2, 200f);
}
} else {
}
// return super.onDoubleTap(e);
return true;
}
}
}
ImageView::::::::::::::
public class MyPicImageView extends ImageView {
public MyPicImageView(Context context) {
super(context);
init();
}
public MyPicImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyPicImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@SuppressWarnings("unused")
private static final String TAG = "ImageViewTouchBase";
protected Matrix mBaseMatrix = new Matrix();
protected Matrix mSuppMatrix = new Matrix();
private final Matrix mDisplayMatrix = new Matrix();
private final float[] mMatrixValues = new float[9];
protected Bitmap image = null;
int mThisWidth = -1, mThisHeight = -1;
float mMaxZoom = 3f;// 最大缩放比例
float mMinZoom=0.1f;// 最小缩放比例
private int imageWidth;// 图片的原始宽度
private int imageHeight;// 图片的原始高度
private float scaleRate;// 图片适应屏幕的缩放比例
/**
* 解决放大后超出屏幕大小的图片上滑,下滑总是靠顶部或底部停靠
*/
protected void onDraw(Canvas canvas) {
// 正在显示的图片实际宽高
float width = imageWidth * getScale();
float height = imageHeight * getScale();
if (width > EnLargePicActivity.screenWidth) {
// 如果图宽大于屏宽,就不用水平居中
center(true, true);
} else {
center(true, true);
}super.onDraw(canvas);
}
/**
* 计算图片要适应屏幕需要缩放的比例
*/
private void arithScaleRate() {
float scaleWidth = EnLargePicActivity.screenWidth / (float) imageWidth;
float scaleHeight = EnLargePicActivity.screenHeight
/ (float) imageHeight;
scaleRate = Math.min(scaleWidth, scaleHeight);}
public float getScaleRate() {
return scaleRate;
}
public int getImageWidth() {
return imageWidth;
}
public void setImageWidth(int imageWidth) {
this.imageWidth = imageWidth;
}
public int getImageHeight() {
return imageHeight;
}
public void setImageHeight(int imageHeight) {
this.imageHeight = imageHeight;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
event.startTracking();
return true;
}return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
&& !event.isCanceled()) {
if (getScale() > 1.0f) {
zoomTo(1.0f);
return true;
}
}
return super.onKeyUp(keyCode, event);
}
protected Handler mHandler = new Handler();
@Override
public void setImageBitmap(Bitmap bitmap) {
super.setImageBitmap(bitmap);
image = bitmap;
// 计算适应屏幕的比例
arithScaleRate();
// 缩放到屏幕大小
zoomTo(scaleRate, EnLargePicActivity.screenWidth / 2f,
EnLargePicActivity.screenHeight / 2f);
// 居中
layoutToCenter();
}
protected void center(boolean horizontal, boolean vertical) {
if (image == null) {
return;
}
Matrix m = getImageViewMatrix();
RectF rect = new RectF(0, 0, image.getWidth(), image.getHeight());
m.mapRect(rect);
float height = rect.height();
float width = rect.width();
float deltaX = 0, deltaY = 0;
if (vertical) {
int viewHeight = getHeight();
if (height < viewHeight) {
deltaY = (viewHeight - height) / 2 - rect.top;
} else if (rect.top > 0) {
deltaY = -rect.top;
} else if (rect.bottom < viewHeight) {
deltaY = getHeight() - rect.bottom;
}
}
if (horizontal) {
int viewWidth = getWidth();
if (width < viewWidth) {
deltaX = (viewWidth - width) / 2 - rect.left;
} else if (rect.left > 0) {
deltaX = -rect.left;
} else if (rect.right < viewWidth) {
deltaX = viewWidth - rect.right;
}}
postTranslate(deltaX, deltaY);
setImageMatrix(getImageViewMatrix());
}
private void init() {
setScaleType(ImageView.ScaleType.MATRIX);
}
/**
* 设置图片居中显示
*/
public void layoutToCenter() {
// 正在显示的图片实际宽高
float width = imageWidth * getScale();
float height = imageHeight * getScale();
// 空白区域宽高
float fill_width = EnLargePicActivity.screenWidth - width;
float fill_height = EnLargePicActivity.screenHeight - height;
// 需要移动的距离
float tran_width = 0f;
float tran_height = 0f;
if (fill_width > 0)
tran_width = fill_width / 2;
if (fill_height > 0)
tran_height = fill_height / 2;
postTranslate(tran_width, tran_height);
setImageMatrix(getImageViewMatrix());
}
protected float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
mMinZoom = (EnLargePicActivity.screenWidth / 2f) / imageWidth;
return mMatrixValues[whichValue];
}
protected float getScale(Matrix matrix) {
return getValue(matrix, Matrix.MSCALE_X);
}
protected float getScale() {
return getScale(mSuppMatrix);
}
protected Matrix getImageViewMatrix() {
mDisplayMatrix.set(mBaseMatrix);
mDisplayMatrix.postConcat(mSuppMatrix);
return mDisplayMatrix;
}
static final float SCALE_RATE = 1.25F;
protected float maxZoom() {
if (image == null) {
return 1F;
}
float fw = (float) image.getWidth() / (float) mThisWidth;
float fh = (float) image.getHeight() / (float) mThisHeight;
float max = Math.max(fw, fh) * 4;
return max;
}
protected void zoomTo(float scale, float centerX, float centerY) {
float oldScale = getScale();
if (scale > mMaxZoom) {
scale = mMaxZoom;
} else if (scale < mMinZoom) {
scale = mMinZoom;
}
float deltaScale = scale / oldScale;
mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);
setImageMatrix(getImageViewMatrix());
center(true, true);
}
protected void zoomTo(final float scale, final float centerX,
final float centerY, final float durationMs) {
final float incrementPerMs = (scale - getScale()) / durationMs;
final float oldScale = getScale();
final long startTime = System.currentTimeMillis();
mHandler.post(new Runnable() {
public void run() {
long now = System.currentTimeMillis();
float currentMs = Math.min(durationMs, now - startTime);
float target = oldScale + (incrementPerMs * currentMs);
zoomTo(target, centerX, centerY);
if (currentMs < durationMs) {
mHandler.post(this);
}
}
});
}
protected void zoomTo(float scale) {
float cx = getWidth() / 2F;
float cy = getHeight() / 2F;
zoomTo(scale, cx, cy);
}
protected void zoomToPoint(float scale, float pointX, float pointY) {
float cx = getWidth() / 2F;
float cy = getHeight() / 2F;
panBy(cx - pointX, cy - pointY);
zoomTo(scale, cx, cy);
}
protected void zoomIn() {
zoomIn(SCALE_RATE);
}
protected void zoomOut() {
zoomOut(SCALE_RATE);
}
protected void zoomIn(float rate) {
if (getScale() >= mMaxZoom) {
return;
} else if (getScale() <= mMinZoom) {
return;
}
if (image == null) {
return;
}
float cx = getWidth() / 2F;
float cy = getHeight() / 2F;
mSuppMatrix.postScale(rate, rate, cx, cy);
setImageMatrix(getImageViewMatrix());
}
protected void zoomOut(float rate) {
if (image == null) {
return;
}
float cx = getWidth() / 2F;
float cy = getHeight() / 2F;
Matrix tmp = new Matrix(mSuppMatrix);
tmp.postScale(1F / rate, 1F / rate, cx, cy);
if (getScale(tmp) < 1F) {
mSuppMatrix.setScale(1F, 1F, cx, cy);
} else {mSuppMatrix.postScale(1F / rate, 1F / rate, cx, cy);
}setImageMatrix(getImageViewMatrix());
center(true, true);
}
public void postTranslate(float dx, float dy) {
mSuppMatrix.postTranslate(dx, dy);
setImageMatrix(getImageViewMatrix());}
float _dy = 0.0f;
protected void postTranslateDur(final float dy, final float durationMs) {
_dy = 0.0f;
final float incrementPerMs = dy / durationMs;
final long startTime = System.currentTimeMillis();
mHandler.post(new Runnable() {
public void run() {long now = System.currentTimeMillis();
float currentMs = Math.min(durationMs, now - startTime);
postTranslate(0, incrementPerMs * currentMs - _dy);
_dy = incrementPerMs * currentMs;
if (currentMs < durationMs) {
mHandler.post(this);
}}
});
}
protected void panBy(float dx, float dy) {
postTranslate(dx, dy);
setImageMatrix(getImageViewMatrix());
}}
xml文件布局::::::::::::
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.hztbc.android.definedview.MyPicImageView
android:id="@+id/pic"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="matrix"
android:layout_centerInParent="true"
></com.hztbc.android.definedview.MyPicImageView>
<ProgressBar
android:id="@+id/pb"
android:layout_width="wrap_content"
android:focusable="false"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
主Activity:::::::::::::::::::
public class EnLargePicActivity extends BaseActivity {
/** Called when the activity is first created. */
// 屏幕的宽度
public static int screenWidth;
// 屏幕的高度
public static int screenHeight;
private MyGallery gallery;
private ArrayList<String> urls;
private int position;
private static PicCache bitMapUtilPublic;
GalleryAdapter galleryAdapter;
@InjectView(R.id.num)
TextView num;
TextView pathTV;
@InjectView(R.id.content)
private RelativeLayout contentRL;
private String imagePaht = null;
private int m_scaleW, m_scaleH;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置窗体无标题 全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main_gallary);
bitMapUtilPublic = new PicCache();
urls = this.getIntent().getStringArrayListExtra("url");
position = this.getIntent().getIntExtra("position", -1);
gallery = (MyGallery) findViewById(R.id.mygallery);
gallery.setVerticalFadingEdgeEnabled(false);
gallery.setHorizontalFadingEdgeEnabled(false);// 设置view在水平滚动时,水平边不淡出。
galleryAdapter = new GalleryAdapter(this, urls, bitMapUtilPublic);
gallery.setAdapter(galleryAdapter);
gallery.setSelection(position);
gallery.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.i("--xxl--", "onItemClick:::::" + position + "");
num.setText((position + 1) + "/" + urls}
});
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
if(view==null){
view=LayoutInflater.from(getApplicationContext()).inflate(R.layout.gallary_image_item, null);}
num.setText((position + 1) + "/" + urls.size());
GalleryWhetherStop(position, view);}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// 获取屏幕的大小
int statusBarHeight = ViewUtil.getStatusBarHeight(getResources());
screenWidth = getWindow().getWindowManager().getDefaultDisplay()
.getWidth();
screenHeight = getWindow().getWindowManager().getDefaultDisplay()
.getHeight()
- statusBarHeight;
Log.i("--xxl--", "screenWidth::::::::"+screenWidth+"screenHeight:::::::"+screenHeight);
pathTV = new TextView(this);
pathTV.setTextColor(Color.WHITE);
pathTV.setGravity(Gravity.CENTER_HORIZONTAL);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.mygallery);
contentRL.addView(pathTV, layoutParams);
gallery.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
Log.i("--xxl--", "onLongClick:::::");
SaveImgSelectDialog fileSelectDialog = new SaveImgSelectDialog(EnLargePicActivity.this,R.style.MyDialog){
@Override
public void doSaveImg() {this.dismiss();
Intent intent = new Intent(EnLargePicActivity.this,
FileManagerActivity.class);
intent.putExtra("flag", true);
startActivityForResult(intent, 100);}
};
fileSelectDialog.show();
Window dialogWindow = fileSelectDialog.getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
dialogWindow.setGravity(Gravity.BOTTOM);
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
lp.width = (int)(display.getWidth()); //设置宽度
fileSelectDialog.getWindow().setAttributes(lp);
return true; }
});}
protected void GalleryWhetherStop(final int position, View view) {
final String url = urls.get(position).toString();
final MyPicImageView imageView = (MyPicImageView) view
.findViewById(R.id.pic);
final ProgressBar pb = (ProgressBar) view.findViewById(R.id.pb);
if (!"null".equals(url) && !"".equals(url) && url != null) {
FileLoader.getImageAsync(url, new FileCache.FileDownLoad() {
Bitmap bmp;
@Override
public void onFileLoaded(final File localFile, String remoteurl) {
EnLargePicActivity.this.imagePaht = localFile
.getAbsolutePath();
runOnUiThread(new Runnable() {
bmp = bitMapUtilPublic.getBitmap(localFile
.getAbsolutePath());
if (bmp == null || bmp.isRecycled()) {
imageView.setImageBitmap(null);
} else {
Log.i("--xxl--", "Width::::::::"+bmp.getWidth()+"Height:::::::"+bmp.getHeight());
imageView.setImageHeight(bmp.getHeight());
imageView.setImageWidth(bmp.getWidth());
imageView.setImageBitmap(bmp);
imageView.invalidate();
pb.setVisibility(View.GONE);
}
}
});}
@Override
public void onLoading(long filelenght, long downloadedlenght,final int percent) {}
});
}}
@Override
protected void onDestroy() {
bitMapUtilPublic.removeAllBitMap();
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode == RESULT_OK) {
String path = data.getStringExtra("path");
String message = FileUtil.copyFile(this.imagePaht, path + "/");
showMessage(message);
pathTV.setText("已保存至" + path + "文件夹下");
}
}