Как получить непрерывное событие Touch?

Мой класс расширяет представление, и мне нужно получать непрерывные события касания.

Если я использую:

public boolean onTouchEvent(MotionEvent me) {

    if(me.getAction()==MotionEvent.ACTION_DOWN) {
        myAction();
    }
    return true;
}

... событие касания захватывается один раз.

Что делать, если мне нужно постоянно касаться, не двигая пальцем? Пожалуйста, скажите мне, что мне не нужно использовать нити или таймеры. Мое приложение уже слишком тяжело.

Спасибо.

Ответ 1

Используйте if(me.getAction() == MotionEvent.ACTION_MOVE). Невозможно полностью держать палец на 100% полностью на экране, поэтому Action_Move будет вызываться каждый раз, когда палец перемещается, даже если он только пиксель или два.

Вы также можете прослушивать me.getAction() == MotionEvent.ACTION_UP - до тех пор, пока это не произойдет, пользователь все равно должен коснуться экрана.

Ответ 2

Вам нужно установить эти свойства для элемента       андроид: фокусируемый = "истина"       андроид: кликабельны = "истина" если нет, просто создайте действие вниз.

Ответ 3

Она - простой фрагмент кода, который показывает, как вы можете справиться с продолжающимся касанием. Когда вы касаетесь устройства и удерживаете касание и перемещаете свой искатель, выполняется действие Touch Move.

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    if(isTsunami){
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            // Write your code to perform an action on down
            break;
        case MotionEvent.ACTION_MOVE:
            // Write your code to perform an action on contineus touch move
            break;
        case MotionEvent.ACTION_UP:
            // Write your code to perform an action on touch up
            break;
    }
    }
    return true;
}

Ответ 4

Попробуйте это. Это работает для меня:

public static OnTouchListener loadContainerOnTouchListener() {
    OnTouchListener listener = new OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        LinearLayout layout = (LinearLayout)v;
        for(int i =0; i< layout.getChildCount(); i++)
        {
            View view = layout.getChildAt(i);
            Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
            if(outRect.contains((int)event.getX(), (int)event.getY()))
            {
                Log.d(this.getClass().getName(), String.format("Over view.id[%d]", view.getId()));
            }
        }

    }

Помните: слушатель, который вы установили, должен быть макетом контейнера (сетка, относительная, линейная).

LinearLayout layout = findViewById(R.id.yourlayoutid);
layout.setOnTouchListener(HelperClass.loadContainerOnTouchListener());

Ответ 5

Это может помочь,

requestDisallowInterceptTouchEvent(true);

на родительском представлении, как это -

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            view.getParent().requestDisallowInterceptTouchEvent(true);
            switch(motionEvent.getAction()){
            }

            return false; 

         }

Ответ 6

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

float x = 0, y = 0;

@Override
public boolean onTouchEvent(MotionEvent event) {
    x = event.getX();
    y = event.getY();

    // handle touch events with 
    switch( event.getActionMasked() ) {
        case MotionEvent.ACTION_DOWN :
            if(cont)
            {
                // remove any previous callbacks
                removeCallbacks(contin);

                // post new runnable
                postDelayed(contin, 10);
            }
            invalidate();
            return true;
        case MotionEvent.ACTION_MOVE :
            if(!cont && thumbing != null)
            {
                //  do non-continuous operations here
            }
            invalidate();       
            return true;
        case MotionEvent.ACTION_UP :

            // set runnable condition to false
            x = 0;

            // remove the callbacks to the thread
            removeCallbacks(contin);
            invalidate();
            return true;
        default :
            return super.onTouchEvent(event);
    }
}

public boolean cont = false;

// sets input to continuous
public void set_continuous(boolean b) { cont = b; }


public Runnable contin = new Runnable()
{

    @Override
    public void run() {
        if(x != 0)
        {
            //  do continuous operations here
            postDelayed(this, 10);
        }
    }

};

Тем не менее, убедитесь, что в вашем основном действии, вызывающем это представление, удаляются обратные вызовы вручную с помощью метода onPause следующим образом

@Override
protected void onPause() {
    if(left.cont) left.removeCallbacks(left.contin);
    if(right.cont) right.removeCallbacks(left.contin); 
    super.onPause();
}

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

** протестирован на Samsung Galaxy S3 с аппаратным ускорением на **

Ответ 7

Все эти ответы частично правильны, но они не позволяют решить проблему правильно.

Прежде всего, для всех, кто решает отслеживать, когда событие ACTION_MOVE. Хорошо, что работает только догадываться, когда? Когда пользователь перемещает свой палец, может быть, если вы решите реализовать пользовательский элемент управления большим пальцем, это нормально, но для обычной пользовательской кнопки, которая не в этом случае.

Во-вторых, использование флага внутри ACTION_DOWN и его проверка в ACTION_UP кажется логичным способом его выполнения, но поскольку Clusterfux обнаруживает, что вы реализуете логику while(!up_flag), вы застряли в проблемах;)

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

Непрерывный" Action_DOWN " в Android

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