一、效果
如上图,手指头放在mExpendItemView,当手指头移动的时候,mTouchImageView随着mExpendItemView的移动而缩放和旋转
二、关键源码
private void initAttribute() {
mCenterX = mTouchImageView.getX() + mTouchImageView.getWidth() / 2;
mCenterY = mTouchImageView.getY() + mTouchImageView.getHeight() / 2;
mOriginX = mTouchImageView.getX() + mTouchImageView.getWidth()
- mCenterX;
mOriginY = mTouchImageView.getY() + mTouchImageView.getHeight()
- mCenterY;
ma1 = (float) (Math.atan2(mOriginY, mOriginX) * 180 / Math.PI);
}
private void touchExpandView(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mCorrectionX = event.getRawX() - v.getX();
mCorrectionY = event.getRawY() - v.getY();
initAttribute();
break;
case MotionEvent.ACTION_MOVE:
v.setX(getDistanceX(event));
v.setY(getDistanceY(event));
setScaleAndRotate(event);
break;
}
}
private float getDistanceX(MotionEvent event) {
return event.getRawX() - mCorrectionX;
}
private float getDistanceY(MotionEvent event) {
return event.getRawY() - mCorrectionY;
}
private void setScaleAndRotate(MotionEvent event) {
float x2 = mExpendItemView.getX() + INT_EXPAND_WIDTH / 2 - mCenterX;
float y2 = mExpendItemView.getY() + INT_EXPAND_HEIGHT / 2
- mCenterY;
float a2 = (float) (Math.atan2(y2, x2) * 180 / Math.PI);
mTouchImageView.setRotation(a2 - ma1);
float r1 = (float) Math.sqrt(mOriginX * mOriginX + mOriginY
* mOriginY);
float r2 = (float) Math.sqrt(y2 * y2 + x2 * x2);
float scale = r2 / r1;
mTouchImageView.setScaleX(scale);
mTouchImageView.setScaleY(scale);
}
入口是touchExpandView, 需要监听OnTouchListener,然后在onTouch执行touchExpandView。
三、原理
1、小图标mExpendItemView的移动
简单的数学知识:
mCorrectionX = event.getRawX() - v.getX();
这个mCorrectionX就是touch点和mTouchImageView左上角的X坐标的距离。这个值在移动的过程中是不变的。
所以,移动的时候,v的x坐标就是:
v.getX() = event.getRawX() - mCorrectionX.
就是上面代码中的函数getDistanceX
2、mTouchImageView的缩放和旋转
很重要的一点,缩放和旋转都是相对于原始大小和角度的。坐标是相对于mTouchImageView的中心点。
所以,先记录原始大小和角度:initAttribute()
缩放的倍数,就是缩放后的半径除以原始大小的半径。半径的算法就是勾股定理。
旋转的角度,就是上图的a2 - a1.
a2和a1的算法就是tan a = y / x.