8

我的应用程序包含一个充满按钮的区域。我希望以这种方式实现活动,在按钮区域上挥动手势会将其切换到另外两个区域之一(使用 ViewFlipper)。

我已经提出了两种检测手势的方法。第一个涉及使用 GestureDetector。但是,Button 上的触摸运动事件并没有引发 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");
  }


}

问题是:如何实现这样一个界面,它可以决定用户动作是手势还是按钮点击?

最好的问候——幽灵。

4

2 回答 2

3

自己解决了。这个想法是从 GestureOverlayView 捕获手势事件,除了将它们传递给 GestureDetector 之外,还测量用户手势的距离。距离应存储在私有活动的字段中(因此可用于所有事件处理程序)。最后,fling 和 click 处理程序将检查该字段的值;如果它低于某个值(比如说,10 像素应该没问题),它应该被解释为点击。否则 - 作为一种姿态。

请注意,该按钮看起来已被单击,并且将调用其单击处理程序。我决定创建一个低级别的单击处理程序(附加到 GestureOverlayView 上的所有按钮),它会执行手势/单击检查,如果结果是单击,则选择更高级别的单击处理程序之一。

该解决方案对我有用;但是,如果希望禁用按钮的单击外观并阻止调用处理程序,则可能涉及重新定义按钮和/或 GestureOverlayView 组件。

于 2011-05-09T11:54:12.403 回答
2

另一个解决方案:制作此功能:

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

并为每个 Widget 调用它,如下所示:

scfSetTag.SetSwipe(svAllView, gestureScanner);

如果您需要从许多活动或片段中进行此操作,则可以创建一个 class.java 文件并在您需要实现滑动的每个活动上实例化此类。这会检测到在任何witdget上都滑动点击。希望有所帮助!

于 2012-07-21T18:21:35.453 回答