您的位置:首页 > 移动开发 > Android开发

Android 自定义View可拖动移动位置及边缘拉伸放大缩

2017-12-29 11:51 731 查看
首先说一下定义这样一个View有什么用?在一些app中,需要设置头像,而用户选择的图片可能是使用摄像头拍摄,也可能是选择的相册里面的图片,总之,这样的图片大小不一,就比如在使用某个聊天软件的时候,设置头像,需要对图片进行截取.

要实现这样一个功能,首先,需要分析用户的操作,即用户所点击的View的位置,如下图,我把View分为9个区域,

当ACTION_DOWN时如果坐标为1.2.3.4四个区域,则对View进行相应的左上/右上/左下/右下拉伸;

当ACTION_DOWN时如果坐标为5.6.7.8四个区域,则分别对上/右/下/左四个方向进行拉伸;

当ACTION_DOWN时如果坐标为9这个区域,则对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 = 0x15;

private
static final int LEFT = 0x16;

private
static final int BOTTOM = 0x17;

private
static final int RIGHT = 0x18;

private
static final int LEFT_TOP = 0x11;

private
static final int RIGHT_TOP = 0x12;

private
static final int LEFT_BOTTOM = 0x13;

private
static final int RIGHT_BOTTOM = 0x14;

private
static final int CENTER = 0x19;

private int
offset = 20;

protected
Paint paint = new Paint();

4000

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” />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐