我正在创建一个菜单,其中的项目必须响应两种类型的事件:
的OnClick
如果用户点击该项,则应启动一项活动。每个按钮都会启动不同的活动。OnFling
当用户从右向左滑动项目时,应显示其名称。每个项目都有不同的名称,名称将只显示 在刷过的项目中。
我尝试了很多不同的东西,在StackOverflow上搜索了许多教程和问题,但我找不到合适的答案,而且我的实现仍然很差。
我现在正在做的是为我的自定义适配器的方法OnClick
中的每个项设置getView
句柄,并在listView上设置gestureListener并处理方法onFling
,但它没有按预期行事:大多数时候我尝试滑动,手势处理为点击...
我知道我可以使用类似this的实现,但我认为我不能在这种情况下使用onTouch事件技巧,因为我需要视图位置所以我可以处理应该启动哪些活动(onTouch / click)或哪些TextView
应该可见。
以下是我到目前为止的片段:
final GestureDetector gestureDetector = new GestureDetector(
new GestureListener());
lvMenu.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(final View view, final MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return false;
}
return true;
}
});
内在阶级:
class GestureListener extends SimpleOnGestureListener {
protected MotionEvent mLastOnDownEvent = null;
@Override
public boolean onDown(final MotionEvent e) {
return true;
}
@Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2,
final float velocityX, final float velocityY) {
Log.d("OnFling", "Called");
final int SWIPE_MIN_DISTANCE = 20;
final int SWIPE_MAX_OFF_PATH = 250;
final int SWIPE_THRESHOLD_VELOCITY = 200;
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
return false;
}
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Log.i("A", "Right to Left");
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Log.i("B", "Left to Right");
}
} catch (final Exception e) {
// nothing
}
return super.onFling(e1, e2, velocityX, velocityY);
}
}
我的自定义适配器中的onClick()
方法:
public void onClick(final View v) {
Intent i = null;
switch (position) {
case 0:
i = new Intent(parent.getContext(),
ProfileActivity.class);
break;
case 1:
i = new Intent(parent.getContext(),
CatalogActivity.class);
break;
case 2:
i = new Intent(parent.getContext(), GuideActivity.class);
break;
case 3:
i = new Intent(parent.getContext(),
EventsActivity.class);
break;
default:
Log.d("MenuActivity", "Switch default case.");
break;
}
if (i != null) {
parent.getContext().startActivity(i);
}
}
谢谢:)
编辑1:现在我正在尝试将OnTouchListener设置为自定义适配器中的每个View。但它没有用......我无法弄清楚原因。
这就是我设置TouchListener的方法:
convertView.setOnTouchListener(new MenuGestureHandler() {
@Override
public boolean onSwipeRight() {
Log.d("Swipe Right", "OK!");
return true;
}
@Override
public void onClick() {
Log.d("Click", "OK!");
}
});
这是课程(有一些无用的代码,如swipeUp,swipeDown):
public class MenuGestureHandler implements OnTouchListener {
GestureDetector gestureDetector = new GestureDetector(new GestureListener());
@Override
public boolean onTouch(final View v, final MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onSingleTapConfirmed(final MotionEvent e) {
onClick(); // my method
return super.onSingleTapConfirmed(e);
}
@Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2,
final float velocityX, final float velocityY) {
boolean result = false;
try {
final float diffY = e2.getY() - e1.getY();
final float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
result = onSwipeRight();
} else {
result = onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD
&& Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
result = onSwipeBottom();
} else {
result = onSwipeTop();
}
}
}
} catch (final Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public boolean onSwipeRight() {
return false;
}
public boolean onSwipeLeft() {
return false;
}
public void onClick() {
}
public boolean onSwipeTop() {
return false;
}
public boolean onSwipeBottom() {
return false;
}
编辑2 我可以通过覆盖我的GestureListener类中的方法onDown()
并将其设置为始终返回true来使其工作。我真的不明白为什么我需要这样做,但它似乎现在正在运作!
答案 0 :(得分:4)
这里可能会考虑一些问题,但首要的是触摸事件的层次结构。
根据我收集的内容,GestureDetector
通过ListView
附加到OnTouchListener
,OnClickListener
设置在各个列表项上 - 这是儿童ListView
的观点。
由于触摸处理顺序,这是一个问题。 ListView
(实际上任何ViewGroup
)会先将触摸事件传递给其子视图,并直接处理事件 当且仅当 没有孩子时视图消耗事件。带有OnClickListener
的子视图将始终使用触摸事件,因为它会针对点击事件跟踪它们...因此您现有的滑动检测器从不(或很少)看到任何事件。
最简单的解决方案可能是避免在两个元素之间分割触摸处理。对每个处理点击(即单击)和滑动的列表项使用一个GestureDetector
- 并确保它们自己设置项目...而不是父项{{1} }}
您也可以考虑在Android Touch System上观看我的演讲,以便更详细地了解您正在处理的内容。
答案 1 :(得分:0)
我知道这是一个老问题,这是未来搜索的答案: