Android如何自定义View可拖动移动位置及边缘拉伸放大缩实例源码介绍



Android如何自定义View可拖动移动位置及边缘拉伸放大缩实例源码介绍。定义这样一个View有什么用?一些app中,需要设置头像,而用户选择的图片可能是使用摄像头拍摄,也可能是选择的相册里面的图片,总之,这样的图片大小不一,就比如在使用某个聊天软件的时候,设置头像,需要对图片进行截取.要实现这功能,需要分析用户的操作,即用户所点击的View的位置,如下图,把View分为9个区域,

  • 当ACTION_DOWN时如果坐标为1.2.3.4四个区域,则对View进行相应的左上/右上/左下/右下拉伸;
  • 当ACTION_DOWN时如果坐标为5.6.7.8四个区域,则分别对上/右/下/左四个方向进行拉伸; 
  • 当ACTION_DOWN时如果坐标为9这个区域,则对View进行移动;

Android <wbr>自定义View可拖动移动位置及边缘拉伸放大缩(转)

下面来看具体实现;

在下面的类中,有五个方法center/left/top/bottom/right分别对应移动/向左拉伸/向上拉伸/向下拉伸/向右拉伸,当Action_down为1-4所在的区域时,组合前面的对应的两个拉伸方法即可,如左上角拉伸则对应执行left+top方法,这也是把四个单独一条边的边缘拉伸独立出来的原因;在View中,设定了View的最小宽度和高度,都是200,所以当用户点击边缘进行缩小操作时,能缩小的最小值也就是200;分别在left/top/bottom/right中体现;

public class DragScaleView extends View implements OnTouchListener {

   protected int screenWidth;
   protected int screenHeight;
   protected int lastX;
   protected int lastY;
   private int oriLeft;
   private int oriRight;
   private int oriTop;
   private int oriBottom;
   private int dragDirection;
   private static final int TOP = 0×15;
   private static final int LEFT = 0×16;
   private static final int BOTTOM = 0×17;
   private static final int RIGHT = 0×18;
   private static final int LEFT_TOP = 0×11;
   private static final int RIGHT_TOP = 0×12;
   private static final int LEFT_BOTTOM = 0×13;
   private static final int RIGHT_BOTTOM = 0×14;
   private static final int CENTER = 0×19;
   private int offset = 20;
   protected Paint paint = new Paint();

  
   protected void initScreenW_H() {
       screenHeight = getResources().getDisplayMetrics().heightPixels – 40;
       screenWidth = getResources().getDisplayMetrics().widthPixels;
   }

   public DragScaleView(Context context, AttributeSet attrs, int defStyle) {
       super(context, attrs, defStyle);
       setOnTouchListener(this);
       initScreenW_H();
   }

   public DragScaleView(Context context, AttributeSet attrs) {
       super(context, attrs);
       setOnTouchListener(this);
       initScreenW_H();
   }

   public DragScaleView(Context context) {
       super(context);
       setOnTouchListener(this);
       initScreenW_H();
   }

   @Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       paint.setColor(Color.RED);
       paint.setStrokeWidth(4.0f);
       paint.setStyle(Style.STROKE);
       canvas.drawRect(offset, offset, getWidth() – offset, getHeight()
               - offset, paint);
   }

   @Override
   public boolean onTouch(View v, MotionEvent event) {
       int action = event.getAction();
       if (action == MotionEvent.ACTION_DOWN) {
           oriLeft = v.getLeft();
           oriRight = v.getRight();
           oriTop = v.getTop();
           oriBottom = v.getBottom();
           lastY = (int) event.getRawY();
           lastX = (int) event.getRawX();
           dragDirection = getDirection(v, (int) event.getX(),
                   (int) event.getY());
       }
       // 处理拖动事件
       delDrag(v, event, action);
       invalidate();
       return false;
   }


  
   protected void delDrag(View v, MotionEvent event, int action) {
       switch (action) {
       case MotionEvent.ACTION_MOVE:
           int dx = (int) event.getRawX() – lastX;
           int dy = (int) event.getRawY() – lastY;
           switch (dragDirection) {
           case LEFT: // 左边缘
               left(v, dx);
               break;
           case RIGHT: // 右边缘
               right(v, dx);
               break;
           case BOTTOM: // 下边缘
               bottom(v, dy);
               break;
           case TOP: // 上边缘
               top(v, dy);
               break;
           case CENTER: // 点击中心–>>移动
               center(v, dx, dy);
               break;
           case LEFT_BOTTOM: // 左下
               left(v, dx);
               bottom(v, dy);
               break;
           case LEFT_TOP: // 左上
               left(v, dx);
               top(v, dy);
               break;
           case RIGHT_BOTTOM: // 右下
               right(v, dx);
               bottom(v, dy);
               break;
           case RIGHT_TOP: // 右上
               right(v, dx);
               top(v, dy);
               break;
           }
           if (dragDirection != CENTER) {
               v.layout(oriLeft, oriTop, oriRight, oriBottom);
           }
           lastX = (int) event.getRawX();
           lastY = (int) event.getRawY();
           break;
       case MotionEvent.ACTION_UP:
           dragDirection = 0;
           break;
       }
   }

  
   private void center(View v, int dx, int dy) {
       int left = v.getLeft() + dx;
       int top = v.getTop() + dy;
       int right = v.getRight() + dx;
       int bottom = v.getBottom() + dy;
       if (left < -offset) {
           left = -offset;
           right = left + v.getWidth();
       }
       if (right > screenWidth + offset) {
           right = screenWidth + offset;
           left = right – v.getWidth();
       }
       if (top < -offset) {
           top = -offset;
           bottom = top + v.getHeight();
       }
       if (bottom > screenHeight + offset) {
           bottom = screenHeight + offset;
           top = bottom – v.getHeight();
       }
       v.layout(left, top, right, bottom);
   }

  
   private void top(View v, int dy) {
       oriTop += dy;
       if (oriTop < -offset) {
           oriTop = -offset;
       }
       if (oriBottom – oriTop – 2 * offset < 200) {
           oriTop = oriBottom – 2 * offset – 200;
       }
   }

  
   private void bottom(View v, int dy) {
       oriBottom += dy;
       if (oriBottom > screenHeight + offset) {
           oriBottom = screenHeight + offset;
       }
       if (oriBottom – oriTop – 2 * offset < 200) {
           oriBottom = 200 + oriTop + 2 * offset;
       }
   }

  
   private void right(View v, int dx) {
       oriRight += dx;
       if (oriRight > screenWidth + offset) {
           oriRight = screenWidth + offset;
       }
       if (oriRight – oriLeft – 2 * offset < 200) {
           oriRight = oriLeft + 2 * offset + 200;
       }
   }

  
   private void left(View v, int dx) {
       oriLeft += dx;
       if (oriLeft < -offset) {
           oriLeft = -offset;
       }
       if (oriRight – oriLeft – 2 * offset < 200) {
           oriLeft = oriRight – 2 * offset – 200;
       }
   }

  
   protected int getDirection(View v, int x, int y) {
       int left = v.getLeft();
       int right = v.getRight();
       int bottom = v.getBottom();
       int top = v.getTop();
       if (x < 40 && y < 40) {
           return LEFT_TOP;
       }
       if (y < 40 && right – left – x < 40) {
           return RIGHT_TOP;
       }
       if (x < 40 && bottom – top – y < 40) {
           return LEFT_BOTTOM;
       }
       if (right – left – x < 40 && bottom – top – y < 40) {
           return RIGHT_BOTTOM;
       }
       if (x < 40) {
           return LEFT;
       }
       if (y < 40) {
           return TOP;
       }
       if (right – left – x < 40) {
           return RIGHT;
       }
       if (bottom – top – y < 40) {
           return BOTTOM;
       }
       return CENTER;
   }

  
   public int getCutWidth() {
       return getWidth() – 2 * offset;
   }

  
   public int getCutHeight() {
       return getHeight() – 2 * offset;
   }
}

使用View,如果想要对View进行移动,需要在xml中配置android:clickable=”true”属性;

       android:id=”@+id/ds”
       android:layout_width=”180dip”
       android:layout_height=”180dip”
       android:clickable=”true” />