【问题标题】:Android pinch two finger rotate ViewAndroid捏两指旋转视图
【发布时间】:2020-12-03 13:48:20
【问题描述】:

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

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

【问题讨论】:

    标签: android view rotation touch pinch


    【解决方案1】:

    我是这样解决的

     @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;
                            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-27
      • 2016-11-27
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      • 2012-05-24
      相关资源
      最近更新 更多