setOnLongClickListener не работает

Я использую стороннюю библиотеку. Это позволяет перетаскивать изображения и масштабировать их при сжатии и вращении. Я пытаюсь реализовать удаление изображения и создал метод, который удаляет изображение, на которое вы наводите палец. Теперь мне просто нужно позвонить. Единственное место, откуда я успешно его вызвал, это onDraw. В идеале я бы назвал это двойным нажатием, потому что пользователь будет долго щелкать по нему, чтобы перетащить его. Но longClick, по-видимому, проще, поэтому я сначала тестировал его. Вот мой код. Прокрутите вниз, чтобы увидеть мой setOnClickListener. Я покажу вам код класса перед setOnClickListener, чтобы дать вам некоторый контекст:

public class PhotoSortrView extends View implements MultiTouchObjectCanvas<PhotoSortrView.Img> {

        private ArrayList<Integer> mDrawables = new ArrayList<Integer>();// { R.drawable.m74hubble, R.drawable.catarina, R.drawable.tahiti, R.drawable.sunset, R.drawable.lake };

        public void addDrawable(int drawable, Context context){
            Resources res = context.getResources();
            mDrawables.add(drawable);

            mImages.add(new Img(drawable, res));
            invalidate();
        }

        private ArrayList<Img> mImages = new ArrayList<Img>();
        private AppUser user;

        // --

        private MultiTouchController<Img> multiTouchController = new MultiTouchController<Img>(this);

        // --

        private PointInfo currTouchPoint = new PointInfo();

        private boolean mShowDebugInfo = true;

        private static final int UI_MODE_ROTATE = 1, UI_MODE_ANISOTROPIC_SCALE = 2;

        private int mUIMode = UI_MODE_ROTATE;

        // --

        private Paint mLinePaintTouchPointCircle = new Paint();

        // ---------------------------------------------------------------------------------------------------

        public PhotoSortrView(Context context) {
            this(context, null);
        }

        public PhotoSortrView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }

        public PhotoSortrView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(context);
        }

        @SuppressWarnings("deprecation")
        private void init(Context context) {
            Resources res = context.getResources();
            for (int i = 0; i < mDrawables.size(); i++)
                mImages.add(new Img(mDrawables.get(i), res));

            mLinePaintTouchPointCircle.setColor(Color.YELLOW);
            mLinePaintTouchPointCircle.setStrokeWidth(5);
            mLinePaintTouchPointCircle.setStyle(Style.STROKE);
            mLinePaintTouchPointCircle.setAntiAlias(true);
            this.setLongClickable(true);

            this.setOnLongClickListener(new View.OnLongClickListener() {

                @Override
                public boolean onLongClick(View v) {
                    Toast.makeText(getContext(), "Long Clicked", Toast.LENGTH_SHORT).show();
                    Log.d("long clicking", "long clicking");
                    return true;
                }
            });
        }

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

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dressing_room);
    photoSorter = new PhotoSortrView(this);
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            this.addContentView(photoSorter, params);

Это представление, которое добавляется к этому действию, но оно имеет холст и может добавлять множество перетаскиваемых изображений. Спасибо.

ИЗМЕНИТЬ Я изменил его на

this.setOnTouchListener(new View.OnTouchListener() {

               // @Override
                //public boolean onLongClick(View v) {
                //  Toast.makeText(getContext(), "Long Clicked", Toast.LENGTH_SHORT).show();
                //  Log.d("long clicking", "long clicking");
                //    return true;
               // }

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    Toast.makeText(getContext(), "Long Clicked", Toast.LENGTH_SHORT).show();
                    Log.d("long clicking", "long clicking");
                    return false;
                }
            });
        }

И это работает. Можем ли мы перейти от этого к двойному тапу?


person user3164083    schedule 12.01.2014    source источник
comment
попробуйте mlinePaintTouchPointCircle.setOnLongClickListener....   -  person Ranjit    schedule 12.01.2014
comment
@RanjitPati Я получил ошибку, так как это не применимо для типа Paint. Спасибо хоть.   -  person user3164083    schedule 12.01.2014
comment
вы импортировали android.view.View.OnLongClickListener;?   -  person Shayan Pourvatan    schedule 12.01.2014
comment
так как у меня нет хорошего представления о графике, но все же я думаю, что в вашем контексте есть какая-то проблема.   -  person Ranjit    schedule 12.01.2014
comment
@Shayanpourvatan Я только что сделал это, и у него есть предупреждение о том, что он никогда не используется. Спасибо.   -  person user3164083    schedule 12.01.2014
comment
@RanjitPati Я только что добавил больше информации об этом классе в свой вопрос. Спасибо   -  person user3164083    schedule 12.01.2014
comment
хорошо, сделайте одну вещь. Создайте переменную контекста в вашем классе PhotoSortrView, например частный контекст контекста; и назначьте его контексту действия внутри конструкции. и используйте его с onclicklistener.   -  person Ranjit    schedule 12.01.2014
comment
@RanjitPati setOnLongClickListener не определен для типа Context. К сожалению, он просит меня преобразовать тип Context в тип View, что также не работает.   -  person user3164083    schedule 12.01.2014
comment
@RanjitPati Я обновил свой вопрос внизу :)   -  person user3164083    schedule 12.01.2014


Ответы (1)


Существует встроенный GestureDetector, способный "поймать" все обычные взаимодействия между устройством и пользователем, включая двойное касание. Однако, чтобы настроить его для одного представления или набора представлений, вам придется немного потрудиться. Сейчас я опубликую код своей тестовой активности:

public class MainActivity extends Activity implements OnClickListener {
    private GestureDetector gd;
    View.OnTouchListener otl;

    class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_SHORT).show();
            return true;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gd = new GestureDetector(this, new MyGestureDetector());
        otl = new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                return gd.onTouchEvent(event);
            }
        };
        LinearLayout cotainerView = (LinearLayout) findViewById(R.id.container);
        TextView tvNormal = new TextView(this);
        tvNormal.setText("Normal text view");
        tvNormal.setHeight(50);
        DoubleTapTextView tvDoubleTap = new DoubleTapTextView(this);
        tvDoubleTap.setText("Double tap text view");
        tvDoubleTap.setHeight(50);
        tvDoubleTap.setOnClickListener(this);
        tvDoubleTap.setOnTouchListener(otl);
        containerView.addView(tvNormal);
        containerView.addView(tvDoubleTap);
    }

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

    }

}

Таким образом, хитрость заключается в том, чтобы передать событие onTouch, а также его аргумент (MotionEvent e) вашему пользовательскому GestureListener. Таким образом, каждый жест (событие касания) будет прослушиваться, но ваш собственный прослушиватель будет выполнять метод onDoubleTap(MotionEvent e) только в случае, если жест представляет собой двойное касание. Надеюсь, вы поняли идею, стоящую за этим, и в качестве удовольствия я публикую скриншот приложения, работающего в эмуляторе, чтобы показать вам, что событие действительно перехвачено :) Снимок экрана

EDIT: вот ключевые моменты решения

  1. Activity implements OnClickListener
  2. Зарегистрируйте нужный вид как для OnClickLister, так и для OnTouchListener.

    tvDoubleTap.setOnClickListener(this); //Your activity implements OnClickListener
    tvDoubleTap.setOnTouchListener(otl); //The wrapper listener from which you call your custom one
    
  3. Внутри базового OnTouchListener передайте аргумент вашему собственному GestureListener.

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gd.onTouchEvent(event);
    }
    
  4. Внутри своего пользовательского метода GestureListener onDoubleTap(MotionEvent e) реализуйте свое решение.

    class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_SHORT).show();
            return true;
        }
    }
    

Кредиты: спасибо gav за его исследование его вопрос

person nstosic    schedule 12.01.2014
comment
Если подумать, это довольно плохое решение, я отредактирую ответ, как только приду к хорошему. - person nstosic; 12.01.2014
comment
Вы имели в виду, что я добавлю это в свой класс, реализующий двойное касание, или сделаю это совершенно новым классом? Я бы не знал, как это реализовать. Я все равно оставлю это сейчас, у вас или у кого-то еще может быть что-то лучше позже. Спасибо. - person user3164083; 12.01.2014
comment
Я отредактирую его позже (примерно через час-два) с полным решением - person nstosic; 12.01.2014
comment
Извините, что это заняло так много времени. У меня было сбой подключения к Интернету, и у меня тоже :) В любом случае, я собираюсь отредактировать ответ довольно странным, но работающим решением. - person nstosic; 12.01.2014
comment
Большое спасибо! Я собираюсь попробовать это. Знаете ли вы, почему для его работы требуется довольно много кода? Никто больше не ответил, так что это был не просто очевидный небольшой блок кода. Это всегда так в Android или моя настройка просто неудобна для этого прослушивателя событий? - person user3164083; 13.01.2014
comment
Оно работает! Спасибо! Очень подробный и понятный ответ с акцентом на ключевые моменты. - person user3164083; 13.01.2014