仿美图秀秀的图片剪切
Posted ihrthk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仿美图秀秀的图片剪切相关的知识,希望对你有一定的参考价值。
先贴上美图秀秀原作的效果图,右边是我仿的效果图。
刚一眼打量过去,吸引我们的就是那四个大点。就从它开始吧,目前看来这个大点是一个图片,当点击下去的时候有加亮的效果,可能这又是一张图片。我们先不要考虑这些,先把它当做一个普通的Point来处理就好了。正常来讲的话,我们这里需要四个Point,但是考虑到后面我们对这些点进行复杂的运算和事件处理,只要申请两个Point就好了,以便降低问题的复杂度。两个即leftUpPoint和rightDownPoint。(其余两个点只要由这个两点拼一下就可以了)
那么画中间的框就用下面的代码:
paint.setARGB(255, 255, 255, 255);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
Rect frameRect = new Rect(leftUpPoint.x + offsetLeftUpPoint.x,
leftUpPoint.y + offsetLeftUpPoint.y, rightDownPoint.x
+ offsetRightDownPoint.x, rightDownPoint.y
+ offsetRightDownPoint.y);
canvas.drawRect(frameRect, paint);
offsetLeftUpPoint和offsetRightDownPoint是leftUpPoint和rightDownPoint相对的偏移量,后面事件处理的时候会用到。
然后顺势把里面的线条和数字画出来。代码如下:
// 画内框里线条
paint.setARGB(90, 255, 255, 255);
paint.setStrokeWidth(2);
canvas.drawLine(leftUpPoint.x + this.getDynamicFrameWidth() / 3
+ offsetLeftUpPoint.x, leftUpPoint.y + offsetLeftUpPoint.y,
leftUpPoint.x + this.getDynamicFrameWidth() / 3
+ offsetLeftUpPoint.x, rightDownPoint.y
+ offsetRightDownPoint.y, paint);
canvas.drawLine(rightDownPoint.x - this.getDynamicFrameWidth() / 3
+ offsetRightDownPoint.x, leftUpPoint.y + offsetLeftUpPoint.y,
rightDownPoint.x - this.getDynamicFrameWidth() / 3
+ offsetRightDownPoint.x, rightDownPoint.y
+ offsetRightDownPoint.y, paint);
canvas.drawLine(leftUpPoint.x + offsetLeftUpPoint.x, leftUpPoint.y
+ this.getDynamicFrameHeight() / 3 + offsetLeftUpPoint.y,
rightDownPoint.x + offsetRightDownPoint.x,
leftUpPoint.y + this.getDynamicFrameHeight() / 3
+ offsetLeftUpPoint.y, paint);
canvas.drawLine(leftUpPoint.x + offsetLeftUpPoint.x, rightDownPoint.y
- this.getDynamicFrameHeight() / 3 + offsetRightDownPoint.y,
rightDownPoint.x + offsetRightDownPoint.x, rightDownPoint.y
- this.getDynamicFrameHeight() / 3
+ offsetRightDownPoint.y, paint);
// 画外框里的数字
paint.setARGB(255, 255, 255, 255);
paint.setStrokeWidth(0);
paint.setTextSize(10);
paint.setTextAlign(Align.CENTER);
canvas.drawText(
this.getDynamicFrameWidth() + "*"
+ this.getDynamicFrameHeight(),
(leftUpPoint.x + offsetLeftUpPoint.x + rightDownPoint.x + offsetRightDownPoint.x) / 2,
(leftUpPoint.y + offsetLeftUpPoint.y + rightDownPoint.y
+ offsetRightDownPoint.y + 10) / 2, paint);
没有什么说的,大家只要注意一下线条和数字与中间框的坐标关系就可以了,代码上提到的:getDynamicFrameWidth()和getDynamicFrameHeight()这两个方法,后面也会说明的。
再看仔细看一下中间框的外围的情况,像是有一种透明黒的效果,那就对了,这也是一种效果哦,也需要“画”的哦。
还是注意分析与中间框的坐标关系,代码如下咯:
// 画内框外围
paint.setARGB(180, 0, 0, 0);
Rect top = new Rect(0, 0, width, leftUpPoint.y + offsetLeftUpPoint.y);
Rect bottom = new Rect(0, rightDownPoint.y + offsetRightDownPoint.y,width, height);
Rect left = new Rect(0, leftUpPoint.y + offsetLeftUpPoint.y,leftUpPoint.x + offsetLeftUpPoint.x, rightDownPoint.y + offsetRightDownPoint.y);
Rect right = new Rect(rightDownPoint.x + offsetRightDownPoint.x, leftUpPoint.y + offsetLeftUpPoint.y, width, rightDownPoint.y + offsetRightDownPoint.y);
canvas.drawRect(top, paint);
canvas.drawRect(bottom, paint);
canvas.drawRect(left, paint);
canvas.drawRect(right, paint);
静态的问题已经基本处理完了,下面我们要把拖动和放大缩小这两动态问题考虑进来。
那就需要我们重写View的onTouchEvent()这个方法,我们要实现整个效果全在这个方法里呢。
第一步,我要将这个方法的返回值设置成true,否则就接收不到后面的ACTION_MOVE和ACTION_UP这两个事件了。要是这样就悲剧了大哭
第二步,在设置返回值之前,要执行一下this.invalidate();这个方法,因为View的onDraw()方法是被动的,只有当View无效的时候才会执行。
预热一下,说明一下我们需要东西:
a:onTouchEvent()方法的框架,即能处理ACTION_DOWN、ACTION_MOVE和ACTION_UP三种事件。
b:记录leftUpPoint和rightDownPoint两个点的偏移量offsetLeftUpPoint和offsetRightDownPoint
c:记录onTouchEvent()上一次点击的坐标lastPoint,在执行完ACTION_DOWN事件,再执行ACTION_MOVE事件时会用到。
d:六种动作事件的标识符EVENT_NONE = 0, EVENT_MOVE = 1, EVENT_SCALE_LEFTUP = 2, EVENT_SCALE_LEFTDOWN = 3, EVENT_SCALE_RIGHTUP = 4, EVENT_SCALE_RIGHTDOWN = 5;及它们的掌控件变量eventType
e:还有那四个取得中间框长和宽和方法
private int getDynamicFrameWidth()
return (rightDownPoint.x + offsetRightDownPoint.x)
- (leftUpPoint.x + offsetLeftUpPoint.x);
private int getDynamicFrameHeight()
return (rightDownPoint.y + offsetRightDownPoint.y)
- (leftUpPoint.y + offsetLeftUpPoint.y);
什么是又动态呢?在onDraw()方法用到长和宽就是动态。关于这一点,大家
在仔细想一想就会明白了。不用我多说什么,我把整个onTouchEvent()方法里的代码贴上来,大家看一下就会明白了,:
/*
* 接收触屏事件
*/
@Override
public boolean onTouchEvent(MotionEvent event)
// TODO Auto-generated method stub
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
handleActionDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
handleActionMove(x, y);
break;
case MotionEvent.ACTION_UP:
handleActionUp();
break;
this.invalidate();
return true;
/**
* 得到eventType事件类型的值和lastPoint坐标点
*
* @param x
* x坐标
* @param y
* y坐标
*/
private void handleActionDown(int x, int y)
// move
if (leftUpPoint.x < x && x < rightDownPoint.x && leftUpPoint.y < y
&& y < rightDownPoint.y)
lastPoint = new Point(x, y);
eventType = EVENT_MOVE;
// leftup
else if (Math.abs(x - leftUpPoint.x) < DOT_RADIO
&& Math.abs(y - leftUpPoint.y) < DOT_RADIO)
lastPoint = new Point(x, y);
eventType = EVENT_SCALE_LEFTUP;
// leftdown
else if (Math.abs(x - leftUpPoint.x) < DOT_RADIO
&& Math.abs(y - rightDownPoint.y) < DOT_RADIO)
lastPoint = new Point(x, y);
eventType = EVENT_SCALE_LEFTDOWN;
// rightup
else if (Math.abs(x - rightDownPoint.x) < DOT_RADIO
&& Math.abs(y - leftUpPoint.y) < DOT_RADIO)
lastPoint = new Point(x, y);
eventType = EVENT_SCALE_RIGHTUP;
// rightdown
else if (Math.abs(x - rightDownPoint.x) < DOT_RADIO
&& Math.abs(y - rightDownPoint.y) < DOT_RADIO)
lastPoint = new Point(x, y);
eventType = EVENT_SCALE_RIGHTDOWN;
else
eventType = EVENT_NONE;
/**
* 根据eventType进行处理
*
* @param x
* x坐标
* @param y
* y坐标
*/
private void handleActionMove(int x, int y)
switch (eventType)
case EVENT_MOVE:
offsetLeftUpPoint.x = x - lastPoint.x;
offsetLeftUpPoint.y = y - lastPoint.y;
moveRestriction();
offsetRightDownPoint.x = offsetLeftUpPoint.x;
offsetRightDownPoint.y = offsetLeftUpPoint.y;
break;
case EVENT_SCALE_LEFTUP:
offsetLeftUpPoint.x = x - lastPoint.x;
offsetLeftUpPoint.y = y - lastPoint.y;
leftUpScaleRestriction();
offsetRightDownPoint.x = 0;
offsetRightDownPoint.y = 0;
break;
case EVENT_SCALE_LEFTDOWN:
offsetLeftUpPoint.x = x - lastPoint.x;
offsetRightDownPoint.y = y - lastPoint.y;
leftDownScaleRestriction();
offsetLeftUpPoint.y = 0;
offsetRightDownPoint.x = 0;
break;
case EVENT_SCALE_RIGHTUP:
offsetRightDownPoint.x = x - lastPoint.x;
offsetLeftUpPoint.y = y - lastPoint.y;
rightUpScaleRestriction();
offsetRightDownPoint.y = 0;
offsetLeftUpPoint.x = 0;
break;
case EVENT_SCALE_RIGHTDOWN:
offsetRightDownPoint.x = x - lastPoint.x;
offsetRightDownPoint.y = y - lastPoint.y;
rightDownScaleRestriction();
offsetLeftUpPoint.x = 0;
offsetLeftUpPoint.y = 0;
break;
case EVENT_NONE:
break;
/**
* 进行复位
*/
private void handleActionUp()
leftUpPoint.x += offsetLeftUpPoint.x;
leftUpPoint.y += offsetLeftUpPoint.y;
rightDownPoint.x += offsetRightDownPoint.x;
rightDownPoint.y += offsetRightDownPoint.y;
offsetLeftUpPoint.x = 0;
offsetLeftUpPoint.y = 0;
offsetRightDownPoint.x = 0;
offsetRightDownPoint.y = 0;
eventType = EVENT_NONE;
/**
* 移动限制
*/
private void moveRestriction()
if (leftUpPoint.x + offsetLeftUpPoint.x < 0)
offsetLeftUpPoint.x = -leftUpPoint.x;
else if (leftUpPoint.x + offsetLeftUpPoint.x > this.getWidth()
- (rightDownPoint.x - leftUpPoint.x))
offsetLeftUpPoint.x = this.getWidth()
- (rightDownPoint.x - leftUpPoint.x) - leftUpPoint.x;
if (leftUpPoint.y + offsetLeftUpPoint.y < 0)
offsetLeftUpPoint.y = -leftUpPoint.y;
else if (leftUpPoint.y + offsetLeftUpPoint.y > this.getHeight()
- (rightDownPoint.y - leftUpPoint.y))
offsetLeftUpPoint.y = this.getHeight()
- (rightDownPoint.y - leftUpPoint.y) - leftUpPoint.y;
/**
* 左上缩放限制
*/
private void leftUpScaleRestriction()
if (leftUpPoint.x + offsetLeftUpPoint.x < 0)
offsetLeftUpPoint.x = -leftUpPoint.x;
if (rightDownPoint.x - (leftUpPoint.x + offsetLeftUpPoint.x) < FRAME_MIN_WIDTH)
offsetLeftUpPoint.x = rightDownPoint.x - leftUpPoint.x
- FRAME_MIN_WIDTH;
if (leftUpPoint.y + offsetLeftUpPoint.y < 0)
offsetLeftUpPoint.y = -leftUpPoint.y;
if (rightDownPoint.y - (leftUpPoint.y + offsetLeftUpPoint.y) < FRAME_MIN_HEIGHT)
offsetLeftUpPoint.y = rightDownPoint.y - leftUpPoint.y
- FRAME_MIN_HEIGHT;
/**
* 左下缩放限制
*/
private void leftDownScaleRestriction()
if (leftUpPoint.x + offsetLeftUpPoint.x < 0)
offsetLeftUpPoint.x = -leftUpPoint.x;
if (rightDownPoint.x - (leftUpPoint.x + offsetLeftUpPoint.x) < FRAME_MIN_WIDTH)
offsetLeftUpPoint.x = rightDownPoint.x - leftUpPoint.x
- FRAME_MIN_WIDTH;
if (rightDownPoint.y + offsetRightDownPoint.y > this.getHeight())
offsetRightDownPoint.y = this.getHeight() - rightDownPoint.y;
if ((rightDownPoint.y + offsetRightDownPoint.y) - leftUpPoint.y < FRAME_MIN_HEIGHT)
offsetRightDownPoint.y = FRAME_MIN_HEIGHT + leftUpPoint.y
- rightDownPoint.y;
/**
* 右上缩放限制
*/
private void rightUpScaleRestriction()
if (rightDownPoint.x + offsetRightDownPoint.x > this.getWidth())
offsetRightDownPoint.x = this.getWidth() - rightDownPoint.x;
if ((rightDownPoint.x + offsetRightDownPoint.x) - leftUpPoint.x < FRAME_MIN_WIDTH)
offsetRightDownPoint.x = FRAME_MIN_WIDTH + leftUpPoint.x
- rightDownPoint.x;
if (leftUpPoint.y + offsetLeftUpPoint.y < 0)
offsetLeftUpPoint.y = -leftUpPoint.y;
if (rightDownPoint.y - (leftUpPoint.y + offsetLeftUpPoint.y) < FRAME_MIN_HEIGHT)
offsetLeftUpPoint.y = rightDownPoint.y - leftUpPoint.y
- FRAME_MIN_HEIGHT;
/**
* 右下缩放限制
*/
private void rightDownScaleRestriction()
if (rightDownPoint.x + offsetRightDownPoint.x > this.getWidth())
offsetRightDownPoint.x = this.getWidth() - rightDownPoint.x;
if ((rightDownPoint.x + offsetRightDownPoint.x) - leftUpPoint.x < FRAME_MIN_WIDTH)
offsetRightDownPoint.x = FRAME_MIN_WIDTH + leftUpPoint.x
- rightDownPoint.x;
if (rightDownPoint.y + offsetRightDownPoint.y > this.getHeight())
offsetRightDownPoint.y = this.getHeight() - rightDownPoint.y;
if ((rightDownPoint.y + offsetRightDownPoint.y) - leftUpPoint.y < FRAME_MIN_HEIGHT)
offsetRightDownPoint.y = FRAME_MIN_HEIGHT + leftUpPoint.y
- rightDownPoint.y;
奉上源码下载地址:http://download.csdn.net/detail/ihrthk/4509509
以上是关于仿美图秀秀的图片剪切的主要内容,如果未能解决你的问题,请参考以下文章