你好,游客 登录 注册 搜索
背景:
阅读新闻

Android 图片拖拽、放大缩小的自定义控件

[日期:2014-12-23] 来源:Linux社区  作者:Mingwei [字体: ]

Android 图片拖拽、放大缩小的自定义控件

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

思路: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")
 @Override
 protected void onDraw(Canvas canvas) {
  // TODO Auto-generated method stub
  super.onDraw(canvas);
  if (mDrawable == null || mDrawable.getIntrinsicHeight() == 0
    || mDrawable.getIntrinsicWidth() == 0) {
   return;
  }
  setBounds();
  mDrawable.draw(canvas);
  // Log.i("draw", "draw+++++++++++++++++++++++++++++++++++++++");

 }

 @SuppressLint("ClickableViewAccessibility")
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // TODO Auto-generated method stub
  switch (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;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.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);
 
 }
}

效果

最简单的Ubuntu Touch & Android 双系统安装方式 http://www.linuxidc.com/Linux/2014-01/94881.htm

在Nexus上实现Ubuntu和Android 4.4.2 双启动 http://www.linuxidc.com/Linux/2014-05/101849.htm

Ubuntu 14.04 配置 Android SDK 开发环境 http://www.linuxidc.com/Linux/2014-05/101039.htm

64位Ubuntu 11.10下Android开发环境的搭建(JDK+Eclipse+ADT+Android SDK详细) http://www.linuxidc.com/Linux/2013-06/85303.htm

Ubuntu 14.04 x64配置Android 4.4 kitkat编译环境的方法 http://www.linuxidc.com/Linux/2014-04/101148.htm

Ubuntu 12.10 x64 安装 Android SDK http://www.linuxidc.com/Linux/2013-03/82005.htm

更多Android相关信息见Android 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=11

本文永久更新链接地址http://www.linuxidc.com/Linux/2014-12/110763.htm

linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款