Android捏两个手指旋转视图



我正在制作一个在照片上添加贴纸的应用程序。我把一个ImageView放在FrameLayout中,并向其中添加视图。我用两根手指拖动和缩放贴纸,使其移动,但如何用两根手指旋转整个视图。我也不需要图像在视图内部旋转,而是需要整个视图旋转。这是我的代码:

final ImageView newSticker = new ImageView(getApplicationContext());
newSticker.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,FrameLayout.LayoutParams.WRAP_CONTENT));
Bitmap sticker = BitmapFactory.decodeResource(getResources(),stickerArray.getResourceId(position,0));
newSticker.setImageBitmap(sticker);
viewGroup.addView(newSticker);
if(selectedSticker != null)
selectedSticker.setBackgroundColor(getResources().getColor(android.R.color.transparent));
selectedSticker = newSticker;
newSticker.setBackgroundResource(R.drawable.sticker_border);

newSticker.setOnTouchListener(new View.OnTouchListener()
{
PointF DownPT = new PointF();
PointF StartPT = new PointF();
float olddistance,oldrotation;
float height, width;
float oldK;
float lineA;
float m1;
@Override
public boolean onTouch(View v, MotionEvent event)
{
if(selectedSticker != null)
selectedSticker.setBackgroundColor(getResources().getColor(android.R.color.transparent));
selectedSticker = newSticker;
newSticker.setBackgroundResource(R.drawable.sticker_border);
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_MOVE :
if(event.getPointerCount() == 1)
{
float x =StartPT.x + event.getX() - DownPT.x;
float y = StartPT.y + event.getY() - DownPT.y;
newSticker.setX((int) (StartPT.x + event.getX() - DownPT.x));
newSticker.setY((int) (StartPT.y + event.getY() - DownPT.y));
Log.i("MOVE","Moved to x="+x+" and y="+y);
Log.i("MOVE","StartPT  x="+StartPT.x+"  y="+StartPT.y);
Log.i("MOVE","DownPT  x="+DownPT.x+"  y="+DownPT.y);
}
else if(event.getPointerCount() == 2)
{
newSticker.setX((int) (StartPT.x + event.getX(0) - DownPT.x));
newSticker.setY((int) (StartPT.y + event.getY(0) - DownPT.y));
final float dX =event.getX(0) - event.getX(1);
final float dY =event.getY(0) - event.getY(1);
float newdistance = (float) Math.sqrt(dX * dX + dY * dY);
float distance = newdistance - olddistance;
float newWidth = ((width+distance > 150) ? (width + distance) : 150 );
float newHeight = ((height+distance > 150) ? (height + distance) : 150 );
FrameLayout.LayoutParams lp= new FrameLayout.LayoutParams((int) (newWidth), (int) (newHeight));
newSticker.setLayoutParams(lp);


Log.i("ROTATION","dX="+dX+" dY="+dY);
double radians = Math.atan2(dY, dX);
Log.i("ROTATION","Radians="+radians);
float newRot = (float) Math.toDegrees(radians);
Log.i("ROTATION","Old Angle="+oldrotation);
Log.i("ROTATION","New Angle="+newRot);
float r = newRot - oldrotation;
Log.i("ROTATION","Rotate to="+r);
newSticker.setRotation((int) r);
Log.i("ROTATION","ROTATION SET");

}
StartPT.set( newSticker.getX(), newSticker.getY() );
Log.i("ROTATION","STARTPT SET");
break;
case MotionEvent.ACTION_DOWN :
DownPT.set(event.getX(), event.getY());
StartPT.set(newSticker.getX(), newSticker.getY());
Log.i("ACTION DOWN","DownPT x="+event.getX()+" y="+event.getY());
Log.i("ACTION DOWN","StartPT x="+newSticker.getX()+" y="+newSticker.getY());
break;
case MotionEvent.ACTION_POINTER_DOWN:
height = newSticker.getHeight();
width = newSticker.getWidth();
final float odX =event.getX(0) - event.getX(1);
final float odY =event.getY(0) - event.getY(1);
olddistance = (float) Math.sqrt(odX * odX + odY * odY);
double oldradians = Math.atan2(odY, odX);                                       
oldrotation = (float) Math.toDegrees(oradians);
oldrotation = newSticker.getRotation();
Log.i("ACTION POINTER DOWN","odX="+odX+" odY="+odY);
Log.i("ACTION POINTER DOWN","Old Rotation="+oldrotation);
break;
case MotionEvent.ACTION_POINTER_UP :
height = newSticker.getHeight();
width = newSticker.getWidth();
break;
default :
break;
}
return true;
}
});

我像这个一样解决了它

@Override
public void onClick(View v)
{
final ImageView newSticker = new ImageView(getApplicationContext());
newSticker.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,FrameLayout.LayoutParams.WRAP_CONTENT));
Bitmap sticker = BitmapFactory.decodeResource(getResources(),stickerArray.getResourceId(position,0));
newSticker.setImageBitmap(sticker);
viewGroup.addView(newSticker);
if(selectedSticker != null)
selectedSticker.setBackgroundColor(getResources().getColor(android.R.color.transparent));
selectedSticker = newSticker;
newSticker.setBackgroundResource(R.drawable.sticker_border);

newSticker.setOnTouchListener(new View.OnTouchListener()
{
float mX, mY;
float olddistance;
float height, width;
static final int INVALID_POINTER_ID = -1;
PointF mFPoint = new PointF();
PointF mSPoint = new PointF();
int mPtrID1, mPtrID2;
float mAngle;
float oldRotation;
@Override
public boolean onTouch(View v, MotionEvent event)
{
if(selectedSticker != null)
selectedSticker.setBackgroundColor(getResources().getColor(android.R.color.transparent));
selectedSticker = newSticker;
newSticker.setBackgroundResource(R.drawable.sticker_border);

switch (event.getActionMasked())
{
case MotionEvent.ACTION_MOVE :
if (mPtrID1 != INVALID_POINTER_ID && mPtrID2 != INVALID_POINTER_ID)
{
PointF nfPoint = new PointF();
PointF nsPoint = new PointF();
getRawPoint(event, mPtrID1, nsPoint,newSticker);
getRawPoint(event, mPtrID2, nfPoint,newSticker);
mAngle = angleBetweenLines(mFPoint, mSPoint, nfPoint, nsPoint);
mAngle = (mAngle+oldRotation)%360;
newSticker.setRotation(mAngle);
}

if(event.getPointerCount() == 1)
{
newSticker.animate()
.x(event.getRawX() + mX)
.y(event.getRawY() + mY)
.setDuration(0)
.start();
}
else if(event.getPointerCount() == 2)
{
final float dX =event.getX(0) - event.getX(1);
final float dY =event.getY(0) - event.getY(1);
float newdistance = (float) Math.sqrt(dX * dX + dY * dY);
float distance = newdistance - olddistance;
float newWidth = ((width+distance > 150) ? (width + distance) : 150 );
float newHeight = ((height+distance > 150) ? (height + distance) : 150 );
FrameLayout.LayoutParams lp= new FrameLayout.LayoutParams((int) (newWidth), (int) (newHeight));
newSticker.setLayoutParams(lp);
}
break;
case MotionEvent.ACTION_DOWN :
mX = newSticker.getX() - event.getRawX();
mY = newSticker.getY() - event.getRawY();
mPtrID1 = event.getPointerId(event.getActionIndex());
break;
case MotionEvent.ACTION_POINTER_DOWN:
height = newSticker.getHeight();
width = newSticker.getWidth();
final float odX =event.getX(0) - event.getX(1);
final float odY =event.getY(0) - event.getY(1);
olddistance = (float) Math.sqrt(odX * odX + odY * odY);
mPtrID2 = event.getPointerId(event.getActionIndex());
getRawPoint(event, mPtrID1, mSPoint,newSticker);
getRawPoint(event, mPtrID2, mFPoint,newSticker);
oldRotation = newSticker.getRotation();
break;
case MotionEvent.ACTION_UP:
mPtrID1 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP :
height = newSticker.getHeight();
width = newSticker.getWidth();
mPtrID2 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_CANCEL:
mPtrID1 = INVALID_POINTER_ID;
mPtrID2 = INVALID_POINTER_ID;
break;
default :
break;
}
return true;
}

最新更新