Android,可点击小部件上的手势
我的应用程序包含一个充满按钮的区域。我希望以这种方式实现该活动,即按钮区域上的快速手势会将其切换到另外两个区域之一(使用 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");
}
}
问题是:如何实现这样一个接口,它可以决定用户操作是否应被视为手势或按钮单击?
最好的问候——斯普克。
My application contains an area filled with buttons. I wish to implement the activity in such way, that fling gesture over the button area would switch it to one of two another areas (using ViewFlipper).
I've made two approaches on detecting gestures. The first one involved using GestureDetector. However, the touch motion events over the Button didn't raised the onTouchEvent activity method, so - in result - I couldn't have forwarded it to the GestureDetector class. A failure, in short.
The second approach - involved using the GestureOverlayView. This time, however, I've reached the second extreme: not only the gesture was detected, but also the button, over which gesture is performed, reported a click.
I wish the interface to work in the following way: if user touches button and releases the touch (or moves the finger only a little), the button reports click and no gesture is detected. On the other hand, if user touches the screen and makes a longer move, the gesture shall be detected and no click event reported by the button.
I've implemented a small proof-of-concept application. The activity XML code follows:
<?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>
The activity java code follows:
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");
}
}
The question is: how to implement such an interface, which can decide, if user action shall be treated as the gesture or button click?
Best regards -- Spook.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
自己解决了。这个想法是从 GestureOverlayView 捕获手势事件,除了将它们传递给 GestureDetector 之外,还测量用户手势的距离。该距离应存储在私有活动的字段中(因此可供所有事件处理程序使用)。最后,fling 和 click 处理程序应检查该字段的值;如果低于某个值(例如,10 像素即可),则应将其解释为点击。否则 - 作为一种姿态。
请注意,该按钮看起来都已被单击,并且其单击处理程序将被调用。我决定创建一个低级单击处理程序(附加到 GestureOverlayView 上的所有按钮),它执行手势/单击检查,如果结果是单击,则选择较高级别的单击处理程序之一。
该解决方案对我有用;但是,如果希望禁用按钮的单击外观并阻止调用处理程序,则可能需要重新定义按钮和/或 GestureOverlayView 组件。
Solved myself. The idea is to catch gesture events from GestureOverlayView and, apart from passing them to GestureDetector, measure the distance of user's gesture. The distance shall be stored in a private activity's field (thus available for all event handlers). Finally, fling and click handlers shall check the value of this field; if it is below certain value (say, 10 pixels shall be fine), it should be interpreted as a click. Otherwise - as a gesture.
Note, that the button will both look clicked and its click handler will be called. I've decided to create a low-level click handler (attached to all buttons over GestureOverlayView), which does the gesture/click check and if the result is a click, chooses one of higher-level click handlers.
The solution works for me; however if one wished to disable the clicked look of button and prevent the handler from being called, it would probably involve redefining the button and/or GestureOverlayView components.
另一个解决方案:
创建此函数:
并为每个 Widget 调用它,如下所示:
如果您需要从许多活动或片段中创建此函数,您可以创建一个 class.java 文件并在需要实现滑动的每个活动上实例化此类。
这会检测到任何witdget 上的滑动和点击。
希望有帮助!
anOther Solution:
Make this function:
And call it for each Widget as follows:
If you need make this from many activities or fragments, you can make a class.java file and instantiate this class on each activity you need implement the swipe.
This detects both swipe an click on any witdget.
Hope help!