需求:像相册中的图片跟随手指拖动,双指的放大和缩小,相册中拖出范围之后有弹回的动画,感觉上很圆润,很舒服,我写的例子中并没有加动画

思路:1.自定义DragImageView.java

2.自定义中先画图片,图片大于屏幕就把图片缩小后显示,图片小于屏幕就直接显示,显示之前要计算显示图片的Rect,Rect是其实就是四个坐标,用来控制显示图片的范 围,这个Rect是根据图片的长宽比例计算而来,显示在屏幕中间。

3.跟随手指移动:在touchEvent事件中处理好单双指的各种事件之后,跟随手指就是不断的改变Rect的坐标,然后不断的invalidate()(该方法是重新强制绘制View);

4.双指缩放:双指缩放的时候从图片Rect的中心缩放的,没有实现相册那种从手指中心缩放的那种。

5.单指和双指的事件在touc事件中已近处理好了

event.getPointerCount()==2的情况就是双指部分

float X0,Y0,X1,Y1双指的四个坐标

在双指移动的时候计算一个双指的距离出来m1,在MOVE执行的时候重新计算一个新的距离m2,去判断m1和m2大小来判断双指是张开还是捏合,并且执行相应事件,判断之后把m2复制给m1,这时的MOVE事件会有新的m2出来,所以就一直判断就ok了。放大和缩小就是按照一定的比例去改变Rect的值。


DragImageView.java

public class DragImageView extends View {private Paint mPaint;private Drawable mDrawable;private Rect mDrawableRect = new Rect();// private Rect mDrawableOffsetRect = new Rect();private Context mContext;private float mRation_WH = 0;private float mOldX = 0;private float mOldY = 0;private float mOldX0, mOldY0, mOldX1, mOldY1, mOldK, mOldB, mOldHandsX,mOldHandsY;private double mD1;private boolean isFirst = true;private int SINGALDOWN = 1;// 单点按下private int MUTILDOWM = 2;// 双点按下private int MUTILMOVE = 3;// 双点拖拽private int mStatus = 0;enum STATUS {SINGAL, MUTILDOWN, MUTILMOVE;}public DragImageView(Context context) {super(context);this.mContext = context;mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setColor(Color.BLACK);mPaint.setStyle(Style.FILL);mPaint.setTextSize(35.0f);}@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);if (mDrawable == null || mDrawable.getIntrinsicHeight() == 0|| mDrawable.getIntrinsicWidth() == 0) {return;}setBounds();mDrawable.draw(canvas);// Log.i("draw", "draw+++++++++++++++++++++++++++++++++++++++");}@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (event.getPointerCount()) {case 1:switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mStatus = SINGALDOWN;mOldX = event.getX();mOldY = event.getY();// Log.i("x_y_down", event.getX() + "__" + event.getY());break;case MotionEvent.ACTION_UP:checkBounds();// Log.i("x_y_up", event.getX() + "__" + event.getY());break;case MotionEvent.ACTION_MOVE:// Log.i("x_y_move", event.getX() + "__" + event.getY());if (mStatus == SINGALDOWN) {int offsetWidth = (int) (event.getX() - mOldX);int offsetHeight = (int) (event.getY() - mOldY);// Log.i("x_y_offset", offsetWidth + "__" + offsetHeight);mOldX = event.getX();mOldY = event.getY();mDrawableRect.offset(offsetWidth, offsetHeight);invalidate();}break;default:break;}break;default:/* * mStatus = MUTILDOWM; if (mStatus == MUTILDOWM) { mOldX0 = * event.getX(0); mOldY0 = event.getY(0); mOldX1 = event.getX(1); * mOldY1 = event.getY(1); mOldK = (mOldY1 - mOldY0) / (mOldX1 - * mOldX0); mOldB = (mOldY0 * mOldX1 - mOldY1 * mOldX0) / (mOldX1 - * mOldX0); mOldHandsX = (mOldX0 + mOldX1) / 2; mOldHandsY = * mOldHandsX * mOldK + mOldB; mD1 = Math.sqrt(Math.pow(mOldX0 - * mOldX1, 2) + Math.pow(mOldY0 - mOldY1, 2)); Log.i("mD1", mD1 + * "________________"); } */switch (event.getAction()) {case MotionEvent.ACTION_POINTER_DOWN:Log.i("DOUBLETOWDOWN", "true");break;case MotionEvent.ACTION_MOVE:// Log.i("x_y_move", event.getX(0) + "__" + event.getY(0) +// "___"// + event.getX(1) + "__" + event.getY(1));mStatus = MUTILMOVE;float X0 = event.getX(0);float Y0 = event.getY(0);float X1 = event.getX(1);float Y1 = event.getY(1);float k = (Y1 - Y0) / (X1 - X0);float b = (Y0 * X1 - Y1 * X0) / (X1 - X0);int RectCenterX = mDrawableRect.centerX();int RectCenterY = mDrawableRect.centerY();float mHandsX = (X0 + X1) / 2;float mHandsY = mHandsX * k + b;double mD2 = Math.sqrt(Math.pow(X0 - X1, 2)+ Math.pow(Y0 - Y1, 2));Log.i("GCM", mD2 + "________________X:" + mHandsX + "___Y:"+ mHandsY);if (mD1 < mD2) {// double mMultiple = mD2 / mD1;// int newWidth = (int) (mDrawableRect.width() * mMultiple);// int newHeight = (int) (newWidth / mRation_WH);//// int newleft = mDrawableRect.left / 2;// int newtop = mDrawableRect.top / 2;// int newright = mDrawableRect.right * (3 / 2);// int newbotto = mDrawableRect.bottom * (3 / 2);// // mDrawableRect.set(newleft, newtop, newright,// newbotto);//// mDrawableRect.set(RectCenterX - newWidth / 2, RectCenterY// - newHeight / 2, RectCenterX + newWidth / 2,// RectCenterY + newHeight / 2);// invalidate();if (mDrawableRect.width() < mContext.getResources().getDisplayMetrics().widthPixels * 2) {int offsetwidth = 10;int offsettop = (int) (offsetwidth / mRation_WH);mDrawableRect.set(mDrawableRect.left - offsetwidth,mDrawableRect.top - offsettop,mDrawableRect.right + offsetwidth,mDrawableRect.bottom + offsettop);Log.i("GCM", "aaaaaaaaaaaaaaa");invalidate();}// mDrawableRect.offset((int) mHandsX, (int) mHandsY);} else {if (mDrawableRect.width() > mContext.getResources().getDisplayMetrics().widthPixels / 3) {int offsetwidth = 10;int offsettop = (int) (offsetwidth / mRation_WH);mDrawableRect.set(mDrawableRect.left + offsetwidth,mDrawableRect.top + offsettop,mDrawableRect.right - offsetwidth,mDrawableRect.bottom - offsettop);invalidate();Log.i("GCM", "bbbbbbbbbbbbbbb");}}mD1 = mD2;if (mHandsX < RectCenterX) {if (mHandsY < RectCenterY) {Log.i("PPPPPPP", "1");} else {Log.i("PPPPPPP", "3");}} else {if (mHandsY < RectCenterY) {Log.i("PPPPPPP", "2");} else {Log.i("PPPPPPP", "4");}}//break;case MotionEvent.ACTION_UP:Log.i("mStatus", "mutildouble_up");mStatus = 0;break;default:break;}break;}return true;}public void setBounds() {if (isFirst) {mRation_WH = (float) mDrawable.getIntrinsicWidth()/ (float) mDrawable.getIntrinsicHeight();int px_w = Math.min(getWidth(),dip2px(mContext, mDrawable.getIntrinsicWidth()));int px_h = (int) (px_w / mRation_WH);int left = (getWidth() - px_w) / 2;int top = (getHeight() - px_h) / 2;int right = px_w + left;int bottom = px_h + top;mDrawableRect.set(left, top, right, bottom);// mDrawableOffsetRect.set(mDrawableRect);isFirst = false;Log.i("rect1______", mDrawableRect.left + "," + mDrawableRect.top+ "," + mDrawableRect.right + "," + mDrawableRect.bottom);}mDrawable.setBounds(mDrawableRect);Log.i("rect2______", mDrawableRect.left + "," + mDrawableRect.top + ","+ mDrawableRect.right + "," + mDrawableRect.bottom);Log.i("center_______",mDrawableRect.centerX() + "," + mDrawableRect.centerY());}public void checkBounds() {int newLeft = mDrawableRect.left;int newTop = mDrawableRect.top;boolean isChange = false;if (newLeft < -mDrawableRect.width()) {newLeft = -mDrawableRect.width();isChange = true;}if (newTop < -mDrawableRect.height()) {newTop = -mDrawableRect.height();isChange = true;}if (newLeft > getWidth()) {newLeft = getWidth();isChange = true;}if (newTop > getHeight()) {newTop = getHeight();isChange = true;}if (isChange) {mDrawableRect.offsetTo(newLeft, newTop);invalidate();}}public Drawable getmDrawable() {return mDrawable;}public void setmDrawable(Drawable mDrawable) {this.mDrawable = mDrawable;}public int dip2px(Context context, int value) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (value * scale + 0.5f);}}
在界面中使用


public class MainActivity extends Activity {Context mContext;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);this.mContext = getApplicationContext();requestWindowFeature(Window.FEATURE_NO_TITLE);DragImageView mView = new DragImageView(mContext);mView.setmDrawable(mContext.getResources().getDrawable(R.drawable.bbb));setContentView(mView);}}

效果



更多相关文章

  1. Android中style和theme巧用:Android应用程序启动时背景画面的切
  2. 自定义Android电子时钟控件
  3. 如何利用Activity的Dialog风格完成弹出框设计 “第二届 Google
  4. 超炫的3D特效程序管理功能android
  5. Android窗口管理服务WindowManagerService显示窗口动画的原理分
  6. 实用的Log打印类封装,助尼快速定位源码(android)
  7. Android导入SVG矢量图
  8. Android(安卓)应用开发 之使用LruCache和DiskLruCache来在内存和
  9. 实现ListView的条目下自动隐藏显示Button的方法

随机推荐

  1. android之SMS
  2. 仿优酷Android客户端图片左右滑动(自动滑
  3. 获取Android设备基本信息
  4. Android线程管理之ThreadLocal理解及应用
  5. ContentProvider详解及使用大全
  6. Android 自定义格式的对话框
  7. Android 处理横竖屏切换
  8. android中读写sd卡文件
  9. Android的Thread & ProgressBar
  10. Android Activity 设置全屏