android学习笔记37--------------多点触控缩放图片及单点触控图片移动

转载请注明原文出处:奔跑的蜗牛(袁方的技术博客)点击打开链接

原始图片:


点击放大按钮,或两手拖拉屏幕。


上代码:

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


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值