图片热区点击之二(边界反弹,缩放,移动)

背景:对图片的部分区域进行点击,响应相应的事件(可对图片进行放大,边界反弹,以及图片移动)

针对于前次的热区点击做了个补充

 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!");
			}
		}
	}

  其它的一些代码在程序中均已经做过注释

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值