背景:对图片的部分区域进行点击,响应相应的事件(可对图片进行放大,边界反弹,以及图片移动)
针对于前次的热区点击做了个补充
1.对图片的部分区域进行可响应事件
2.对图片进行缩放后,仍可响应区域点击事件
3.对图片进行移动后.仍可响应区域点击事件
4.当图片移出边界区域后,可进行回弹.
其效果图如下(GIF图片较大,只截取一部分,在模拟器上,缩放效果无法演示)
部分关键性代码:
a.对点击的区域进行判断,
/**
* 检测是否在区域范围内
* @param rectf 从外部传可以重用
* @param x
* @param y
* @return
*/
public boolean isInArea(RectF rectf, float x, float y) {
boolean resStatus = false;
if(this.path != null) {
rectf.setEmpty();
path.computeBounds(rectf, true);
if(isRectF) {
//当是矩形时
resStatus = rectf.contains(x, y);
}else {
//如果是多边形时
Region region = new Region();
region.setPath(path, region);
region.setPath(path, new Region((int)rectf.left, (int)rectf.top, (int)rectf.right, (int)rectf.bottom));
resStatus = region.contains((int)x, (int)y);
}
}
return resStatus;
}
b. 滑动或缩放完成后,是否移出边界检测
/**
* 边界反弹事件检测
* @param event
*/
protected void upToCheckOutOfSide(MotionEvent event) {
float scale = getCurrentScale();
float[] moveXY = getCurrentMoveXY();
float curBitWidth = scale * BIT_WIDTH;
float curBitHeight = scale * BIT_HEIGHT;
float[] dstXY = new float[2];
boolean needMove = false;
dstXY[0] = moveXY[0];
dstXY[1] = moveXY[1];
//当图片的高度小于视图高度时
if(curBitHeight <= VIEW_HEIGHT) {
needMove = true;
dstXY[1] = (VIEW_HEIGHT - curBitHeight) / 2.0f;
}
//当图片的宽度小于视图宽度时
if(curBitWidth <= VIEW_WIDTH) {
needMove = true;
dstXY[0] = (VIEW_WIDTH - curBitWidth) / 2.0f;
}
//当图片高度大于视图的高度时
if(curBitHeight > VIEW_HEIGHT) {
float distance = event.getY() - mPointF.y;
//手向下滑动
if(distance > 0) {
if(moveXY[1] > 0) {
dstXY[1] = 0;
needMove = true;
}
//手向上滑动
}else if(distance < 0) {
float goalY = VIEW_HEIGHT - curBitHeight;
if(moveXY[1] < goalY) {
dstXY[1] = goalY;
needMove = true;
}
}
}
//图片的当前宽度大小视图的高度时
if(curBitWidth > VIEW_WIDTH) {
float distance = event.getX() - mPointF.x;
//向右滑动
if(distance > 0) {
if(moveXY[0] > 0) {
dstXY[0] = 0;
needMove = true;
}
//向左滑动
}else if(distance < 0) {
float goalX = VIEW_WIDTH - curBitWidth;
if(moveXY[0] < goalX) {
dstXY[0] = goalX;
needMove = true;
}
}
}
if(needMove) {
mViewHandler.postDelayed(new MoveRunnable(moveXY[0], moveXY[1], dstXY[0], dstXY[1]), 0);
}
}
c.边界移动的Runnable
/**
* 反弹时的动画线程
*/
protected class MoveRunnable implements Runnable {
//移动的步长
private final static int MOVE_STEEP = 20;
//移动的方向
private float direct;
//是X方向上的移动还是Y方向上的移动
private boolean isMoveX;
private float srcX, srcY, dstX, dstY;
//一元一次方程
private float a, b;
public MoveRunnable(float srcX, float srcY, float dstX, float dstY) {
this.srcX = srcX;
this.srcY = srcY;
this.dstX = dstX;
this.dstY = dstY;
//求解A,B
if((dstY - srcY) != 0 && (dstX - srcX) != 0) {
a = (dstY - srcY) / (dstX - srcX);
b = dstY - a * dstX;
}
//以长的作为出发点
isMoveX = Math.abs(srcX - dstX) > Math.abs(srcY - dstY);
direct = isMoveX ? ((dstX - srcX) > 0 ? 1.0f : -1.0f) : ((dstY - srcY) > 0 ? 1.0f : -1.0f);
isAnimation = true;
}
@Override
public void run() {
float distanceX = 0;
float distanceY = 0;
boolean isEnd = false;
if(isMoveX) {
distanceX = direct * MOVE_STEEP;
srcX += distanceX;
if(direct > 0) {
if(srcX >= dstX) {
isEnd = true;
srcX -= distanceX;
distanceX = dstX - srcX;
srcX = dstX;
}
}else {
if(srcX <= dstX) {
isEnd = true;
srcX -= distanceX;
distanceX = dstX - srcX;
srcX = dstX;
}
}
if(a == 0 && b == 0) {
distanceY = 0;
}else {
float tempY = a * srcX + b;
distanceY = tempY - srcY;
srcY = tempY;
}
}else {
distanceY = direct * MOVE_STEEP;
srcY += distanceY;
if(direct > 0 ) {
if(srcY >= dstY) {
isEnd = true;
srcY -= distanceY;
distanceY = dstY - srcY;
srcY = dstY;
}
}else {
if(srcY <= dstY) {
isEnd = true;
srcY -= distanceY;
distanceY = dstY - srcY;
srcY = dstY;
}
}
if(a == 0 && b == 0 ) {
distanceX = 0;
}else {
float tempX = (srcY - b) / a;
distanceX = tempX - srcX;
srcX = tempX;
}
}
mViewHandler.obtainMessage(0, new Float[]{distanceX, distanceY}).sendToTarget();
if(!isEnd) {
mViewHandler.postDelayed(this, 10);
}else {
isAnimation = false;
LogUtils.d(TAG, isAnimation + ", End!");
}
}
}
其它的一些代码在程序中均已经做过注释