转载请注明原文出处:奔跑的蜗牛(袁方的技术博客)点击打开链接
原始图片:
点击放大按钮,或两手拖拉屏幕。
上代码:
public class main extends Activity
{
/** Called when the activity is first created. */
private ImageZoomView mZoomView;
private ZoomState mZoomState;
private Bitmap mBitmap;
private SimpleZoomListener mZoomListener;
private ProgressBar progressBar;
private Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
progressBar.setVisibility(View.GONE);
mZoomView.setImage(mBitmap);
mZoomState = new ZoomState();
mZoomView.setZoomState(mZoomState);
mZoomListener = new SimpleZoomListener();
mZoomListener.setZoomState(mZoomState);
mZoomView.setOnTouchListener(mZoomListener);
resetZoomState();
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// 隐藏顶部程序名称 写在setContentView(R.layout.xxxx);之前,不然报错
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 隐藏状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_image);
mZoomView = (ImageZoomView) findViewById(R.id.zoomView);
progressBar = (ProgressBar) findViewById(R.id.progress_large);
progressBar.setVisibility(View.VISIBLE);
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
/*
* 加载网络图片 load form url
*/
// mBitmap =
// ImageDownloader.getInstance().getBitmap(url);
mBitmap = BitmapFactory.decodeResource(
main.this.getResources(), R.drawable.test);
handler.sendEmptyMessage(0);
}
});
thread.start();
ZoomControls zoomCtrl = (ZoomControls) findViewById(R.id.zoomCtrl);
zoomCtrl.setOnZoomInClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
float z = mZoomState.getZoom() + 0.25f;
mZoomState.setZoom(z);
mZoomState.notifyObservers();
}
});
zoomCtrl.setOnZoomOutClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
float z = mZoomState.getZoom() - 0.25f;
mZoomState.setZoom(z);
mZoomState.notifyObservers();
}
});
}
@Override
protected void onDestroy()
{
super.onDestroy();
if (mBitmap != null)
mBitmap.recycle();
}
private void resetZoomState()
{
mZoomState.setPanX(0.5f);
mZoomState.setPanY(0.5f);
mZoomState.setZoom(1f);
mZoomState.notifyObservers();
}
}
public class ImageZoomView extends View implements Observer
{
private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
private final Rect mRectSrc = new Rect();
private final Rect mRectDst = new Rect();
private float mAspectQuotient;
private Bitmap mBitmap;
private ZoomState mState;
public ImageZoomView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public void setZoomState(ZoomState state)
{
if (mState != null)
{
mState.deleteObserver(this);
}
mState = state;
mState.addObserver(this);
invalidate();
}
protected void onDraw(Canvas canvas)
{
if (mBitmap != null && mState != null)
{
final int viewWidth = getWidth();
final int viewHeight = getHeight();
final int bitmapWidth = mBitmap.getWidth();
final int bitmapHeight = mBitmap.getHeight();
final float panX = mState.getPanX();
final float panY = mState.getPanY();
final float zoomX = mState.getZoomX(mAspectQuotient) * viewWidth
/ bitmapWidth;
final float zoomY = mState.getZoomY(mAspectQuotient) * viewHeight
/ bitmapHeight;
// Setup source and destination rectangles
mRectSrc.left = (int) (panX * bitmapWidth - viewWidth / (zoomX * 2));
mRectSrc.top = (int) (panY * bitmapHeight - viewHeight
/ (zoomY * 2));
mRectSrc.right = (int) (mRectSrc.left + viewWidth / zoomX);
mRectSrc.bottom = (int) (mRectSrc.top + viewHeight / zoomY);
mRectDst.left = getLeft();
mRectDst.top = getTop();
mRectDst.right = getRight();
mRectDst.bottom = getBottom();
// Adjust source rectangle so that it fits within the source image.
if (mRectSrc.left < 0)
{
mRectDst.left += -mRectSrc.left * zoomX;
mRectSrc.left = 0;
}
if (mRectSrc.right > bitmapWidth)
{
mRectDst.right -= (mRectSrc.right - bitmapWidth) * zoomX;
mRectSrc.right = bitmapWidth;
}
if (mRectSrc.top < 0)
{
mRectDst.top += -mRectSrc.top * zoomY;
mRectSrc.top = 0;
}
if (mRectSrc.bottom > bitmapHeight)
{
mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY;
mRectSrc.bottom = bitmapHeight;
}
canvas.drawBitmap(mBitmap, mRectSrc, mRectDst, mPaint);
}
}
public void update(Observable observable, Object data)
{
invalidate();
}
private void calculateAspectQuotient()
{
if (mBitmap != null)
{
mAspectQuotient = (((float) mBitmap.getWidth()) / mBitmap
.getHeight())
/ (((float) getWidth()) / getHeight());
}
}
public void setImage(Bitmap bitmap)
{
mBitmap = bitmap;
calculateAspectQuotient();
invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom)
{
super.onLayout(changed, left, top, right, bottom);
calculateAspectQuotient();
}
}
public class SimpleZoomListener implements View.OnTouchListener
{
public enum ControlType
{
PAN, ZOOM
}
@SuppressWarnings("unused")
private ControlType mControlType = ControlType.PAN;
private ZoomState mState;
private float mX;
private float mY;
private float mGap;
public void setZoomState(ZoomState state)
{
mState = state;
}
public void setControlType(ControlType controlType)
{
mControlType = controlType;
}
public boolean onTouch(View v, MotionEvent event)
{
final int action = event.getAction();
int pointCount = event.getPointerCount();
if (pointCount == 1)
{
final float x = event.getX();
final float y = event.getY();
switch (action)
{
case MotionEvent.ACTION_DOWN:
mX = x;
mY = y;
break;
case MotionEvent.ACTION_MOVE:
{
final float dx = (x - mX) / v.getWidth();
final float dy = (y - mY) / v.getHeight();
mState.setPanX(mState.getPanX() - dx);
mState.setPanY(mState.getPanY() - dy);
mState.notifyObservers();
mX = x;
mY = y;
break;
}
}
}
if (pointCount == 2)
{
final float x0 = event.getX(event.getPointerId(0));
final float y0 = event.getY(event.getPointerId(0));
final float x1 = event.getX(event.getPointerId(1));
final float y1 = event.getY(event.getPointerId(1));
final float gap = getGap(x0, x1, y0, y1);
switch (action)
{
case MotionEvent.ACTION_POINTER_2_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
mGap = gap;
break;
case MotionEvent.ACTION_POINTER_1_UP:
mX = x1;
mY = y1;
break;
case MotionEvent.ACTION_POINTER_2_UP:
mX = x0;
mY = y0;
break;
case MotionEvent.ACTION_MOVE:
{
final float dgap = (gap - mGap) / mGap;
// Log.d("Gap", String.valueOf(dgap));
Log.d("Gap", String.valueOf((float) Math.pow(20, dgap)));
mState.setZoom(mState.getZoom() * (float) Math.pow(5, dgap));
mState.notifyObservers();
mGap = gap;
break;
}
}
}
return true;
}
private float getGap(float x0, float x1, float y0, float y1)
{
return (float) Math.pow(
Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2), 0.5);
}
}
public class ZoomState extends Observable
{
private float mZoom;
private float mPanX;
private float mPanY;
public float getPanX()
{
return mPanX;
}
public float getPanY()
{
return mPanY;
}
public float getZoom()
{
return mZoom;
}
public void setPanX(float panX)
{
if (panX != mPanX)
{
mPanX = panX;
setChanged();
}
}
public void setPanY(float panY)
{
if (panY != mPanY)
{
mPanY = panY;
setChanged();
}
}
public void setZoom(float zoom)
{
if (zoom != mZoom)
{
mZoom = zoom;
setChanged();
}
}
public float getZoomX(float aspectQuotient)
{
return Math.min(mZoom, mZoom * aspectQuotient);
}
public float getZoomY(float aspectQuotient)
{
return Math.min(mZoom, mZoom / aspectQuotient);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:id="@+id/zoomViewRelativeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/zoomControlRelativeLayout"
android:layout_marginBottom="2px"
>
<whu.iss.activity.ImageZoomView
android:id="@+id/zoomView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
</whu.iss.activity.ImageZoomView>
<ProgressBar
android:id="@+id/progress_large"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="?android:attr/progressBarStyleLarge"
android:visibility="gone"
android:layout_centerInParent="true"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/zoomControlRelativeLayout"
android:layout_width="fill_parent"
android:layout_height="50px"
android:layout_alignParentBottom="true"
>
<ZoomControls
android:id="@+id/zoomCtrl"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
>
</ZoomControls>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
工程下载地址: 点击打开链接 另补充 Android Gallery3D 源码 已编译 :地址 http://download.csdn.net/detail/yf210yf/4102113
原文链接: http://blog.csdn.net/yf210yf/article/details/7308575