2016-06-07 3 views
3

у меня есть дни, пытаясь сделать эту работу, проверили некоторые другие ответы и никто, кажется, работает для меня: SMove, Scale и Rotate ImageView OnTouch не работает

я добавить наклейку на RelativeLayout, я хочу, стикер для перемещения, масштабирования и поворота с помощью методов OnTouch после его выбора (у него есть OnClickListener, который вызывает setOnTouchListener) , имея в виду, что я могу добавить наклейки N.

private void addSticker(ImageView sticker) 
{ 

    flMemeFrame.addView(sticker); 

    sticker.setOnClickListener(new View.OnClickListener() 
    { 
     @Override 
     public void onClick(View v) 
     { 
      { 
       if (selectedView != null) 
       { 
        CancelSelection(selectedView); 
       } 
       selectedView = v; 

       v.setOnTouchListener(new View.OnTouchListener() 
       { 
        private float mScaleFactor = 0.5f; 
        private float mRotationDegree = 0.f; 
        private float mFocusX = 0.f; 
        private float mFocusY = 0.f; 
        private int mScreenHeight; 
        private int mScreenWidth; 
        private Matrix matrix = new Matrix();//Các lớp Matrix giữ một ma trận 3x3 để di chuyển tọa độ. 
        private int mImageWidth, mImageHeight; 
        private ScaleGestureDetector mScaleDetector; 
        private RotateGestureDetector mRotateDetector; 
        private MoveGestureDetector mMoveDetector; 

        class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
         @Override 
         public boolean onScale(ScaleGestureDetector detector) { 
          mScaleFactor *= detector.getScaleFactor(); 
          mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 1.0f)); 
          return true; 
         } 
        } 

        class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener { 
         @Override 
         public boolean onRotate(RotateGestureDetector detector) { 
          mRotationDegree -= detector.getRotationDegreesDelta(); 
          return true; 
         } 
        } 

        class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener { 
         @Override 
         public boolean onMove(MoveGestureDetector detector) { 
          PointF d = detector.getFocusDelta(); 
          mFocusX += d.x; 
          mFocusY += d.y; 

          return true; 
         } 
        } 
        @Override 
        public boolean onTouch(View v, MotionEvent event) 
        { 
         mImageHeight = v.getHeight(); 
         mImageWidth = v.getWidth(); 

         mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
         mRotateDetector = new RotateGestureDetector(context, new RotateListener()); 
         mMoveDetector = new MoveGestureDetector(context, new MoveListener()); 

         mScaleDetector.onTouchEvent(event); 
         mRotateDetector.onTouchEvent(event); 
         mMoveDetector.onTouchEvent(event); 
         float scaleImageCenterX = (mImageWidth * mScaleFactor)/2; 
         float scaleImageCenterY = (mImageHeight * mScaleFactor)/2; 

         matrix.reset(); 
         matrix.postScale(mScaleFactor, mScaleFactor); 
         matrix.postRotate(mRotationDegree, scaleImageCenterX, scaleImageCenterY); 
         matrix.postTranslate(mFocusX - scaleImageCenterX, mFocusY - scaleImageCenterY); 

         ImageView view = (ImageView) v; 
         view.setScaleType(ImageView.ScaleType.MATRIX); 
         view.setImageMatrix(matrix); 

         return true; 
        } 
       }); 
      } 
     } 
    }); 
} 

здесь, где я установить изображение

ImageView sticker = new ImageView(context); 
       RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT); 
       rlp.addRule(RelativeLayout.CENTER_IN_PARENT); 
       sticker.setLayoutParams(rlp); 
addSticker(sticker); 

в приложение компилируется и не падает, но наклейка не делает OnTouch :(

ссылки, которые я пробовал:

http://code.almeros.com/android-multitouch-gesture-detectors#.V1Y0sZMrLMW

rotation and scaling and move using multi touch in android

и некоторые другие ссылки, которые я не могу найти сейчас

Кто может помочь?

EDIT: код CancelSelection (полностью не связанный, поскольку единственное, что я делаю, это установить selectedView как null и удалить фон, я также удалю OnTouchListener, потому что я не хочу перемещать/масштабировать/вращать вид, если он не выбран)

@SuppressWarnings("deprecation") 
public void CancelSelection(View v) 
{ 
    if(isCaptionEditPanelOpen) 
    { 
     rlQuickEdit.setVisibility(View.GONE); 
     rlQuickEdit = null; 
     isCaptionEditPanelOpen = false; 
    } 
    //toogleButtonVisibility(false); 
    v.setBackgroundColor(getResources().getColor(android.R.color.transparent)); 
    selectedView = null; 
    v.setOnTouchListener(null); 
} 

я написал этот класс, чтобы увидеть, если я могу заставить его работать без всей сложности моего приложения, такие же результаты:

package com.andujardev.imagerotation; 

import android.content.Context; 
import android.graphics.Matrix; 
import android.graphics.PointF; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
import android.view.View; 
import android.widget.ImageView; 

public class MainActivity extends AppCompatActivity 
{ 
    Context context; 
    ImageView imgRotate; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     context = this; 

     imgRotate = (ImageView) findViewById(R.id.imgRotate); 

     imgRotate.setOnTouchListener(new View.OnTouchListener() 
     { 
      private float mScaleFactor = 0.5f; 
      private float mRotationDegree = 0.f; 
      private float mFocusX = 0.f; 
      private float mFocusY = 0.f; 
      private int mScreenHeight; 
      private int mScreenWidth; 
      private Matrix matrix = new Matrix(); 
      private int mImageWidth, mImageHeight; 
      private ScaleGestureDetector mScaleDetector; 
      private RotateGestureDetector mRotateDetector; 
      private MoveGestureDetector mMoveDetector; 

      class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
       @Override 
       public boolean onScale(ScaleGestureDetector detector) { 
        mScaleFactor *= detector.getScaleFactor(); 
        mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 1.0f)); 
        return true; 
       } 
      } 

      class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener { 
       @Override 
       public boolean onRotate(RotateGestureDetector detector) { 
        mRotationDegree -= detector.getRotationDegreesDelta(); 
        return true; 
       } 
      } 

      class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener { 
       @Override 
       public boolean onMove(MoveGestureDetector detector) { 
        PointF d = detector.getFocusDelta(); 
        mFocusX += d.x; 
        mFocusY += d.y; 

        return true; 
       } 
      } 
      @Override 
      public boolean onTouch(View v, MotionEvent event) 
      { 
       mImageHeight = v.getHeight(); 
       mImageWidth = v.getWidth(); 

       mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
       mRotateDetector = new RotateGestureDetector(context, new RotateListener()); 
       mMoveDetector = new MoveGestureDetector(context, new MoveListener()); 

       mScaleDetector.onTouchEvent(event); 
       mRotateDetector.onTouchEvent(event); 
       mMoveDetector.onTouchEvent(event); 
       float scaleImageCenterX = (mImageWidth * mScaleFactor)/2; 
       float scaleImageCenterY = (mImageHeight * mScaleFactor)/2; 

       matrix.reset(); 
       matrix.postScale(mScaleFactor, mScaleFactor); 
       matrix.postRotate(mRotationDegree, scaleImageCenterX, scaleImageCenterY); 
       matrix.postTranslate(mFocusX - scaleImageCenterX, mFocusY - scaleImageCenterY); 

       ImageView view = (ImageView) v; 
       view.setImageMatrix(matrix); 

       return true; 
      } 
     }); 
    } 
} 
+0

Прежде всего, вы не понимаете работу жестов. Ниже приведен правильный ответ с вашим кодом, потому что с помощью touch это не то же самое, что и щелчок. Подробнее о любом жесте в Google Doc. – GensaGames

+0

Это не так, я просто нажимаю жесты на конкретный элемент, когда пользователь выбрал его с помощью ClickListener, когда TouchListener активен, прослушиватель кликов не вызывается, когда пользователь нажимает кнопку OUTSIDE, изображение не выбирается, и вы can not использовать жесты на нем –

+0

Еще одна важная вещь в том, что я создал другой проект, использовал код Gestures (без всякой сложности моего приложения), и он тоже не работает ... –

ответ

1

Попробуйте ..следующие причина, указанная выше код не работает, потому что TouchListener и Cli ckListener не могут работать вместе в вышеприведенном situation..Click требует, чтобы вы касаетесь, а затем покинуть Вид на события в occur.However сенсорное событие требует, чтобы вы все еще коснувшись View ...

private void addSticker(ImageView sticker) 
{ 

flMemeFrame.addView(sticker); 

sticker.setOnTouchListener(new View.OnTouchListener() 
      { 
       private float mScaleFactor = 0.5f; 
       private float mRotationDegree = 0.f; 
       private float mFocusX = 0.f; 
       private float mFocusY = 0.f; 
       private int mScreenHeight; 
       private int mScreenWidth; 
       private Matrix matrix = new Matrix();//Các lớp Matrix giữ một ma trận 3x3 để di chuyển tọa độ. 
       private int mImageWidth, mImageHeight; 
       private ScaleGestureDetector mScaleDetector; 
       private RotateGestureDetector mRotateDetector; 
       private MoveGestureDetector mMoveDetector; 

       class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
        @Override 
        public boolean onScale(ScaleGestureDetector detector) { 
         mScaleFactor *= detector.getScaleFactor(); 
         mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 1.0f)); 
         return true; 
        } 
       } 

       class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener { 
        @Override 
        public boolean onRotate(RotateGestureDetector detector) { 
         mRotationDegree -= detector.getRotationDegreesDelta(); 
         return true; 
        } 
       } 

       class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener { 
        @Override 
        public boolean onMove(MoveGestureDetector detector) { 
         PointF d = detector.getFocusDelta(); 
         mFocusX += d.x; 
         mFocusY += d.y; 

         return true; 
        } 
       } 
       @Override 
       public boolean onTouch(View v, MotionEvent event) 
       { 
        mImageHeight = v.getHeight(); 
        mImageWidth = v.getWidth(); 

        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
        mRotateDetector = new RotateGestureDetector(context, new RotateListener()); 
        mMoveDetector = new MoveGestureDetector(context, new MoveListener()); 

        mScaleDetector.onTouchEvent(event); 
        mRotateDetector.onTouchEvent(event); 
        mMoveDetector.onTouchEvent(event); 
        float scaleImageCenterX = (mImageWidth * mScaleFactor)/2; 
        float scaleImageCenterY = (mImageHeight * mScaleFactor)/2; 

        matrix.reset(); 
        matrix.postScale(mScaleFactor, mScaleFactor); 
        matrix.postRotate(mRotationDegree, scaleImageCenterX, scaleImageCenterY); 
        matrix.postTranslate(mFocusX - scaleImageCenterX, mFocusY - scaleImageCenterY); 

        ImageView view = (ImageView) v; 
        view.setScaleType(ImageView.ScaleType.MATRIX); 
        view.setImageMatrix(matrix); 

        return true; 
       } 
      }); 
     } 
    } 
+0

вы могли слушать DOWN и UP Touch Events для обработки эффекта DRAG, который вы хотите. –

+0

Причина, по которой я делаю это, это то, что я фактически активирую сенсорные функции, когда я нажимаю на изображение, как если бы я сначала выбрал изображение, а затем начал его манипулировать, когда я покидаю затем вернитесь к нормальным функциям щелчка. –

+0

Не могли бы вы опубликовать код для cancelSelection .. –

2

Это интересно что для каждыйonTouch событие, которое вы создаете новый ScaleGestureDetector, RotateGestureDetector и MoveGestureDetector.

Принимая во внимание каждый, соответствующий детектив жестов нуждается в предыдущем событии касания, чтобы определить и интерпретировать, как реагировать, это, безусловно, значительная часть проблемы, поскольку вы создаете новый детектор жестов для каждого события касания. На самом деле, если вы посмотрите в источнике для Almeros детектора для onTouchEvent(MotionEvent ev) метода он гласит:

Applications should pass a complete and consistent event stream to this method. 
* A complete and consistent event stream involves all MotionEvents from the initial 
* ACTION_DOWN to the final ACTION_UP or ACTION_CANCEL. 

Для начала вы должны убедиться, что вы только создание одного объекта детектора, поэтому он может потреблять все сенсорные события.

+0

Я уже нашел решение, это было одним из проблемы, но у меня не было хорошего объяснения, спасибо! другая проблема заключалась в том, что изображение было установлено на WRAP_CONTENT, и этот код не перемещает/масштабирует/не поворачивает ImageView, а Drawable в imageView, поэтому ImageView должен быть MATCH_PARENT, и это приводит меня к большей проблеме. я могу только отредактировать последнее добавленное изображение ... (Он принимает ImageView как матрицу, поэтому масштабирует и вращает в этой матрице, я хочу, чтобы матрица была моей FrameLayout, но я не знаю, как это изменить) –

+0

хорошо, период баунти закончился, и до сих пор вы были единственными, кто попал в один из пунктов, поэтому я награжу вас щедростью, однако моя проблема не совсем (или полностью) решена. –