我有一个扩展FrameLayout
并实现ScaleGestureDetector.OnScaleGestureListener
的自定义视图。正如类名所示,此视图是可缩放的+可扩展的。继承人自定义视图类:https://gist.github.com/Orbyt/23c82ce9002df6c318d4
我一直试图找到一种方法来检测此视图的长按。我知道,通常,我可以在Activity中执行类似的操作:
GestureDetector mGestureDetector = new GestureDetector(this, this);
mZoomableLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent e) {
// do tasks here
}
});
使用它,View不再可缩放,可能是因为它拦截了所有onTouch事件而不是Views类中的实现。
所以我的问题是,在这个视图中检测长按的最简洁方法是什么?
答案 0 :(得分:2)
首先,您需要使用触摸坡度来区分实际移动和无意的用户手指移动(请参阅ACTION_MOVE)。其次,如果您要延长FrameLayout
,则覆盖onTouchEvent
代替this.setOnTouchListener
中的init()
更清晰。
将变量添加到自定义视图中:
private final Handler mHandler = new Handler();
private ScaleGestureDetector mScaleDetector;
private int mTouchSlop;
private Runnable mLongPressed = new Runnable() {
public void run() {
Log.i(TAG, "Long press!");
//Do your long press stuff here.
}
};
内部init()
:
mScaleDetector = new ScaleGestureDetector(context, this);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
在switch语句中:
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//Whatever you were doing previously here
mHandler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
break;
case MotionEvent.ACTION_MOVE:
if (mode == Mode.DRAG) {
dx = motionEvent.getX() - startX;
dy = motionEvent.getY() - startY;
if(Math.abs(dx) > mTouchSlop || Math.abs(dy) > mTouchSlop) {
//Actual movement
mHandler.removeCallbacks(mLongPressed);
} else {
//Below touch slop, not a movement
dx = 0;
dy = 0;
}
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mHandler.removeCallbacks(mLongPressed);
//Whatever you were doing previously here
break;
case MotionEvent.ACTION_POINTER_UP:
mHandler.removeCallbacks(mLongPressed);
//Whatever you were doing previously here
break;
case MotionEvent.ACTION_UP:
mHandler.removeCallbacks(mLongPressed);
//Whatever you were doing previously here
break;
}
//Whatever you were doing previously here
现在所有三个功能都在运作。
如果需要长按点,请创建一个抽象类,使用浮点x和y实现Runnable
并将其填入ACTION_DOWN
,然后使用run()
中的坐标
答案 1 :(得分:2)
我有一个缩放变焦圈,我在其上检测到正常点击和长按。下面给出了代码片段。在这里,我检测到MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP之间的时间间隔长按和正常点击。
愿这对你有所帮助。
private static final int MAX_CLICK_DURATION = 200;
private float mScaleFactor = 1.0000000f;
private long mStartClickTime;
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean right = x > (screenWidthPX / 2 + ((mLayoutHeight / 4) + 20) * mScaleFactor);
boolean left = x < (screenWidthPX / 2 - ((mLayoutHeight / 4) + 20) * mScaleFactor);
boolean top = y > (mLayoutHeight / 2 + ((mLayoutHeight / 4) + 20) * mScaleFactor);
boolean bottom = y < (mLayoutHeight / 2 - ((mLayoutHeight / 4) + 20) * mScaleFactor);
if (event.getPointerCount() > 1) {
if (left || right || top || bottom) {
// You may not need this condtion, I needed this because I had custom view of pinch zoom circle and, this condition detects the touch at outer area of circle.
} else {
mScaleGestureDetector.onTouchEvent(event);
}
} else {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mStartClickTime = Calendar.getInstance().getTimeInMillis();
break;
}
case MotionEvent.ACTION_UP: {
long clickDuration = Calendar.getInstance().getTimeInMillis() - mStartClickTime;
if (clickDuration < MAX_CLICK_DURATION) {
if (left || right || top || bottom) {
} else {
Toast.makeText(mContext, "Normal CLick Detected", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mContext, "Long CLick Detected", Toast.LENGTH_SHORT).show();
}
}
}
}
return true;
}
答案 2 :(得分:1)
好的,对不起,我根本不了解你的问题。 现在进入您的MainActivity:
public yourMainConstructor()
{
[...]
GestureDetector sgd;
sgd = new GestureDetector(context,new ScaleListener());
[...]
}
class ScaleListener extends GestureDetector.SimpleOnGestureListener {
@Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
}
}
然后在主类onTouchEvent()
中覆盖@Override
public boolean onTouchEvent(MotionEvent event)
{
sgd.onTouchEvent(event);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
[...]
}
}