Android, жесты над кликабельными виджетами - PullRequest
8 голосов
/ 21 апреля 2011

Мое приложение содержит область, заполненную кнопками. Я хочу реализовать действие таким образом, чтобы жест перетаскивания над областью кнопки переключал его на одну из двух других областей (используя ViewFlipper).

Я сделал два подхода к обнаружению жестов. Первый связан с использованием GestureDetector. Однако события сенсорного движения над кнопкой не вызвали метод действия onTouchEvent, поэтому в результате я не смог переслать его в класс GestureDetector. Короче говоря, отказ.

Второй подход - использование GestureOverlayView. На этот раз, однако, я достиг второй крайности: не только жест был обнаружен, но и кнопка, над которой выполняется жест, сообщила о щелчке.

Мне бы хотелось, чтобы интерфейс работал следующим образом: если пользователь касается кнопки и отпускает прикосновение (или слегка перемещает палец), кнопка сообщает о щелчке, и жест не обнаруживается. С другой стороны, если пользователь касается экрана и делает более длинный ход, жест должен быть обнаружен, и кнопка не сообщает о событии щелчка.

Я реализовал небольшое приложение для проверки концепции. Код активности XML следующий:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"  xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical">
  <android.gesture.GestureOverlayView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/overlay">
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
    <TextView android:id="@+id/display" android:layout_width="match_parent" android:layout_height="wrap_content" />
    <Button android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/button"/>
    </LinearLayout>
  </android.gesture.GestureOverlayView>
</LinearLayout>

Ниже приведен код активности Java:

package spk.sketchbook;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.gesture.*;
import android.gesture.GestureOverlayView.OnGestureListener;

public class Main extends Activity implements OnGestureListener, OnClickListener
{       
  private void SetupEvents()
  {
    GestureOverlayView ov = (GestureOverlayView)findViewById(R.id.overlay);
    ov.addOnGestureListener(this);

    Button b = (Button)findViewById(R.id.button);
    b.setOnClickListener(this);
  }

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    SetupEvents();
  }

  @Override
  public void onGesture(GestureOverlayView arg0, MotionEvent arg1)
  {
    TextView tv = (TextView)findViewById(R.id.display);
    tv.setText("Gesture");
  }

  @Override
  public void onGestureCancelled(GestureOverlayView arg0, MotionEvent arg1)
  {

  }

  @Override
  public void onGestureEnded(GestureOverlayView overlay, MotionEvent event)
  {

  }

  @Override
  public void onGestureStarted(GestureOverlayView overlay, MotionEvent event)
  {

  }

  @Override
  public void onClick(View v)
  {
    TextView tv = (TextView)findViewById(R.id.display);
    tv.setText("Click");
  }


}

Вопрос в том, как реализовать такой интерфейс, который может решить, будет ли действие пользователя рассматриваться как жест или нажатие кнопки?

С наилучшими пожеланиями - Spook.

Ответы [ 2 ]

3 голосов
/ 09 мая 2011

решил сам.Идея состоит в том, чтобы отлавливать события жестов из GestureOverlayView и, помимо передачи их в GestureDetector, измерять расстояние жеста пользователя.Расстояние должно быть сохранено в поле частного действия (таким образом, доступно для всех обработчиков событий).Наконец, обработчики fling и click должны проверить значение этого поля;если оно ниже определенного значения (скажем, 10 пикселей должно быть в порядке), его следует интерпретировать как щелчок.В противном случае - как жест.

Обратите внимание, что кнопка будет выглядеть как нажатая, и будет вызван ее обработчик нажатия.Я решил создать низкоуровневый обработчик щелчков (прикрепленный ко всем кнопкам над GestureOverlayView), который выполняет проверку жестов / щелчков и, если результатом является щелчок, выбирает один из высокоуровневых обработчиков кликов.* Решение работает для меня;однако, если кто-то хочет отключить нажатие кнопки и предотвратить вызов обработчика, это, вероятно, потребует переопределения кнопки и / или компонентов GestureOverlayView.

2 голосов
/ 21 июля 2012

другое решение: Сделайте эту функцию:

public void SetSwipe(View v, final GestureDetector gestureScanner){
    // Sets scroll view listener
    v.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
              if (gestureScanner.onTouchEvent(event))  
                return true;  
              else  
                return false;  
        }
    });
}

И назовите его для каждого виджета следующим образом:

scfSetTag.SetSwipe(svAllView, gestureScanner);

Если вам нужно сделать это из множества действий или фрагментов, вы можете создать файл class.java и создать экземпляр этого класса для каждого действия, в котором вам нужно реализовать свайп. Это обнаруживает, как проведите одним щелчком мыши по любому остроумию. Надеюсь, помощь!

...