找了一些demo感觉没有自己想要的效果,于是借鉴一些改造一下并记录下来;
1、主Activity
public class PictureViewFra extends Activity {
private PicGallery gallery;
// private ViewGroup tweetLayout; // 弹层
private boolean mTweetShow = false; // 弹层是否显示
// 屏幕宽度
public static int screenWidth;
// 屏幕高度
public static int screenHeight;
private GalleryAdapter mAdapter;
private ArrayList helpTopicImage = new ArrayList();
private int position = 0;
// private ProgressDialog mProgress;
private TextView tv_img_count,tv_topic_title;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.picture_view);
getIntentData();
tv_img_count = (TextView)findViewById(R.id.tv_img_count);
tv_topic_title = (TextView)findViewById(R.id.tv_topic_title);
gallery = (PicGallery) findViewById(R.id.pic_gallery);
gallery.setVerticalFadingEdgeEnabled(false);// 取消竖直渐变边框
gallery.setHorizontalFadingEdgeEnabled(false);// 取消水平渐变边框
gallery.setDetector(new GestureDetector(this,
new MySimpleGesture()));
mAdapter = new GalleryAdapter(this,helpTopicImage,position);
gallery.setAdapter(mAdapter);
gallery.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView> arg0, View arg1, int arg2, long arg3) {
return false;
}
});
mAdapter.getPositionListener(new GalleryAdapter.GalleryPositionListener() {
@Override
public void movePosition(int index) {
Log.d("helpTopicImage--> ", " " + index);
tv_img_count.setText((index+1)+"/"+helpTopicImage.size());
tv_topic_title.setText(helpTopicImage.get(index).getImgInfo());
}
});
// mAdapter.setData(dataResult);
initViews();
// mProgress = ProgressDialog.show(getActivity(),
// null,getActivity().getString(R.string.loading));
}
private void getIntentData() {
Intent intent = getIntent();
helpTopicImage = (ArrayList)intent.getSerializableExtra("helpTopicImage");
position = intent.getIntExtra("position", 0);
}
private void initViews() {
screenWidth = getWindow().getWindowManager().getDefaultDisplay()
.getWidth();
screenHeight = getWindow().getWindowManager().getDefaultDisplay()
.getHeight();
}
private class MySimpleGesture extends SimpleOnGestureListener {
// 按两下的第二下Touch down时触发
public boolean onDoubleTap(MotionEvent e) {
View view = gallery.getSelectedView();
if (view instanceof MyImageView) {
MyImageView imageView = (MyImageView) view;
if (imageView.getScale() > imageView.getMiniZoom()) {
imageView.zoomTo(imageView.getMiniZoom());
} else {
imageView.zoomTo(imageView.getMaxZoom());
}
} else {
}
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// Logger.LOG("onSingleTapConfirmed",
// "onSingleTapConfirmed excute");
// mTweetShow = !mTweetShow;
// tweetLayout.setVisibility(mTweetShow ? View.VISIBLE
// : View.INVISIBLE);
return true;
}
}
}
public class GalleryAdapter extends BaseAdapter {
private Context context;
private ArrayList imageViews = new ArrayList();
private GalleryPositionListener positionListener;
private ArrayList helpTopicImage = new ArrayList();
private int position = 0;
private ArrayList bitmaps = new ArrayList();
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
Bitmap bitmap = (Bitmap) msg.obj;
Bundle bundle = msg.getData();
String url = bundle.getString("url");
for (int i = 0; i < imageViews.size(); i++) {
if (imageViews.get(i).getTag().equals(url)) {
imageViews.get(i).setImageBitmap(bitmap);
}
}
}
};
public void setData(List data) {
notifyDataSetChanged();
}
public GalleryAdapter(Context context,ArrayList helpTopicImage,int position) {
this.context = context;
this.helpTopicImage = helpTopicImage;
this.position = position;
for(int i=0; i
public class PicGallery extends Gallery {
private GestureDetector gestureScanner;
private MyImageView imageView;
public PicGallery(Context context) {
super(context);
}
public PicGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setDetector(GestureDetector dectector) {
gestureScanner = dectector;
}
public PicGallery(Context context, AttributeSet attrs) {
super(context, attrs);
this.setOnTouchListener(new OnTouchListener() {
float baseValue;
float originalScale;
@Override
public boolean onTouch(View v, MotionEvent event) {
View view = PicGallery.this.getSelectedView();
if (view instanceof MyImageView) {
imageView = (MyImageView) 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);// 计算两点的距离
// System.out.println("value:" + value);
if (baseValue == 0) {
baseValue = value;
} else {
float scale = value / baseValue;// 当前两点间的距离除以手指落下时两点间的距离就是需要缩放的比例。
// scale the image
imageView.zoomTo(originalScale * scale, x
+ event.getX(1), y + event.getY(1));
}
}
}
}
return false;
}
});
}
float v[] = new float[9];
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
View view = PicGallery.this.getSelectedView();
if (view instanceof MyImageView) {
float xdistance = calXdistance(e1, e2);
float min_distance = PictureViewFra.screenWidth / 4f;
if (isScrollingLeft(e1, e2) && xdistance > min_distance) {
kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
} else if (!isScrollingLeft(e1, e2) && xdistance > min_distance) {
kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
}
imageView = (MyImageView) view;
Matrix m = imageView.getImageMatrix();
m.getValues(v);
// 图片实时的上下左右坐标
float left, right;
// 图片的实时宽,高
float width = imageView.getScale() * imageView.getImageWidth();
float height = imageView.getScale() * imageView.getImageHeight();
if ((int) width <= PictureViewFra.screenWidth
&& (int) height <= PictureViewFra.screenHeight)// 如果图片当前大小<屏幕大小,直接处理滑屏事件
{
super.onScroll(e1, e2, distanceX, distanceY);
} else {
left = v[Matrix.MTRANS_X];
right = left + width;
Rect r = new Rect();
imageView.getGlobalVisibleRect(r);
if (distanceX > 0)// 向左滑动
{
if (r.left > 0 || right < PictureViewFra.screenWidth) {// 判断当前ImageView是否显示完全
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
} else if (distanceX < 0)// 向右滑动
{
if (r.right < PictureViewFra.screenWidth || left > 0) {
super.onScroll(e1, e2, distanceX, distanceY);
} else {
imageView.postTranslate(-distanceX, -distanceY);
}
}
}
} else {
super.onScroll(e1, e2, distanceX, distanceY);
}
return false;
}
private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {
return e2.getX() > e1.getX();
}
private float calXdistance(MotionEvent e1, MotionEvent e2) {
return Math.abs(e2.getX() - e1.getX());
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//Logger.d(DEBUG,"[PicGallery.onTouchEvent]"+"PicGallery.onTouchEvent");
if (gestureScanner != null) {
gestureScanner.onTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 判断边界是否越界
View view = PicGallery.this.getSelectedView();
if (view instanceof MyImageView) {
if(kEvent != KEY_INVALID) { // 是否切换上一页或下一页
onKeyDown(kEvent, null);
kEvent = KEY_INVALID;
}
imageView = (MyImageView) view;
float width = imageView.getScale() * imageView.getImageWidth();
float height = imageView.getScale()
* imageView.getImageHeight();
// Logger.LOG("onTouchEvent", "width=" + width + ",height="
// + height + ",screenWidth="
// + PictureViewActivity.screenWidth + ",screenHeight="
// + PictureViewActivity.screenHeight);
if ((int) width <= PictureViewFra.screenWidth
&& (int) height <= PictureViewFra.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 && bottom < PictureViewFra.screenHeight) {
// imageView.postTranslateDur(-top, 200f);
imageView.postTranslateDur(PictureViewFra.screenHeight
- bottom, 200f);
}
if (top > 0 && bottom > PictureViewFra.screenHeight) {
// imageView.postTranslateDur(PictureViewActivity.screenHeight
// - bottom, 200f);
imageView.postTranslateDur(-top, 200f);
}
float left =v[Matrix.MTRANS_X];
float right = left + width;
if(left<0 && right< PictureViewFra.screenWidth){
// imageView.postTranslateXDur(-left, 200f);
imageView.postTranslateXDur(PictureViewFra.screenWidth
- right, 200f);
}
if(left>0 && right>PictureViewFra.screenWidth){
// imageView.postTranslateXDur(PictureViewActivity.screenWidth
// - right, 200f);
imageView.postTranslateXDur(-left, 200f);
}
}
break;
}
return super.onTouchEvent(event);
}
int kEvent = KEY_INVALID; //invalid
public static final int KEY_INVALID = -1;
}
public class MyImageView extends ImageView {
// This is the base transformation which is used to show the image
// initially. The current computation for this shows the image in
// it's entirety, letterboxing as needed. One could choose to
// show the image as cropped instead.
//
// This matrix is recomputed when we go from the thumbnail image to
// the full size image.
protected Matrix mBaseMatrix = new Matrix();
// This is the supplementary transformation which reflects what
// the user has done in terms of zooming and panning.
//
// This matrix remains the same when we go from the thumbnail image
// to the full size image.
protected Matrix mSuppMatrix = new Matrix();
// This is the final matrix which is computed as the concatentation
// of the base matrix and the supplementary matrix.
private final Matrix mDisplayMatrix = new Matrix();
// Temporary buffer used for getting the values out of a matrix.
private final float[] mMatrixValues = new float[9];
// The current bitmap being displayed.
protected Bitmap image = null;
protected Handler mHandler = new Handler();
int mThisWidth = -1, mThisHeight = -1;//布局后的宽度和高度,由于是全屏显示,这两个值等于屏幕分辨率
float mMaxZoom;// 最大缩放比例
float mMinZoom;// 最小缩放比例
private int imageWidth;// 图片的原始宽度
private int imageHeight;// 图片的原始高度
// float scaleRate;// 图片适应屏幕的缩放比例
static final float SCALE_RATE = 1.25F;
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyImageView(Context context) {
super(context);
init();
}
@Override
public void setImageBitmap(Bitmap bitmap) {
super.setImageBitmap(bitmap);
image = bitmap;
setImageHeight(bitmap.getHeight());
setImageWidth(bitmap.getWidth());
Drawable d = getDrawable();
if (d != null) {
d.setDither(true);
}
}
// Center as much as possible in one or both axis. Centering is
// defined as follows: if the image is scaled down below the
// view's dimensions then center it (literally). If the image
// is scaled larger than the view and is translated out of view
// then translate it back into view (i.e. eliminate black bars).
protected void center(boolean horizontal, boolean vertical) {
if (image == null) {
return;
}
Matrix m = getImageViewMatrix();
RectF rect = new RectF(0, 0, image.getWidth(), image.getHeight());
// RectF rect = new RectF(0, 0, imageWidth*getScale(),
// imageHeight*getScale());
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(ScaleType.MATRIX);
}
// Setup the base matrix so that the image is centered and scaled properly.
private void getProperBaseMatrix(Bitmap bitmap, Matrix matrix) {
float viewWidth = getWidth();
float viewHeight = getHeight();
float w = bitmap.getWidth();
float h = bitmap.getHeight();
matrix.reset();
// We limit up-scaling to 3x otherwise the result may look bad if it's
// a small icon.
float scale = Math.min(viewWidth / w, viewHeight / h);
mMinZoom = scale;
mMaxZoom = 2*scale;
matrix.postScale(scale, scale);
matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h
* scale) / 2F);
}
protected float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
return mMatrixValues[whichValue];
}
// Get the scale factor out of the matrix.
protected float getScale(Matrix matrix) {
return getValue(matrix, Matrix.MSCALE_X);
}
public float getScale() {
return getScale(mSuppMatrix)*mMinZoom;
}
public float getScaleRate() {
return getScale(mSuppMatrix);
}
public float getMiniZoom() {
return mMinZoom;
}
public float getMaxZoom() {
return mMaxZoom;
}
// Combine the base matrix and the supp matrix to make the final matrix.
protected Matrix getImageViewMatrix() {
// The final matrix is computed as the concatentation of the base matrix
// and the supplementary matrix.
mDisplayMatrix.set(mBaseMatrix);
mDisplayMatrix.postConcat(mSuppMatrix);
return mDisplayMatrix;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
mThisWidth = right - left;
mThisHeight = bottom - top;
if (image != null) {
getProperBaseMatrix(image, mBaseMatrix);
setImageMatrix(getImageViewMatrix());
}
}
protected void zoomTo(float scale, float centerX, float centerY) {
if (scale > mMaxZoom) {
scale = mMaxZoom;
} else if (scale < mMinZoom) {
scale = mMinZoom;
}
float oldScale = getScale();
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);
}
}
});
}
public 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; // Don't let the user zoom into the molecular level.
}
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;
// Zoom out to at most 1x.
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);
}
}
});
}
float _dx = 0.0f;
protected void postTranslateXDur(final float dx, final float durationMs) {
_dx = 0.0f;
final float incrementPerMs = dx / 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(incrementPerMs * currentMs - _dx, 0);
_dx = incrementPerMs * currentMs;
if (currentMs < durationMs) {
mHandler.post(this);
}
}
});
}
protected void panBy(float dx, float dy) {
postTranslate(dx, dy);
setImageMatrix(getImageViewMatrix());
}
@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() > mMinZoom) {
zoomTo(mMinZoom);
return true;
}
}
return super.onKeyUp(keyCode, event);
}
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;
}
}